/******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ 755:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "addonName": () => (/* binding */ addonName),
/* harmony export */   "addonVersion": () => (/* binding */ addonVersion),
/* harmony export */   "application": () => (/* binding */ application),
/* harmony export */   "applicationVersion": () => (/* binding */ applicationVersion),
/* harmony export */   "baseName": () => (/* binding */ baseName),
/* harmony export */   "platform": () => (/* binding */ platform),
/* harmony export */   "platformVersion": () => (/* binding */ platformVersion)
/* harmony export */ });
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

let addonName = "adblockchrome";
let baseName = "adblock";
let addonVersion = "5.9.0";
let application = null;
let applicationVersion;
let platform = "chromium";
let platformVersion = null;

let regexp = /(\S+)\/(\S+)(?:\s*\(.*?\))?/g;
let match;

while (match = regexp.exec(navigator.userAgent))
{
  let app = match[1];
  let ver = match[2];

  if (app == "Chrome")
  {
    platformVersion = ver;
  }
  else if (app != "Mozilla" && app != "AppleWebKit" && app != "Safari")
  {
    // For compatibility with legacy websites, Chrome's UA
    // also includes a Mozilla, AppleWebKit and Safari token.
    // Any further name/version pair indicates a fork.
    application = app == "OPR" ? "opera" : app.toLowerCase();
    applicationVersion = ver;
  }
}

// not a Chromium-based UA, probably modifed by the user
if (!platformVersion)
{
  application = "unknown";
  applicationVersion = platformVersion = "0";
}

// no additional name/version, so this is upstream Chrome
if (!application)
{
  application = "chrome";
  applicationVersion = platformVersion;
}


/***/ }),

/***/ 7269:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "addonName": () => (/* binding */ addonName),
/* harmony export */   "addonVersion": () => (/* binding */ addonVersion),
/* harmony export */   "application": () => (/* binding */ application),
/* harmony export */   "applicationVersion": () => (/* binding */ applicationVersion),
/* harmony export */   "platform": () => (/* binding */ platform),
/* harmony export */   "platformVersion": () => (/* binding */ platformVersion)
/* harmony export */ });
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

let addonName = "adblockchrome";
let addonVersion = "5.9.0";
let application = null;
let applicationVersion;
let platform = "chromium";
let platformVersion = null;

let regexp = /(\S+)\/(\S+)(?:\s*\(.*?\))?/g;
let match;

while (match = regexp.exec(navigator.userAgent))
{
  let app = match[1];
  let ver = match[2];

  if (app == "Chrome")
  {
    platformVersion = ver;
  }
  // For compatibility with legacy websites, Chrome's UA
  // also includes a Mozilla, AppleWebKit and Safari token.
  // Any further name/version pair indicates a fork.
  else if (app != "Mozilla" && app != "AppleWebKit" && app != "Safari")
  {
    if (app == "Edg")
      application = "edge";
    else if (app == "OPR")
      application = "opera";
    else
      application = app.toLowerCase();

    applicationVersion = ver;
  }
}

// not a Chromium-based UA, probably modifed by the user
if (!platformVersion)
{
  application = "unknown";
  applicationVersion = platformVersion = "0";
}

// no additional name/version, so this is upstream Chrome
if (!application)
{
  application = "chrome";
  applicationVersion = platformVersion;
}


/***/ }),

/***/ 7590:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
;// CONCATENATED MODULE: ./node_modules/@eyeo/snippets/webext/ml.mjs
/*!
 * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets),
 * Copyright (C) 2006-present eyeo GmbH
 * 
 * @eyeo/snippets is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 * 
 * @eyeo/snippets is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with @eyeo/snippets.  If not, see <http://www.gnu.org/licenses/>.
 */

const callback = (environment, ...filters) => {
const t=Proxy,{apply:e,bind:i,call:s}=Function,o=s.bind(e),r=s.bind(i),u=s.bind(s),a={get:(t,e)=>r(s,t[e])},n=e=>new t(e,a),L={get:(t,e)=>r(t[e],t)},M=e=>new t(e,L),{assign:C,defineProperties:w,freeze:y,getOwnPropertyDescriptor:v,getOwnPropertyDescriptors:D,getPrototypeOf:l}=M(Object),{hasOwnProperty:g}=n({}),{species:p}=Symbol,j={get(t,e){const i=t[e];class s extends i{}const o=D(i.prototype);delete o.constructor,y(w(s.prototype,o));const r=D(i);return delete r.length,delete r.prototype,r[p]={value:s},y(w(s,r))}},A=e=>new t(e,j),c="undefined"!=typeof environment?environment:{};"undefined"==typeof globalThis&&(window.globalThis=window);const{apply:I,ownKeys:m}=M(Reflect),h="world"in c,O=h&&"ISOLATED"===c.world,z=h&&"MAIN"===c.world,x="object"==typeof chrome&&!!chrome.runtime,d="object"==typeof browser&&!!browser.runtime,K=!z&&(O||x||d),P=t=>K?t:Y(t,S(t)),{create:Y,defineProperties:Q,defineProperty:b,freeze:E,getOwnPropertyDescriptor:T,getOwnPropertyDescriptors:S}=M(Object),f=M(globalThis),q=K?globalThis:A(globalThis),{Map:k,RegExp:G,Set:N,WeakMap:B,WeakSet:U}=q,J=(t,e,i=null)=>{const s=m(e);for(const o of m(t)){if(s.includes(o))continue;const r=T(t,o);if(i&&"value"in r){const{value:t}=r;"function"==typeof t&&(r.value=i(t))}b(e,o,r)}},W=t=>{const e=q[t];class i extends e{}const{toString:s,valueOf:o}=e.prototype;Q(i.prototype,{toString:{value:s},valueOf:{value:o}});const r=t.toLowerCase(),u=t=>function(){const e=I(t,this,arguments);return typeof e===r?new i(e):e};return J(e,i,u),J(e.prototype,i.prototype,u),i},F=E({frozen:new B,hidden:new U,iframePropertiesToAbort:{read:new N,write:new N},abortedIframes:new B}),R=new G("^[A-Z]");var H=new Proxy(new k([["chrome",K&&(x&&chrome||d&&browser)||void 0],["isExtensionContext",K],["variables",F],["console",P(console)],["document",globalThis.document],["performance",P(performance)],["JSON",P(JSON)],["Map",k],["Math",P(Math)],["Number",K?Number:W("Number")],["RegExp",G],["Set",N],["String",K?String:W("String")],["WeakMap",B],["WeakSet",U],["MouseEvent",MouseEvent]]),{get(t,e){if(t.has(e))return t.get(e);let i=globalThis[e];return"function"==typeof i&&(i=(R.test(e)?q:f)[e]),t.set(e,i),i},has:(t,e)=>t.has(e)});const V={WeakSet:WeakSet,WeakMap:WeakMap,WeakValue:class{has(){return!1}set(){}}},{apply:Z}=Reflect;const{Map:X,WeakMap:_,WeakSet:$,setTimeout:tt}=H;let et=!0,it=t=>{t.clear(),et=!et};var st=function(t){const{WeakSet:e,WeakMap:i,WeakValue:s}=this||V,o=new e,r=new i,u=new s;return function(e){if(o.has(e))return e;if(r.has(e))return r.get(e);if(u.has(e))return u.get(e);const i=Z(t,this,arguments);return o.add(i),i!==e&&("object"==typeof e&&e?r:u).set(e,i),i}}.bind({WeakMap:_,WeakSet:$,WeakValue:class extends X{set(t,e){return et&&(et=!et,tt(it,0,this)),super.set(t,e)}}});const{concat:ot,includes:rt,join:ut,reduce:at,unshift:nt}=n([]),Lt=A(globalThis),{Map:Mt,WeakMap:Ct}=Lt,wt=new Mt,yt=e=>{const i=(t=>{const e=[];let i=t;for(;i;){if(wt.has(i))nt(e,wt.get(i));else{const t=D(i);wt.set(i,t),nt(e,t)}i=l(i)}return nt(e,{}),o(C,null,e)})("function"==typeof e?e.prototype:e),s={get(t,e){if(e in i){const{value:s,get:o}=i[e];if(o)return u(o,t);if("function"==typeof s)return r(s,t)}return t[e]},set(t,e,s){if(e in i){const{set:o}=i[e];if(o)return u(o,t,s),!0}return t[e]=s,!0}};return e=>new t(e,s)},{isExtensionContext:vt,Array:Dt,Number:lt,String:gt,Object:pt}=H,{isArray:jt}=Dt,{getOwnPropertyDescriptor:At,setPrototypeOf:ct}=pt,{toString:It}=pt.prototype,{slice:mt}=gt.prototype,{get:ht}=At(Node.prototype,"nodeType"),Ot=vt?{}:{Attr:yt(Attr),CanvasRenderingContext2D:yt(CanvasRenderingContext2D),CSSStyleDeclaration:yt(CSSStyleDeclaration),Document:yt(Document),Element:yt(Element),HTMLCanvasElement:yt(HTMLCanvasElement),HTMLElement:yt(HTMLElement),HTMLImageElement:yt(HTMLImageElement),HTMLScriptElement:yt(HTMLScriptElement),MutationRecord:yt(MutationRecord),Node:yt(Node),ShadowRoot:yt(ShadowRoot),get CSS2Properties(){return Ot.CSSStyleDeclaration}},zt=(t,e)=>{if("Element"!==e&&e in Ot)return Ot[e](t);if(jt(t))return ct(t,Dt.prototype);const i=(t=>u(mt,u(It,t),8,-1))(t);if(i in Ot)return Ot[i](t);if(i in H)return ct(t,H[i].prototype);if("nodeType"in t)switch(u(ht,t)){case 1:if(!(e in Ot))throw new Error("unknown hint "+e);return Ot[e](t);case 2:return Ot.Attr(t);case 3:return Ot.Node(t);case 9:return Ot.Document(t)}throw new Error("unknown brand "+i)};var xt=vt?t=>t===window||t===globalThis?H:t:st(((t,e="Element")=>{if(t===window||t===globalThis)return H;switch(typeof t){case"object":return t&&zt(t,e);case"string":return new gt(t);case"number":return new lt(t);default:throw new Error("unsupported value")}}));let{document:dt,getComputedStyle:Kt,isExtensionContext:Pt,variables:Yt,Array:Qt,MutationObserver:bt,Object:Et,XPathEvaluator:Tt,XPathExpression:St,XPathResult:ft}=xt(window),{querySelectorAll:qt}=dt,kt=qt&&r(qt,dt);const{assign:Gt,setPrototypeOf:Nt}=Et;class Bt extends St{evaluate(...t){return Nt(o(super.evaluate,this,t),ft.prototype)}}class Ut extends Tt{createExpression(...t){return Nt(o(super.createExpression,this,t),Bt.prototype)}}function Jt(t){if(Yt.hidden.has(t))return;!function(t){Pt&&"function"==typeof checkElement&&checkElement(t)}(t),Yt.hidden.add(t);let{style:e}=xt(t),i=xt(e,"CSSStyleDeclaration"),s=xt([]),{debugCSSProperties:o}=c;for(let[t,e]of o||[["display","none"]])i.setProperty(t,e,"important"),s.push([t,i.getPropertyValue(t)]);new bt((()=>{for(let[t,e]of s){let s=i.getPropertyValue(t),o=i.getPropertyPriority(t);s==e&&"important"==o||i.setProperty(t,e,"important")}})).observe(t,{attributes:!0,attributeFilter:["style"]})}function Wt(t){let e=t;if(e.startsWith("xpath(")&&e.endsWith(")")){let t=e.slice(6,-1),i=(new Ut).createExpression(t,null),s=ft.ORDERED_NODE_SNAPSHOT_TYPE;return t=>{if(!t)return;let e=i.evaluate(dt,s,null),{snapshotLength:o}=e;for(let i=0;i<o;i++)t(e.snapshotItem(i))}}return e=>kt(t).forEach(e)}function Ft(t,e,i,s){let o;null==i&&(i=e);const r=()=>{for(const r of kt(i)){const i=xt(r).closest(e);i&&t(r,i)&&(o(),Jt(i),"function"==typeof s&&s(i))}};return Gt(new bt(r),{race(t){o=t,this.observe(dt,{childList:!0,characterData:!0,subtree:!0}),r()}})}function Rt(t,e,i){let s=xt(e,"CSSStyleDeclaration");if("none"==s.getPropertyValue("display"))return!1;let o=s.getPropertyValue("visibility");if("hidden"==o||"collapse"==o)return!1;if(!i||t==i)return!0;let r=xt(t).parentElement;return!r||Rt(r,Kt(r),i)}function Ht(t){let e=Kt(t),{cssText:i}=e;if(i)return i;for(let t of e)i+=`${t}: ${e[t]}; `;return xt(i).trim()}let{Math:Vt,RegExp:Zt}=xt(window);function Xt(t){let{length:e}=t;if(e>1&&"/"===t[0]){let i="/"===t[e-1];if(i||e>2&&xt(t).endsWith("/i")){let e=[xt(t).slice(1,i?-1:-2)];return i||e.push("i"),new Zt(...e)}}return new Zt(xt(t).replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))}let _t=!1;function $t(){return _t}const{console:te}=xt(window),ee=()=>{};function ie(...t){$t()&&xt(t).unshift("%c DEBUG","font-weight: bold"),te.log(...t)}function se(t){return r($t()?ie:ee,null,t)}let{Array:oe,Error:re,Map:ue,parseInt:ae}=xt(window),ne=null,Le=null;function Me(t,e){if(null===ne)return ee;let i=ne,{participants:s}=i;return s.set(o,e),o;function o(){if(i.winners<1)return;if(se("race")(`${t} won the race`),i===ne)Le.push(o);else if(s.delete(o),--i.winners<1){for(let t of s.values())t();s.clear()}}}const Ce={get(t,e){const i=t;for(;!g(t,e);)t=l(t);const{get:s,set:r}=v(t,e);return function(){return arguments.length?o(r,i,arguments):u(s,i)}}};var we;function ye(t,e,i){var s,o;i?"load"===i?(t("Waiting until window.load"),window.onload=()=>{t("Window.load fired."),e()}):"loading"===i||"interactive"===i||"complete"===i?(t("Waiting document state until :",i),document.onreadystatechange=()=>{t("Document state changed:",document.readyState),document.readyState===i&&e()}):(t("Waiting until ",i," event is triggered on document"),(s=document,o=i,new Promise((t=>{const e=()=>{s.removeEventListener(o,e),t()};s.addEventListener(o,e)}))).then((()=>{t(i," is triggered on document, starting the snippet"),e()})).catch((e=>{t("There was an error while waiting for the event.",e)}))):e()}xt(window),we=window,new t(we,Ce),xt(/^\d+$/);let{MutationObserver:ve,WeakSet:De,getComputedStyle:le}=xt(window);let{clearTimeout:ge,fetch:pe,getComputedStyle:je,setTimeout:Ae,Map:ce,MutationObserver:Ie,Uint8Array:me}=xt(window);let he=new ce;function Oe(t,{as:e="arrayBuffer",cleanup:i=6e4}={}){let s=e+":"+t,o=he.get(s)||{remove:()=>he.delete(s),result:null,timer:0};return ge(o.timer),o.timer=Ae(o.remove,i),o.result||(o.result=pe(t).then((t=>t[e]())).catch(o.remove),he.set(s,o)),o.result}function ze(t){return t.reduce(((t,e)=>t+function(t,e=2){let i=xt(t).toString(16);return i.length<e&&(i=xt("0").repeat(e-i.length)+i),i}(e)),"")}const{parseFloat:xe,Math:de,MutationObserver:Ke,WeakSet:Pe}=xt(window),{min:Ye}=de,Qe=(t,e)=>{const i=t.length+1,s=e.length+1,o=[[0]];let r=0,u=0;for(;++r<s;)o[0][r]=r;for(r=0;++r<i;){const i=t[u];let a=0,n=0;for(o[r]=[r];++a<s;)o[r][a]=Ye(o[u][a]+1,o[r][n]+1,o[u][n]+(i!=e[n])),++n;++u}return o[i-1][s-1]};let{getComputedStyle:be,Map:Ee,WeakSet:Te,parseFloat:Se}=xt(window);const{ELEMENT_NODE:fe,TEXT_NODE:qe}=Node;let{MutationObserver:ke,WeakSet:Ge,getComputedStyle:Ne}=xt(window);let{getComputedStyle:Be,MutationObserver:Ue,WeakSet:Je}=xt(window);xt(window);const We={mark(){},end(){},toString:()=>"{mark(){},end(){}}"};function Fe(t,e=10){return We}let{MutationObserver:Re,WeakSet:He}=xt(window);const{ELEMENT_NODE:Ve}=Node;let{MutationObserver:Ze,WeakSet:Xe}=xt(window);const{ELEMENT_NODE:_e}=Node;let{parseInt:$e,setTimeout:ti,Error:ei,MouseEvent:ii,MutationObserver:si,WeakSet:oi}=xt(window);let{parseInt:ri,setTimeout:ui,Error:ai,MouseEvent:ni,MutationObserver:Li,WeakSet:Mi}=xt(window);const Ci=["auxclick","click","dblclick","gotpointercapture","lostpointercapture","mouseenter","mousedown","mouseleave","mousemove","mouseout","mouseover","mouseup","pointerdown","pointerenter","pointermove","pointerover","pointerout","pointerup","pointercancel","pointerleave"];const wi={log:ie,race:function(t,e="1"){switch(t){case"start":ne={winners:ae(e,10)||1,participants:new ue},Le=new oe;break;case"end":case"finish":case"stop":ne=null;for(let t of Le)t();Le=null;break;default:throw new re(`Invalid action: ${t}`)}},debug:function(){_t=!0},"hide-if-matches-xpath":function(t,e){const{mark:i,end:s}=Fe(),o=se("hide-if-matches-xpath"),r=e=>{const r=Wt(`xpath(${t})`),u=new He,a=()=>{i(),r((e=>{if(u.has(e))return!1;u.add(e),L(),xt(e).nodeType===Ve?Jt(e):xt(e).textContent="",o("Matched: ",e," for selector: ",t)})),s()},n=new Re(a),L=Me("hide-if-matches-xpath",(()=>n.disconnect()));n.observe(e,{characterData:!0,childList:!0,subtree:!0}),a()};if(e){let t,i=0;const s=Wt(`xpath(${e})`),o=()=>{s((t=>{r(t),i++})),i>0&&t.disconnect()};t=new Re(o),t.observe(document,{characterData:!0,childList:!0,subtree:!0}),o()}else r(document)},"hide-if-matches-computed-xpath":function(t,e,i,s){const{mark:o,end:r}=Fe(),u=se("hide-if-matches-computed-xpath");if(!e||!t)return void u("No query or searchQuery provided.");const a=e=>{const i=(e=>t.replace("{{}}",e))(e);u("Starting hiding elements that match query: ",i);const s=Wt(`xpath(${i})`),a=new Xe,n=()=>{o(),s((e=>{if(a.has(e))return!1;a.add(e),M(),xt(e).nodeType===_e?Jt(e):xt(e).textContent="",u("Matched: ",e," for selector: ",t)})),r()},L=new Ze(n),M=Me("hide-if-matches-computed-xpath",(()=>L.disconnect()));L.observe(document,{characterData:!0,childList:!0,subtree:!0}),n()},n=Xt(i);ye(u,(()=>{if(e){u("Started searching for: ",e);const t=new Xe;let i;const s=Wt(`xpath(${e})`),o=()=>{s((e=>{if(t.has(e))return!1;if(t.add(e),u("Found node: ",e),e.innerHTML){u("Searching in: ",e.innerHTML);const t=e.innerHTML.match(n);if(t&&t.length){let e="";e=t[1]?t[1]:t[0],u("Matched search query: ",e),a(e)}}}))};i=new Ze(o),i.observe(document,{characterData:!0,childList:!0,subtree:!0}),o()}}),s)},"hide-if-contains":function(t,e="*",i=null){const s=se("hide-if-contains");let o=Xt(t);const r=Ft((t=>o.test(xt(t).textContent)),e,i,(t=>{s("Matched: ",t," for selector: ",e,i)}));r.race(Me("hide-if-contains",(()=>{r.disconnect()})))},"hide-if-contains-similar-text":function(t,e,i=null,s=0,o=0){const r=new Pe,u=se("hide-if-contains-similar-text"),a=xt(t),{length:n}=a,L=n+xe(s)||0,M=xt([...a]).sort(),C=xe(o)||1/0;null==i&&(i=e),u("Looking for similar text: "+a);const w=()=>{for(const t of kt(i)){if(r.has(t))continue;r.add(t);const{innerText:i}=xt(t),o=Ye(C,i.length-L+1);for(let r=0;r<o;r++){const o=xt(i).substr(r,L);if(Qe(M,xt([...o]).sort())-s<=0){const i=xt(t).closest(e);if(u("Found similar text: "+a,i),i){v(),Jt(i);break}}}}};let y=new Ke(w),v=Me("hide-if-contains-similar-text",(()=>y.disconnect()));y.observe(document,{childList:!0,characterData:!0,subtree:!0}),w()},"hide-if-contains-visible-text":function(t,e,i=null,...s){let o=xt([]);const r=new Ee([["-snippet-box-margin","2"],["-disable-bg-color-check","false"],["-check-is-contained","false"]]);for(let t of s){t=xt(t);let e=t.indexOf(":");if(e<0)continue;let i=t.slice(0,e).trim().toString(),s=t.slice(e+1).trim().toString();i&&s&&(r.has(i)?r.set(i,s):o.push([i,s]))}let u=xt([["opacity","0"],["font-size","0px"],["color","rgba(0, 0, 0, 0)"]]),a=new Ee(u.concat(o));function n(t,e,{bgColorCheck:i=!0}={}){e||(e=be(t)),e=xt(e);for(const[t,i]of a){if(Xt(i).test(e.getPropertyValue(t)))return!1}let s=e.getPropertyValue("color");return!i||e.getPropertyValue("background-color")!=s}function L(t,e,{bgColorCheck:i=!0}={}){let s=be(t,e);if(!Rt(t,s)||!n(t,s,{bgColorCheck:i}))return"";let{content:o}=xt(s);if(o&&"none"!==o){let e=xt([]);return o=xt(o).trim().replace(/(["'])(?:(?=(\\?))\2.)*?\1/g,(t=>""+(e.push(xt(t).slice(1,-1))-1))),o=o.replace(/\s*attr\(\s*([^\s,)]+)[^)]*?\)\s*/g,((e,i)=>xt(t).getAttribute(i)||"")),o.replace(/\x01(\d+)/g,((t,i)=>e[i]))}return""}function M(t,e,{boxMargin:i=2}={}){const s=xt(t).getBoundingClientRect(),o=xt(e).getBoundingClientRect(),r=o.left-i,u=o.right+i,a=o.top-i,n=o.bottom+i;return r<=s.left&&s.left<=u&&a<=s.top&&s.top<=n&&a<=s.bottom&&s.bottom<=n&&r<=s.right&&s.right<=u}function C(t,e,i,s,o,{boxMargin:r=2,bgColorCheck:u,checkIsContained:a}={}){let w=!i;if(w&&(i=be(t)),!Rt(t,i,w&&e))return"";s||"hidden"!==xt(i).getPropertyValue("overflow-x")&&"hidden"!==xt(i).getPropertyValue("overflow-y")||(s=t);let y=L(t,":before",{bgColorCheck:u});for(let e of xt(t).childNodes)switch(xt(e).nodeType){case fe:y+=C(e,t,be(e),s,o,{boxMargin:r,bgColorCheck:u,checkIsContained:a});break;case qe:if(s)M(t,s,{boxMargin:r})&&n(t,i,{bgColorCheck:u})&&(y+=xt(e).nodeValue);else if(n(t,i,{bgColorCheck:u})){if(a&&!M(t,o,{boxMargin:r}))continue;y+=xt(e).nodeValue}}return y+L(t,":after",{bgColorCheck:u})}const w=r.get("-snippet-box-margin"),y=Se(w)||0,v=!("true"===r.get("-disable-bg-color-check")),D="true"===r.get("-check-is-contained");let l=Xt(t),g=new Te;const p=Ft(((t,e)=>{if(g.has(t))return!1;g.add(t);let i=C(t,e,null,null,t,{boxMargin:y,bgColorCheck:v,checkIsContained:D}),s=l.test(i);return $t()&&i.length&&ie(s,l,i),s}),e,i);p.race(Me("hide-if-contains-visible-text",(()=>{p.disconnect()})))},"hide-if-contains-and-matches-style":function(t,e="*",i=null,s=null,o=null,r,u=null,a=null){const n=se("hide-if-contains-and-matches-style"),L=new De;null==i&&(i=e);const M=Xt(t),C=s?Xt(s):null,w=o?Xt(o):null,y=()=>{const t=()=>{if(!(u&&window.innerWidth<u||a&&window.innerWidth>a))for(const t of kt(i))if(!L.has(t)&&M.test(xt(t).textContent))if(!w||w.test(Ht(t))){const i=xt(t).closest(e);if(!i)continue;!C||C.test(Ht(i))?(o(),Jt(i),L.add(t),n("Matched: ",i,"which contains: ",t," for params: ",...arguments)):n("In this element the searchStyle matched but style didn't:\n",i,le(i),...arguments)}else n("In this element the searchStyle didn't match:\n",t,le(t),...arguments)},s=new ve(t),o=Me("hide-if-contains-and-matches-style",(()=>s.disconnect()));s.observe(document,{childList:!0,characterData:!0,subtree:!0}),t()};ye(n,y,r)},"hide-if-has-and-matches-style":function(t,e="*",i=null,s=null,o=null,r=null,u=null,a=null){const n=se("hide-if-has-and-matches-style"),L=new Ge;null==i&&(i=e);const M=s?Xt(s):null,C=o?Xt(o):null,w=()=>{const s=()=>{if(!(u&&window.innerWidth<u||a&&window.innerWidth>a))for(const s of kt(i))if(!L.has(s))if(!xt(s).querySelector(t)||C&&!C.test(Ht(s)))n("In this element the searchStyle didn't match:\n",s,Ne(s),...arguments);else{const t=xt(s).closest(e);!t||M&&!M.test(Ht(t))?n("In this element the searchStyle matched but style didn't:\n",t,Ne(t),...arguments):(r(),Jt(t),L.add(s),n("Matched: ",t,"which contains: ",s," for params: ",...arguments))}},o=new ke(s),r=Me("hide-if-has-and-matches-style",(()=>o.disconnect()));o.observe(document,{childList:!0,subtree:!0}),s()};ye(n,w,r)},"hide-if-labelled-by":function(t,e,i=null){let s=null==i,o=Xt(t),r=new Je,u=()=>{for(let t of kt(e)){let e=s?t:xt(t).closest(i);if(!e||!Rt(t,Be(t),e))continue;let u=xt(t).getAttribute("aria-labelledby"),a=()=>{r.has(e)||o.test(xt(t).getAttribute("aria-label")||"")&&(n(),r.add(e),Jt(e))};if(u)for(let t of xt(u).split(/\s+/)){let i=xt(document).getElementById(t);i?!r.has(i)&&o.test(i.innerText)&&(n(),r.add(i),Jt(e)):a()}else a()}},a=new Ue(u),n=Me("hide-if-labelled-by",(()=>a.disconnect()));a.observe(document,{characterData:!0,childList:!0,subtree:!0}),u()},"hide-if-contains-image":function(t,e,i){null==i&&(i=e);let s=Xt(t);const o=se("hide-if-contains-image");let r=()=>{for(let t of kt(i)){let i=je(t),r=xt(i["background-image"]).match(/^url\("(.*)"\)$/);r&&Oe(r[1]).then((i=>{if(s.test(ze(new me(i)))){let i=xt(t).closest(e);i&&(a(),Jt(i),o("Matched: ",i," for:",...arguments))}}))}},u=new Ie(r),a=Me("hide-if-contains-image",(()=>u.disconnect()));u.observe(document,{childList:!0,subtree:!0}),r()},"simulate-event-poc":function(t,e,i="0"){if(!t)throw new ei("[simulate-event snippet]: No event type provided.");if(!e)throw new ei("[simulate-event snippet]: No selector provided.");let s=Wt(e),o=$e(i,10),r=new oi;function u(){s((e=>{r.has(e)||(r.add(e),ti((()=>{xt(e).dispatchEvent(new ii(t,{bubbles:!0,cancelable:!0}))}),o))}))}new si(u).observe(document,{childList:!0,subtree:!0}),u()},"simulate-mouse-event":function(...t){const e=se("simulate-mouse-event");if(t.length<1)throw new ai("[simulate-mouse-event snippet]: No selector provided.");t.length>7&&(t=t.slice(0,7));const i=xt([]);function s(){return i.forEach((t=>{if(!t.found){(function(t){let e=t;if(e.startsWith("xpath(")&&e.endsWith(")")){let e=Wt(t);return()=>{let t=xt([]);return e((e=>t.push(e))),t}}return()=>Qt.from(kt(t))})(t.selector)().length>0&&(t.found=!0)}})),i.every((t=>t.found))}function o(t,i,s){t&&i&&("click"===i&&t.click?(t.click(),e("Clicked on this node:\n",t,"\nwith a delay of",s,"ms")):(t.dispatchEvent(new ni(i,{bubbles:!0,cancelable:!0})),e("A",i,"event was dispatched with a delay of",s,"ms on this node:\n",t)))}xt(t).forEach((t=>{const s=function(t){if(!t)return null;const i={selector:"",continue:!1,trigger:!1,event:"click",delay:"500",clicked:!1,found:!1},s=t.split("$");let o=[];s.length>=2&&(o=s[1].toLowerCase().split(",")),[i.selector]=s;for(const t of o)if("trigger"===t)i.trigger=!0;else if("continue"===t)i.continue=!0;else if(t.startsWith("event")){const e=t.toLowerCase().split("=");e[1]?i.event=e[1]:i.event="click"}else if(t.startsWith("delay")){const e=t.toLowerCase().split("=");e[1]?i.delay=e[1]:i.delay="500"}return Ci.includes(i.event)||e(i.event," might be misspelled, check for typos.\n","These are the supported events:",Ci),i}(t);i.push(s)}));let r=!1;const[u]=i.slice(-1);u.trigger=!0;let a=new Mi;function n(){if(r||(r=s()),r)for(const t of i){const e=Wt(t.selector),i=ri(t.delay,10);t.trigger&&e((e=>{a.has(e)||(a.add(e),t.continue?setInterval((()=>{o(e,t.event,t.delay)}),i):ui((()=>{o(e,t.event,t.delay)}),i))}))}}new Li(n).observe(document,{childList:!0,subtree:!0}),n()}};let{requestAnimationFrame:yi,MutationObserver:vi,WeakSet:Di,console:li}=xt(window);wi["hide-if-graph-matches"]=function(t,e){let i=globalThis.ml,s=new Di,o=!1,r=!1,u="AD,PRED,DTG,DFS,INF,EV,TOTAL\n",a=0;t.startsWith("mldebug:")&&(r=!0,t=t.slice(8)),t=t.split("..");let n=new vi((function(){o||(o=!0,yi((()=>{o=!1,M()})))})),L=Me("hide-if-graph-matches",(()=>n.disconnect()));async function M(){let o=[...t],n=document,M=[];for(;o.length>1;){let t,e=o.shift();try{t=n.querySelector(e),e&&t&&(n=t.parentElement)}catch(t){n=document;break}}try{M=n.querySelectorAll(o.shift())}catch(t){}for(let t of M){if(!xt(t).innerHTML)continue;let o=xt(t).querySelectorAll(e);0===o.length&&(o=[t]);for(let e of o)if(!s.has(t)&&(s.add(t),xt(e).innerHTML))if(r){let t={dtNow:Date.now(),dtDomToGraph:0,dtPreprocessGraph:0,dtPredict:0,dtDigestPrediction:0,predictions:[],isAd:null,target:e},s=await i.util.domToGraph(i.data.hideIfGraphMatchesConfig.config,e,i.model);t.dtDomToGraph=Date.now();let o=await i.util.preprocessGraph(i.data.hideIfGraphMatchesConfig.config,s,window.location.hostname);t.dtPreprocessGraph=Date.now(),t.predictions=await i.util.predict(i.tfjs,i.model,i.data.hideIfGraphMatchesConfig.config,o),t.dtPredict=Date.now(),t.isAd=await i.util.digestPrediction(t.predictions),t.dtDigestPrediction=Date.now(),li.log("%cMLDB ♥ %c| PRED: %s, DTG: %sms, DFS: %sms, INF: %sms, EV: %sms, TOTAL: %sms | %cAd: %s%c |","color:cyan","color:inherit",JSON.stringify(t.predictions),t.dtDomToGraph-t.dtNow,t.dtPreprocessGraph-t.dtDomToGraph,t.dtPredict-t.dtPreprocessGraph,t.dtDigestPrediction-t.dtPredict,t.dtDigestPrediction-t.dtNow,t.isAd?"color:red":"color:green",t.isAd,"color:inherit",e),a+=1,u+=`            ${t.isAd},            ${JSON.stringify(t.predictions)},            ${t.dtDomToGraph-t.dtNow},            ${t.dtPreprocessGraph-t.dtDomToGraph},            ${t.dtPredict-t.dtPreprocessGraph},            ${t.dtDigestPrediction-t.dtPredict},            ${t.dtDigestPrediction-t.dtNow}\n          `,a>9&&(a=0,li.log("%cMLDB CSV ♥%c\n%s","color:cyan","color:inherit",u.replace(/ /g,"")))}else i.util.inference(i.tfjs,i.model,i.data.hideIfGraphMatchesConfig.config,e).then((e=>{e&&(L(),Jt(t))})).catch((t=>{}))}}!function t(e=0){if(!i)throw new Error("ml not available.");if(!i.model){if(e>2e3)throw new Error("ml failed to initialize.");return yi(t)}n.observe(document,{childList:!0,subtree:!0}),M()}()}
/*!
 * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets),
 * Copyright (C) 2006-present eyeo GmbH
 * 
 * @eyeo/snippets is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 * 
 * @eyeo/snippets is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with @eyeo/snippets.  If not, see <http://www.gnu.org/licenses/>.
 */;

const snippets=wi;
let context;
for (const [name, ...args] of filters) {
if (snippets.hasOwnProperty(name)) {
try { context = snippets[name].apply(context, args); }
catch (error) { console.error(error); }
}
}
context = void 0;
};
const graph = new Map([["log",null],["race",null],["debug",null],["hide-if-matches-xpath",null],["hide-if-matches-computed-xpath",null],["hide-if-contains",null],["hide-if-contains-similar-text",null],["hide-if-contains-visible-text",null],["hide-if-contains-and-matches-style",null],["hide-if-has-and-matches-style",null],["hide-if-labelled-by",null],["hide-if-contains-image",null],["simulate-event-poc",null],["simulate-mouse-event",null],["hide-if-graph-matches",async function(){if(!globalThis.ml){const mt=1e-7,ht=1e-4;class Ot{constructor(t,e){this.backend=t,this.dataMover=e,this.data=new WeakMap,this.dataIdsCount=0}get(t){return this.data.has(t)||this.dataMover.moveData(this.backend,t),this.data.get(t)}set(t,e){this.dataIdsCount++,this.data.set(t,e)}has(t){return this.data.has(t)}delete(t){return this.dataIdsCount--,this.data.delete(t)}numDataIds(){return this.dataIdsCount}}class zt{refCount(t){return notYetImplemented("refCount")}incRef(t){return notYetImplemented("incRef")}timerAvailable(){return!0}time(t){return notYetImplemented("time")}read(t){return notYetImplemented("read")}readSync(t){return notYetImplemented("readSync")}readToGPU(t,e){return notYetImplemented("readToGPU")}numDataIds(){return notYetImplemented("numDataIds")}disposeData(t,e){return notYetImplemented("disposeData")}write(t,e,i){return notYetImplemented("write")}move(t,e,i,s,o){return notYetImplemented("move")}memory(){return notYetImplemented("memory")}floatPrecision(){return notYetImplemented("floatPrecision")}epsilon(){return 32===this.floatPrecision()?mt:ht}dispose(){return notYetImplemented("dispose")}}function xt(t){return t%2==0?t:t+1}function dt(t){let e=0;for(let i=0;i<t.length;i++)e+=t[i];return e}function Kt(t,e){if(!t)throw new Error("string"==typeof e?e:e())}function Pt(t,e,i=""){Kt(Et(t,e),(()=>i+` Shapes ${t} and ${e} must match`))}function Yt(t){Kt(null!=t,(()=>"The input to the tensor constructor must be a non-null value."))}function Qt(t,e=[],i=!1){if(null==e&&(e=[]),Array.isArray(t)||Ft(t)&&!i)for(let s=0;s<t.length;++s)Qt(t[s],e,i);else e.push(t);return e}function bt(t){if(0===t.length)return 1;let e=t[0];for(let i=1;i<t.length;i++)e*=t[i];return e}function Et(t,e){if(t===e)return!0;if(null==t||null==e)return!1;if(t.length!==e.length)return!1;for(let i=0;i<t.length;i++)if(t[i]!==e[i])return!1;return!0}function Tt(t){return t%1==0}function St(t){const e=Math.ceil(Math.sqrt(t));return[e,Math.ceil(t/e)]}function ft(t,e){return e<=t.length?t:t+" ".repeat(e-t.length)}function qt(t,e=(t=>0),i){return new Promise(((s,o)=>{let r=0;const u=()=>{if(t())return void s();r++;const a=e(r);null!=i&&r>=i?o():setTimeout(u,a)};u()}))}function kt(t,e){let i=1,s=-1;for(let e=0;e<t.length;++e)if(t[e]>=0)i*=t[e];else if(-1===t[e]){if(-1!==s)throw Error(`Shapes can only have 1 implicit size. Found -1 at dim ${s} and dim ${e}`);s=e}else if(t[e]<0)throw Error(`Shapes can not be < 0. Found ${t[e]} at dim ${e}`);if(-1===s){if(e>0&&e!==i)throw Error(`Size(${e}) must match the product of shape ${t}`);return t}if(0===i)throw Error(`Cannot infer the missing size in [${t}] when there are 0 elements`);if(e%i!=0)throw Error(`The implicit shape can't be a fractional number. Got ${e} / ${i}`);const o=t.slice();return o[s]=e/i,o}function Gt(t,e){const i=e.length;return Kt((t=null==t?e.map(((t,e)=>e)):[].concat(t)).every((t=>t>=-i&&t<i)),(()=>`All values in axis param must be in range [-${i}, ${i}) but got axis ${t}`)),Kt(t.every((t=>Tt(t))),(()=>`All values in axis param must be integers but got axis ${t}`)),t.map((t=>t<0?i+t:t))}function Nt(t,e){const i=[],s=[],o=null!=e&&Array.isArray(e)&&0===e.length,r=null==e||o?null:Gt(e,t).sort();let u=0;for(let e=0;e<t.length;++e){if(null!=r){if(r[u]===e&&1!==t[e])throw new Error(`Can't squeeze axis ${e} since its dim '${t[e]}' is not 1`);(null==r[u]||r[u]>e)&&1===t[e]&&(i.push(t[e]),s.push(e)),r[u]<=e&&u++}1!==t[e]&&(i.push(t[e]),s.push(e))}return{newShape:i,keptDims:s}}function Bt(t,e){let i=null;if(null==t||"float32"===t)i=new Float32Array(e);else if("int32"===t)i=new Int32Array(e);else{if("bool"!==t)throw new Error(`Unknown data type ${t}`);i=new Uint8Array(e)}return i}function Ut(t,e){let i=null;if(null==t||"float32"===t)i=new Float32Array(e);else if("int32"===t)i=new Int32Array(e);else if("bool"===t)i=new Uint8Array(e);else{if("string"!==t)throw new Error(`Unknown data type ${t}`);i=new Array(e)}return i}function Jt(t){return"bool"===t||"complex64"===t||"float32"===t||"int32"===t||"string"===t}function Wt(t,e){return"complex64"!==e&&(("float32"!==e||"complex64"===t)&&(("int32"!==e||"float32"===t||"complex64"===t)&&("bool"!==e||"bool"!==t)))}function Ft(t){return t instanceof Float32Array||t instanceof Int32Array||t instanceof Uint8Array||t instanceof Uint8ClampedArray}function Rt(t){if("float32"===t||"int32"===t)return 4;if("complex64"===t)return 8;if("bool"===t)return 1;throw new Error(`Unknown dtype ${t}`)}function Ht(t){if(null==t)return 0;let e=0;return t.forEach((t=>e+=t.length)),e}function Vt(t){return"number"==typeof t}function Zt(t){return Array.isArray(t)?Zt(t[0]):t instanceof Float32Array?"float32":t instanceof Int32Array||t instanceof Uint8Array||t instanceof Uint8ClampedArray?"int32":Vt(t)?"float32":isString(t)?"string":isBoolean(t)?"bool":"float32"}function Xt(t){return!!(t&&t.constructor&&t.call&&t.apply)}function _t(t,e){for(let i=e;i<t;++i)if(t%i==0)return i;return t}function $t(t){const e=t.length;if(e<2)return[];const i=new Array(e-1);i[e-2]=t[e-1];for(let s=e-3;s>=0;--s)i[s]=i[s+1]*t[s+1];return i}function te(t,e,i,s=!1){const o=new Array;if(1===e.length){const r=e[0]*(s?2:1);for(let e=0;e<r;e++)o[e]=i[t+e]}else{const r=e[0],u=e.slice(1),a=u.reduce(((t,e)=>t*e))*(s?2:1);for(let e=0;e<r;e++)o[e]=te(t+e*a,u,i,s)}return o}function ee(t,e,i=!1){if(0===t.length)return e[0];const s=t.reduce(((t,e)=>t*e))*(i?2:1);if(0===s)return[];if(s!==e.length)throw new Error(`[${t}] does not match the input size ${e.length}${i?" for a complex tensor":""}.`);return te(0,t,e,i)}function ie(t,e){const i=se(t,e);for(let t=0;t<i.length;t++)i[t]=1;return i}function se(t,e){if(null==e||"float32"===e||"complex64"===e)return new Float32Array(t);if("int32"===e)return new Int32Array(t);if("bool"===e)return new Uint8Array(t);throw new Error(`Unknown data type ${e}`)}function oe(t){t.forEach((e=>{Kt(Number.isInteger(e)&&e>=0,(()=>`Tensor must have a shape comprised of positive integers but got shape [${t}].`))}))}function re(t,e,i){if(0===e)return 0;if(1===e)return t[0];let s=t[t.length-1];for(let e=0;e<t.length-1;++e)s+=i[e]*t[e];return s}function ue(t,e,i){if(0===e)return[];if(1===e)return[t];const s=new Array(e);for(let e=0;e<s.length-1;++e)s[e]=Math.floor(t/i[e]),t-=s[e]*i[e];return s[s.length-1]=t,s}function ae(t){return t&&t.then&&"function"==typeof t.then}const ne="tfjsflags";class Le{constructor(t){this.global=t,this.flags={},this.flagRegistry={},this.urlFlags={},this.getQueryParams=Me,this.populateURLFlags()}setPlatform(t,e){null!=this.platform&&(we().getBool("IS_TEST")||we().getBool("PROD")||console.warn(`Platform ${this.platformName} has already been set. Overwriting the platform with ${t}.`)),this.platformName=t,this.platform=e}registerFlag(t,e,i){if(this.flagRegistry[t]={evaluationFn:e,setHook:i},null!=this.urlFlags[t]){const e=this.urlFlags[t];we().getBool("IS_TEST")||we().getBool("PROD")||console.warn(`Setting feature override from URL ${t}: ${e}.`),this.set(t,e)}}async getAsync(t){return t in this.flags||(this.flags[t]=await this.evaluateFlag(t)),this.flags[t]}get(t){if(t in this.flags)return this.flags[t];const e=this.evaluateFlag(t);if(ae(e))throw new Error(`Flag ${t} cannot be synchronously evaluated. Please use getAsync() instead.`);return this.flags[t]=e,this.flags[t]}getNumber(t){return this.get(t)}getBool(t){return this.get(t)}getFlags(){return this.flags}get features(){return this.flags}set(t,e){if(null==this.flagRegistry[t])throw new Error(`Cannot set flag ${t} as it has not been registered.`);this.flags[t]=e,null!=this.flagRegistry[t].setHook&&this.flagRegistry[t].setHook(e)}evaluateFlag(t){if(null==this.flagRegistry[t])throw new Error(`Cannot evaluate flag '${t}': no evaluation function found.`);return this.flagRegistry[t].evaluationFn()}setFlags(t){this.flags=Object.assign({},t)}reset(){this.flags={},this.urlFlags={},this.populateURLFlags()}populateURLFlags(){if(void 0===this.global||void 0===this.global.location||void 0===this.global.location.search)return;const t=this.getQueryParams(this.global.location.search);if(ne in t){t[ne].split(",").forEach((t=>{const[e,i]=t.split(":");this.urlFlags[e]=parseValue(e,i)}))}}}function Me(t){const e={};return t.replace(/[?&]([^=?&]+)(?:=([^&]*))?/g,((t,...i)=>(Ce(e,i[0],i[1]),i.join("=")))),e}function Ce(t,e,i){t[decodeURIComponent(e)]=decodeURIComponent(i||"")}function we(){return ve}let ye,ve=null;function De(t){ve=t}function le(){if(null==ye){let t;if("undefined"!=typeof window)t=window;else if("undefined"!=typeof global)t=global;else if("undefined"!=typeof process)t=process;else{if("undefined"==typeof self)throw new Error("Could not find a global object");t=self}ye=t}return ye}function ge(){const t=le();return null==t._tfGlobals&&(t._tfGlobals=new Map),t._tfGlobals}function pe(t,e){const i=ge();if(i.has(t))return i.get(t);{const s=e();return i.set(t,s),i.get(t)}}const je="Abs",Ae="Add",ce="BatchMatMul",Ie="Bincount",me="Cast",he="Complex",Oe="ComplexAbs",ze="Concat",xe="Conv2DBackpropFilter",de="Conv2DBackpropInput",Ke="DepthwiseConv2dNativeBackpropFilter",Pe="DepthwiseConv2dNativeBackpropInput",Ye="RealDiv",Qe="Equal",be="Exp",Ee="ExpandDims",Te="FFT",Se="GatherV2",fe="Greater",qe="Identity",ke="IsFinite",Ge="Log",Ne="Log1p",Be="LogicalAnd",Ue="Max",Je="Maximum",We="Mean",Fe="Minimum",Re="Multiply",He="Neg",Ve="NotEqual",Ze="OneHot",Xe="Pack",_e="PadV2",$e="Pow",ti="Prod",ei="Range",ii="Real",si="Relu",oi="Reshape",ri="Reverse",ui="Select",ai="Slice",ni="Sigmoid",Li="Sum",Mi="SquaredDifference",Ci="Sub",wi="Tile",yi="Unpack",vi="ZerosLike",Di="_FusedMatMul";function li(...t){we().getBool("IS_TEST")||we().getBool("PROD")||console.log(...t)}const gi=pe("kernelRegistry",(()=>new Map)),pi=pe("gradRegistry",(()=>new Map));function ji(t,e){const i=mi(t,e);return gi.get(i)}function Ai(t){return pi.get(t)}function ci(t){const e=gi.entries(),i=[];for(;;){const{done:s,value:o}=e.next();if(s)break;const[r,u]=o,[a]=r.split("_");a===t&&i.push(u)}return i}function Ii(t){const{kernelName:e,backendName:i}=t,s=mi(e,i);gi.has(s)&&warn(`The kernel '${e}' for backend '${i}' is already registered`),gi.set(s,t)}function mi(t,e){return`${e}_${t}`}var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},e=hi,i=null;try{i=new WebAssembly.Instance(new WebAssembly.Module(new Uint8Array([0,97,115,109,1,0,0,0,1,13,2,96,0,1,127,96,4,127,127,127,127,1,127,3,7,6,0,1,1,1,1,1,6,6,1,127,1,65,0,11,7,50,6,3,109,117,108,0,1,5,100,105,118,95,115,0,2,5,100,105,118,95,117,0,3,5,114,101,109,95,115,0,4,5,114,101,109,95,117,0,5,8,103,101,116,95,104,105,103,104,0,0,10,191,1,6,4,0,35,0,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,126,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,127,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,128,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,129,34,4,66,32,135,167,36,0,32,4,167,11,36,1,1,126,32,0,173,32,1,173,66,32,134,132,32,2,173,32,3,173,66,32,134,132,130,34,4,66,32,135,167,36,0,32,4,167,11])),{}).exports}catch(It){}function hi(t,e,i){this.low=0|t,this.high=0|e,this.unsigned=!!i}function Oi(t){return!0===(t&&t.__isLong__)}hi.prototype.__isLong__,Object.defineProperty(hi.prototype,"__isLong__",{value:!0}),hi.isLong=Oi;var s={},o={};function zi(t,e){var i,r,u;return e?(u=0<=(t>>>=0)&&t<256)&&(r=o[t])?r:(i=di(t,(0|t)<0?-1:0,!0),u&&(o[t]=i),i):(u=-128<=(t|=0)&&t<128)&&(r=s[t])?r:(i=di(t,t<0?-1:0,!1),u&&(s[t]=i),i)}function xi(t,e){if(isNaN(t))return e?C:M;if(e){if(t<0)return C;if(t>=a)return l}else{if(t<=-n)return g;if(t+1>=n)return D}return t<0?xi(-t,e).neg():di(t%u|0,t/u|0,e)}function di(t,e,i){return new hi(t,e,i)}hi.fromInt=zi,hi.fromNumber=xi,hi.fromBits=di;var r=Math.pow;function Ki(t,e,i){if(0===t.length)throw Error("empty string");if("NaN"===t||"Infinity"===t||"+Infinity"===t||"-Infinity"===t)return M;if("number"==typeof e?(i=e,e=!1):e=!!e,(i=i||10)<2||36<i)throw RangeError("radix");var s;if((s=t.indexOf("-"))>0)throw Error("interior hyphen");if(0===s)return Ki(t.substring(1),e,i).neg();for(var o=xi(r(i,8)),u=M,a=0;a<t.length;a+=8){var n=Math.min(8,t.length-a),L=parseInt(t.substring(a,a+n),i);if(n<8){var C=xi(r(i,n));u=u.mul(C).add(xi(L))}else u=(u=u.mul(o)).add(xi(L))}return u.unsigned=e,u}function Pi(t,e){return"number"==typeof t?xi(t,e):"string"==typeof t?Ki(t,e):di(t.low,t.high,"boolean"==typeof e?e:t.unsigned)}hi.fromString=Ki,hi.fromValue=Pi;var u=4294967296,a=u*u,n=a/2,L=zi(1<<24),M=zi(0);hi.ZERO=M;var C=zi(0,!0);hi.UZERO=C;var w=zi(1);hi.ONE=w;var y=zi(1,!0);hi.UONE=y;var v=zi(-1);hi.NEG_ONE=v;var D=di(-1,2147483647,!1);hi.MAX_VALUE=D;var l=di(-1,-1,!0);hi.MAX_UNSIGNED_VALUE=l;var g=di(0,-2147483648,!1);hi.MIN_VALUE=g;var p=hi.prototype;p.toInt=function(){return this.unsigned?this.low>>>0:this.low},p.toNumber=function(){return this.unsigned?(this.high>>>0)*u+(this.low>>>0):this.high*u+(this.low>>>0)},p.toString=function(t){if((t=t||10)<2||36<t)throw RangeError("radix");if(this.isZero())return"0";if(this.isNegative()){if(this.eq(g)){var e=xi(t),i=this.div(e),s=i.mul(e).sub(this);return i.toString(t)+s.toInt().toString(t)}return"-"+this.neg().toString(t)}for(var o=xi(r(t,6),this.unsigned),u=this,a="";;){var n=u.div(o),L=(u.sub(n.mul(o)).toInt()>>>0).toString(t);if((u=n).isZero())return L+a;for(;L.length<6;)L="0"+L;a=""+L+a}},p.getHighBits=function(){return this.high},p.getHighBitsUnsigned=function(){return this.high>>>0},p.getLowBits=function(){return this.low},p.getLowBitsUnsigned=function(){return this.low>>>0},p.getNumBitsAbs=function(){if(this.isNegative())return this.eq(g)?64:this.neg().getNumBitsAbs();for(var t=0!=this.high?this.high:this.low,e=31;e>0&&0==(t&1<<e);e--);return 0!=this.high?e+33:e+1},p.isZero=function(){return 0===this.high&&0===this.low},p.eqz=p.isZero,p.isNegative=function(){return!this.unsigned&&this.high<0},p.isPositive=function(){return this.unsigned||this.high>=0},p.isOdd=function(){return 1==(1&this.low)},p.isEven=function(){return 0==(1&this.low)},p.equals=function(t){return Oi(t)||(t=Pi(t)),(this.unsigned===t.unsigned||this.high>>>31!=1||t.high>>>31!=1)&&(this.high===t.high&&this.low===t.low)},p.eq=p.equals,p.notEquals=function(t){return!this.eq(t)},p.neq=p.notEquals,p.ne=p.notEquals,p.lessThan=function(t){return this.comp(t)<0},p.lt=p.lessThan,p.lessThanOrEqual=function(t){return this.comp(t)<=0},p.lte=p.lessThanOrEqual,p.le=p.lessThanOrEqual,p.greaterThan=function(t){return this.comp(t)>0},p.gt=p.greaterThan,p.greaterThanOrEqual=function(t){return this.comp(t)>=0},p.gte=p.greaterThanOrEqual,p.ge=p.greaterThanOrEqual,p.compare=function(t){if(Oi(t)||(t=Pi(t)),this.eq(t))return 0;var e=this.isNegative(),i=t.isNegative();return e&&!i?-1:!e&&i?1:this.unsigned?t.high>>>0>this.high>>>0||t.high===this.high&&t.low>>>0>this.low>>>0?-1:1:this.sub(t).isNegative()?-1:1},p.comp=p.compare,p.negate=function(){return!this.unsigned&&this.eq(g)?g:this.not().add(w)},p.neg=p.negate,p.add=function(t){Oi(t)||(t=Pi(t));var e=this.high>>>16,i=65535&this.high,s=this.low>>>16,o=65535&this.low,r=t.high>>>16,u=65535&t.high,a=t.low>>>16,n=0,L=0,M=0,C=0;return M+=(C+=o+(65535&t.low))>>>16,L+=(M+=s+a)>>>16,n+=(L+=i+u)>>>16,n+=e+r,di((M&=65535)<<16|(C&=65535),(n&=65535)<<16|(L&=65535),this.unsigned)},p.subtract=function(t){return Oi(t)||(t=Pi(t)),this.add(t.neg())},p.sub=p.subtract,p.multiply=function(t){if(this.isZero())return M;if(Oi(t)||(t=Pi(t)),i)return di(i.mul(this.low,this.high,t.low,t.high),i.get_high(),this.unsigned);if(t.isZero())return M;if(this.eq(g))return t.isOdd()?g:M;if(t.eq(g))return this.isOdd()?g:M;if(this.isNegative())return t.isNegative()?this.neg().mul(t.neg()):this.neg().mul(t).neg();if(t.isNegative())return this.mul(t.neg()).neg();if(this.lt(L)&&t.lt(L))return xi(this.toNumber()*t.toNumber(),this.unsigned);var e=this.high>>>16,s=65535&this.high,o=this.low>>>16,r=65535&this.low,u=t.high>>>16,a=65535&t.high,n=t.low>>>16,C=65535&t.low,w=0,y=0,v=0,D=0;return v+=(D+=r*C)>>>16,y+=(v+=o*C)>>>16,v&=65535,y+=(v+=r*n)>>>16,w+=(y+=s*C)>>>16,y&=65535,w+=(y+=o*n)>>>16,y&=65535,w+=(y+=r*a)>>>16,w+=e*C+s*n+o*a+r*u,di((v&=65535)<<16|(D&=65535),(w&=65535)<<16|(y&=65535),this.unsigned)},p.mul=p.multiply,p.divide=function(t){if(Oi(t)||(t=Pi(t)),t.isZero())throw Error("division by zero");var e,s,o;if(i)return this.unsigned||-2147483648!==this.high||-1!==t.low||-1!==t.high?di((this.unsigned?i.div_u:i.div_s)(this.low,this.high,t.low,t.high),i.get_high(),this.unsigned):this;if(this.isZero())return this.unsigned?C:M;if(this.unsigned){if(t.unsigned||(t=t.toUnsigned()),t.gt(this))return C;if(t.gt(this.shru(1)))return y;o=C}else{if(this.eq(g))return t.eq(w)||t.eq(v)?g:t.eq(g)?w:(e=this.shr(1).div(t).shl(1)).eq(M)?t.isNegative()?w:v:(s=this.sub(t.mul(e)),o=e.add(s.div(t)));if(t.eq(g))return this.unsigned?C:M;if(this.isNegative())return t.isNegative()?this.neg().div(t.neg()):this.neg().div(t).neg();if(t.isNegative())return this.div(t.neg()).neg();o=M}for(s=this;s.gte(t);){e=Math.max(1,Math.floor(s.toNumber()/t.toNumber()));for(var u=Math.ceil(Math.log(e)/Math.LN2),a=u<=48?1:r(2,u-48),n=xi(e),L=n.mul(t);L.isNegative()||L.gt(s);)L=(n=xi(e-=a,this.unsigned)).mul(t);n.isZero()&&(n=w),o=o.add(n),s=s.sub(L)}return o},p.div=p.divide,p.modulo=function(t){return Oi(t)||(t=Pi(t)),i?di((this.unsigned?i.rem_u:i.rem_s)(this.low,this.high,t.low,t.high),i.get_high(),this.unsigned):this.sub(this.div(t).mul(t))},p.mod=p.modulo,p.rem=p.modulo,p.not=function(){return di(~this.low,~this.high,this.unsigned)},p.and=function(t){return Oi(t)||(t=Pi(t)),di(this.low&t.low,this.high&t.high,this.unsigned)},p.or=function(t){return Oi(t)||(t=Pi(t)),di(this.low|t.low,this.high|t.high,this.unsigned)},p.xor=function(t){return Oi(t)||(t=Pi(t)),di(this.low^t.low,this.high^t.high,this.unsigned)},p.shiftLeft=function(t){return Oi(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?di(this.low<<t,this.high<<t|this.low>>>32-t,this.unsigned):di(0,this.low<<t-32,this.unsigned)},p.shl=p.shiftLeft,p.shiftRight=function(t){return Oi(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?di(this.low>>>t|this.high<<32-t,this.high>>t,this.unsigned):di(this.high>>t-32,this.high>=0?0:-1,this.unsigned)},p.shr=p.shiftRight,p.shiftRightUnsigned=function(t){if(Oi(t)&&(t=t.toInt()),0===(t&=63))return this;var e=this.high;return t<32?di(this.low>>>t|e<<32-t,e>>>t,this.unsigned):di(32===t?e:e>>>t-32,0,this.unsigned)},p.shru=p.shiftRightUnsigned,p.shr_u=p.shiftRightUnsigned,p.toSigned=function(){return this.unsigned?di(this.low,this.high,!1):this},p.toUnsigned=function(){return this.unsigned?this:di(this.low,this.high,!0)},p.toBytes=function(t){return t?this.toBytesLE():this.toBytesBE()},p.toBytesLE=function(){var t=this.high,e=this.low;return[255&e,e>>>8&255,e>>>16&255,e>>>24,255&t,t>>>8&255,t>>>16&255,t>>>24]},p.toBytesBE=function(){var t=this.high,e=this.low;return[t>>>24,t>>>16&255,t>>>8&255,255&t,e>>>24,e>>>16&255,e>>>8&255,255&e]},hi.fromBytes=function(t,e,i){return i?hi.fromBytesLE(t,e):hi.fromBytesBE(t,e)},hi.fromBytesLE=function(t,e){return new hi(t[0]|t[1]<<8|t[2]<<16|t[3]<<24,t[4]|t[5]<<8|t[6]<<16|t[7]<<24,e)},hi.fromBytesBE=function(t,e){return new hi(t[4]<<24|t[5]<<16|t[6]<<8|t[7],t[0]<<24|t[1]<<16|t[2]<<8|t[3],e)};var j=(It={__proto__:null,default:e},[e].forEach((function(t){t&&"string"!=typeof t&&!Array.isArray(t)&&Object.keys(t).forEach((function(e){if("default"!==e&&!(e in It)){var i=Object.getOwnPropertyDescriptor(t,e);Object.defineProperty(It,e,i.get?i:{enumerable:!0,get:function(){return t[e]}})}}))})),Object.freeze(It));const Yi=e||j;function Qi(t){return Yi.fromString(t,!0,16)}function bi(t,e){return"string"===e?encodeString(t):Ti([t],e)}function Ei(t,e){return t instanceof Float32Array&&"float32"===e||t instanceof Int32Array&&"int32"===e||t instanceof Uint8Array&&"bool"===e}function Ti(t,e){if("string"===e)throw new Error("Cannot convert a string[] to a TypedArray");if(Array.isArray(t)&&(t=Qt(t)),we().getBool("DEBUG")&&checkConversionForErrors(t,e),Ei(t,e))return t;if(null==e||"float32"===e||"complex64"===e)return new Float32Array(t);if("int32"===e)return new Int32Array(t);if("bool"===e){const e=new Uint8Array(t.length);for(let i=0;i<e.length;++i)0!==Math.round(t[i])&&(e[i]=1);return e}throw new Error(`Unknown data type ${e}`)}function Si(){return we().platform.now()}Qi("c3a5c85c97cb3127"),Qi("b492b66fbe98f273"),Qi("9ae16a3b2f90404f");class fi{constructor(t,e){this.backendTimer=t,this.logger=e,null==e&&(this.logger=new qi)}profileKernel(t,e,i){let s;const o=()=>{s=i()};let r;const u=Si();if(this.backendTimer.timerAvailable())r=this.backendTimer.time(o);else{o();for(const t of s)t.dataSync();r=Promise.resolve({kernelMs:Si()-u})}if(we().getBool("CHECK_COMPUTATION_FOR_ERRORS"))for(let e=0;e<s.length;e++){const i=s[e];i.data().then((e=>{checkComputationForErrors(e,i.dtype,t)}))}const a={kernelName:t,outputs:s,inputs:e,timeMs:r.then((t=>t.kernelMs)),extraInfo:r.then((t=>null!=t.getExtraProfileInfo?t.getExtraProfileInfo():""))};return a}logKernelProfile(t){const{kernelName:e,outputs:i,timeMs:s,inputs:o,extraInfo:r}=t;i.forEach((t=>{Promise.all([t.data(),s,r]).then((i=>{this.logger.logKernelProfile(e,t,i[0],i[1],o,i[2])}))}))}}class qi{logKernelProfile(t,e,i,s,o,r){const u="number"==typeof s?ft(`${s}ms`,9):s.error,a=ft(t,25),n=e.rank,L=e.size,M=ft(e.shape.toString(),14);let C="";for(const t in o){const i=o[t];if(null!=i){const s=i.shape||e.shape,o=s.length;C+=`${t}: ${o}D ${o>0?s:""} `}}console.log(`%c${a}\t%c${u}\t%c${n}D ${M}\t%c${L}\t%c${C}\t%c${r}`,"font-weight:bold","color:red","color:blue","color: orange","color: green","color: steelblue")}}function ki(t,e,i){const s={},o={};for(let t=0;t<e.length;t++)s[e[t].id]=!0;for(let i=0;i<t.length;i++){const r=t[i],u=r.inputs;for(const t in u){const i=u[t];let a=!1;for(let t=0;t<e.length;t++)if(s[i.id]){r.outputs.forEach((t=>s[t.id]=!0)),a=!0,o[r.id]=!0;break}if(a)break}}const r={};r[i.id]=!0;const u={};for(let e=t.length-1;e>=0;e--){const i=t[e],s=i.inputs;for(let t=0;t<i.outputs.length;t++)if(r[i.outputs[t].id]){for(const t in s)r[s[t].id]=!0,u[i.id]=!0;break}}const a=[];for(let e=0;e<t.length;e++){const i=t[e];if(o[i.id]&&u[i.id]){const t={};for(const e in i.inputs){const o=i.inputs[e];s[o.id]&&(t[e]=o)}const e=Object.assign({},i);e.inputs=t,e.outputs=i.outputs,a.push(e)}}return a}class Gi{constructor(t,e,i){if(this.dtype=e,this.shape=t.slice(),this.size=bt(t),null!=i){const t=i.length;Kt(t===this.size,(()=>`Length of values '${t}' does not match the size inferred by the shape '${this.size}'.`))}if("complex64"===e)throw new Error("complex64 dtype TensorBuffers are not supported. Please create a TensorBuffer for the real and imaginary parts separately and call tf.complex(real, imag).");this.values=i||Ut(e,this.size),this.strides=$t(t)}set(t,...e){0===e.length&&(e=[0]),Kt(e.length===this.rank,(()=>`The number of provided coordinates (${e.length}) must match the rank (${this.rank})`));const i=this.locToIndex(e);this.values[i]=t}get(...t){0===t.length&&(t=[0]);let e=0;for(const i of t){if(i<0||i>=this.shape[e]){const e=`Requested out of range element at ${t}.   Buffer shape=${this.shape}`;throw new Error(e)}e++}let i=t[t.length-1];for(let e=0;e<t.length-1;++e)i+=this.strides[e]*t[e];return this.values[i]}locToIndex(t){if(0===this.rank)return 0;if(1===this.rank)return t[0];let e=t[t.length-1];for(let i=0;i<t.length-1;++i)e+=this.strides[i]*t[i];return e}indexToLoc(t){if(0===this.rank)return[];if(1===this.rank)return[t];const e=new Array(this.shape.length);for(let i=0;i<e.length-1;++i)e[i]=Math.floor(t/this.strides[i]),t-=e[i]*this.strides[i];return e[e.length-1]=t,e}get rank(){return this.shape.length}toTensor(){return Ni().makeTensor(this.values,this.shape,this.dtype)}}let Ni=null,Bi=null;function Ui(t){Ni=t}function Ji(t){Bi=t}class Wi{constructor(t,e,i,s){this.kept=!1,this.isDisposedInternal=!1,this.shape=t.slice(),this.dtype=e||"float32",this.size=bt(t),this.strides=$t(t),this.dataId=i,this.id=s,this.rankType=this.rank<5?this.rank.toString():"higher"}get rank(){return this.shape.length}async buffer(){const t=await this.data();return Bi.buffer(this.shape,this.dtype,t)}bufferSync(){return Bi.buffer(this.shape,this.dtype,this.dataSync())}async array(){const t=await this.data();return ee(this.shape,t,"complex64"===this.dtype)}arraySync(){return ee(this.shape,this.dataSync(),"complex64"===this.dtype)}async data(){this.throwIfDisposed();const t=Ni().read(this.dataId);if("string"===this.dtype){const e=await t;try{return e.map((t=>decodeString(t)))}catch(t){throw new Error("Failed to decode the string bytes into utf-8. To get the original bytes, call tensor.bytes().")}}return t}dataToGPU(t){return this.throwIfDisposed(),Ni().readToGPU(this.dataId,t)}dataSync(){this.throwIfDisposed();const t=Ni().readSync(this.dataId);if("string"===this.dtype)try{return t.map((t=>decodeString(t)))}catch(t){throw new Error("Failed to decode the string bytes into utf-8. To get the original bytes, call tensor.bytes().")}return t}async bytes(){this.throwIfDisposed();const t=await Ni().read(this.dataId);return"string"===this.dtype?t:new Uint8Array(t.buffer)}dispose(){this.isDisposed||(Ni().disposeTensor(this),this.isDisposedInternal=!0)}get isDisposed(){return this.isDisposedInternal}throwIfDisposed(){if(this.isDisposed)throw new Error("Tensor is disposed.")}print(t=!1){return Bi.print(this,t)}clone(){return this.throwIfDisposed(),Bi.clone(this)}toString(t=!1){const e=this.dataSync();return tensorToString(e,this.shape,this.dtype,t)}cast(t){return this.throwIfDisposed(),Bi.cast(this,t)}variable(t=!0,e,i){return this.throwIfDisposed(),Ni().makeVariable(this,t,e,i)}}function Fi(){return pe("Tensor",(()=>Wi))}Object.defineProperty(Wi,Symbol.hasInstance,{value:t=>!!t&&null!=t.data&&null!=t.dataSync&&null!=t.throwIfDisposed}),Fi();class Ri extends Wi{constructor(t,e,i,s){super(t.shape,t.dtype,t.dataId,s),this.trainable=e,this.name=i}assign(t){if(t.dtype!==this.dtype)throw new Error(`dtype of the new value (${t.dtype}) and previous value (${this.dtype}) must match`);if(!Et(t.shape,this.shape))throw new Error(`shape of the new value (${t.shape}) and previous value (${this.shape}) must match`);Ni().disposeTensor(this),this.dataId=t.dataId,Ni().incRef(this,null)}dispose(){Ni().disposeVariable(this),this.isDisposedInternal=!0}}var A,c,I,m,h;Object.defineProperty(Ri,Symbol.hasInstance,{value:t=>t instanceof Wi&&null!=t.assign&&t.assign instanceof Function}),function(t){t.R0="R0",t.R1="R1",t.R2="R2",t.R3="R3",t.R4="R4",t.R5="R5",t.R6="R6"}(A||(A={})),function(t){t.float32="float32",t.int32="int32",t.bool="int32",t.complex64="complex64"}(c||(c={})),function(t){t.float32="float32",t.int32="int32",t.bool="bool",t.complex64="complex64"}(I||(I={})),function(t){t.float32="float32",t.int32="float32",t.bool="float32",t.complex64="complex64"}(m||(m={})),function(t){t.float32="complex64",t.int32="complex64",t.bool="complex64",t.complex64="complex64"}(h||(h={}));const Hi={float32:m,int32:c,bool:I,complex64:h};function Vi(t,e){if("string"===t||"string"===e){if("string"===t&&"string"===e)return"string";throw new Error(`Can not upcast ${t} with ${e}`)}return Hi[t][e]}function Zi(t){return Vi(t,"int32")}function Xi(t,e){if(t.dtype===e.dtype)return[t,e];const i=Vi(t.dtype,e.dtype);return[t.cast(i),e.cast(i)]}function _i(t){const e=[];return $i(t,e,new Set),e}function $i(t,e,i){if(null==t)return;if(t instanceof Wi)return void e.push(t);if(!ts(t))return;const s=t;for(const t in s){const o=s[t];i.has(o)||(i.add(o),$i(o,e,i))}}function ts(t){return Array.isArray(t)||"object"==typeof t}function es(t){return null!=t.kernelName}class is{constructor(){this.registeredVariables={},this.nextTapeNodeId=0,this.numBytes=0,this.numTensors=0,this.numStringTensors=0,this.numDataBuffers=0,this.gradientDepth=0,this.kernelDepth=0,this.scopeStack=[],this.numDataMovesStack=[],this.nextScopeId=0,this.tensorInfo=new WeakMap,this.profiling=!1,this.activeProfile={newBytes:0,newTensors:0,peakBytes:0,kernels:[],result:null,get kernelNames(){return Array.from(new Set(this.kernels.map((t=>t.name))))}}}dispose(){for(const t in this.registeredVariables)this.registeredVariables[t].dispose()}}class ss{constructor(t){this.ENV=t,this.registry={},this.registryFactory={},this.pendingBackendInitId=0,this.state=new is}async ready(){if(null!=this.pendingBackendInit)return this.pendingBackendInit.then((()=>{}));if(null!=this.backendInstance)return;const t=this.getSortedBackends();for(let e=0;e<t.length;e++){const i=t[e];if(await this.initializeBackend(i).success)return void await this.setBackend(i)}throw new Error("Could not initialize any backends, all backend initializations failed.")}get backend(){if(null!=this.pendingBackendInit)throw new Error(`Backend '${this.backendName}' has not yet been initialized. Make sure to await tf.ready() or await tf.setBackend() before calling other methods`);if(null==this.backendInstance){const{name:t,asyncInit:e}=this.initializeBackendsAndReturnBest();if(e)throw new Error(`The highest priority backend '${t}' has not yet been initialized. Make sure to await tf.ready() or await tf.setBackend() before calling other methods`);this.setBackend(t)}return this.backendInstance}backendNames(){return Object.keys(this.registryFactory)}findBackend(t){if(!(t in this.registry)){if(!(t in this.registryFactory))return null;{const{asyncInit:e}=this.initializeBackend(t);if(e)return null}}return this.registry[t]}findBackendFactory(t){return t in this.registryFactory?this.registryFactory[t].factory:null}registerBackend(t,e,i=1){return t in this.registryFactory?(warn(`${t} backend was already registered. Reusing existing backend factory.`),!1):(this.registryFactory[t]={factory:e,priority:i},!0)}async setBackend(t){if(null==this.registryFactory[t])throw new Error(`Backend name '${t}' not found in registry`);if(this.backendName=t,null==this.registry[t]){this.backendInstance=null;const{success:e,asyncInit:i}=this.initializeBackend(t);if(!(i?await e:e))return!1}return this.backendInstance=this.registry[t],this.setupRegisteredKernels(),this.profiler=new fi(this.backendInstance),!0}setupRegisteredKernels(){ci(this.backendName).forEach((t=>{null!=t.setupFunc&&t.setupFunc(this.backendInstance)}))}disposeRegisteredKernels(t){ci(t).forEach((e=>{null!=e.disposeFunc&&e.disposeFunc(this.registry[t])}))}initializeBackend(t){const e=this.registryFactory[t];if(null==e)throw new Error(`Cannot initialize backend ${t}, no registration found.`);try{const i=e.factory();if(!i||i instanceof zt||"function"!=typeof i.then)return this.registry[t]=i,{success:!0,asyncInit:!1};{const e=++this.pendingBackendInitId,s=i.then((i=>!(e<this.pendingBackendInitId)&&(this.registry[t]=i,this.pendingBackendInit=null,!0))).catch((i=>(e<this.pendingBackendInitId||(this.pendingBackendInit=null,warn(`Initialization of backend ${t} failed`),warn(i.stack||i.message)),!1)));return this.pendingBackendInit=s,{success:s,asyncInit:!0}}}catch(e){return warn(`Initialization of backend ${t} failed`),warn(e.stack||e.message),{success:!1,asyncInit:!1}}}removeBackend(t){if(!(t in this.registryFactory))throw new Error(`${t} backend not found in registry`);this.backendName===t&&null!=this.pendingBackendInit&&this.pendingBackendInitId++,t in this.registry&&(this.disposeRegisteredKernels(t),this.registry[t].dispose(),delete this.registry[t]),delete this.registryFactory[t],this.backendName===t&&(this.pendingBackendInit=null,this.backendName=null,this.backendInstance=null)}getSortedBackends(){if(0===Object.keys(this.registryFactory).length)throw new Error("No backend found in registry.");return Object.keys(this.registryFactory).sort(((t,e)=>this.registryFactory[e].priority-this.registryFactory[t].priority))}initializeBackendsAndReturnBest(){const t=this.getSortedBackends();for(let e=0;e<t.length;e++){const i=t[e],{success:s,asyncInit:o}=this.initializeBackend(i);if(o||s)return{name:i,asyncInit:o}}throw new Error("Could not initialize any backends, all backend initializations failed.")}moveData(t,e){const i=this.state.tensorInfo.get(e),s=i.backend,o=this.readSync(e),r=s.refCount(e);s.disposeData(e,!0),i.backend=t,t.move(e,o,i.shape,i.dtype,r),this.shouldCheckForMemLeaks()&&this.state.numDataMovesStack[this.state.numDataMovesStack.length-1]++}tidy(t,e){let i,s=null;if(null==e){if("function"!=typeof t)throw new Error("Please provide a function to tidy()");e=t}else{if("string"!=typeof t&&!(t instanceof String))throw new Error("When calling with two arguments, the first argument to tidy() must be a string");if("function"!=typeof e)throw new Error("When calling with two arguments, the 2nd argument to tidy() must be a function");s=t}return this.scopedRun((()=>this.startScope(s)),(()=>this.endScope(i)),(()=>(i=e(),i instanceof Promise&&console.error("Cannot return a Promise inside of tidy."),i)))}scopedRun(t,e,i){t();try{const t=i();return e(),t}catch(t){throw e(),t}}nextTensorId(){return ss.nextTensorId++}nextVariableId(){return ss.nextVariableId++}clone(t){const e=us.runKernel(qe,{x:t}),i={x:t};return this.addTapeNode(this.state.activeScope.name,i,[e],(t=>({x:()=>{const e={x:t},i={dtype:"float32"};return us.runKernel(me,e,i)}})),[],{}),e}runKernel(t,e,i){null==this.backendName&&this.backend;if(!(null!=ji(t,this.backendName)))throw new Error(`Kernel '${t}' not registered for backend '${this.backendName}'`);return this.runKernelFunc({kernelName:t,inputs:e,attrs:i})}shouldCheckForMemLeaks(){return this.ENV.getBool("IS_TEST")}checkKernelForMemLeak(t,e,i){const s=this.backend.numDataIds();let o=0;i.forEach((t=>{o+="complex64"===t.dtype?3:1}));const r=this.state.numDataMovesStack[this.state.numDataMovesStack.length-1],u=s-e-o-r;if(u>0)throw new Error(`Backend '${this.backendName}' has an internal memory leak (${u} data ids) after running '${t}'`)}runKernelFunc(t){let e,i=[];const s=this.isTapeOn(),o=this.state.numBytes,r=this.state.numTensors;let u,a;this.shouldCheckForMemLeaks()&&this.state.numDataMovesStack.push(0),null==this.backendName&&this.backend;const n=es(t)?t.kernelName:null!=this.state.activeScope?this.state.activeScope.name:"";if(es(t)){const{kernelName:e,inputs:o,attrs:r}=t;null==this.backendName&&this.backend;const n=ji(e,this.backendName);Kt(null!=n,(()=>`Cannot find registered kernel '${e}' for backend '${this.backendName}'`)),u=()=>{const t=this.backend.numDataIds();a=n.kernelFunc({inputs:o,attrs:r,backend:this.backend});const u=Array.isArray(a)?a:[a];this.shouldCheckForMemLeaks()&&this.checkKernelForMemLeak(e,t,u);const L=u.map((t=>null!=t.rank?t:this.makeTensorFromTensorInfo(t)));if(s){const t=this.getTensorsForGradient(e,o,L);i=this.saveTensorsForBackwardMode(t)}return L}}else{const{forwardFunc:e}=t,o=t=>{s&&(i=t.map((t=>this.keep(this.clone(t)))))};u=()=>{const t=this.backend.numDataIds();a=this.tidy((()=>e(this.backend,o)));const i=Array.isArray(a)?a:[a];return this.shouldCheckForMemLeaks()&&this.checkKernelForMemLeak(n,t,i),i}}const{inputs:L,attrs:M}=t,C=es(t)?null:t.backwardsFunc;let w;return this.scopedRun((()=>this.state.kernelDepth++),(()=>this.state.kernelDepth--),(()=>{this.ENV.getBool("DEBUG")||this.state.profiling?(w=this.profiler.profileKernel(n,L,(()=>u())),this.ENV.getBool("DEBUG")&&this.profiler.logKernelProfile(w),e=w.outputs):e=u()})),s&&this.addTapeNode(n,L,e,C,i,M),this.state.profiling&&this.state.activeProfile.kernels.push({name:n,bytesAdded:this.state.numBytes-o,totalBytesSnapshot:this.state.numBytes,tensorsAdded:this.state.numTensors-r,totalTensorsSnapshot:this.state.numTensors,inputShapes:Object.keys(L).map((t=>null!=L[t]?L[t].shape:null)),outputShapes:e.map((t=>t.shape)),kernelTimeMs:w.timeMs,extraInfo:w.extraInfo}),Array.isArray(a)?e:e[0]}saveTensorsForBackwardMode(t){return t.map((t=>this.keep(this.clone(t))))}getTensorsForGradient(t,e,i){const s=Ai(t);if(null!=s){const t=s.inputsToSave||[],o=s.outputsToSave||[];let r;s.saveAllInputs?(Kt(Array.isArray(e),(()=>"saveAllInputs is true, expected inputs to be an array.")),r=Object.keys(e).map((t=>e[t]))):r=t.map((t=>e[t]));const u=i.filter(((t,e)=>o[e]));return r.concat(u)}return[]}makeTensor(t,e,i,s){if(null==t)throw new Error("Values passed to engine.makeTensor() are null");i=i||"float32",s=s||this.backend;let o=t;"string"===i&&isString(t[0])&&(o=t.map((t=>encodeString(t))));const r=s.write(o,e,i),u=new Wi(e,i,r,this.nextTensorId());if(this.trackTensor(u,s),"string"===i){const t=this.state.tensorInfo.get(r),e=Ht(o);this.state.numBytes+=e-t.bytes,t.bytes=e}return u}makeTensorFromDataId(t,e,i,s){const o={dataId:t,shape:e,dtype:i=i||"float32"};return this.makeTensorFromTensorInfo(o,s)}makeTensorFromTensorInfo(t,e){const{dataId:i,shape:s,dtype:o}=t,r=new Wi(s,o,i,this.nextTensorId());return this.trackTensor(r,e),r}makeVariable(t,e=!0,i,s){i=i||this.nextVariableId().toString(),null!=s&&s!==t.dtype&&(t=t.cast(s));const o=new Ri(t,e,i,this.nextTensorId());if(null!=this.state.registeredVariables[o.name])throw new Error(`Variable with name ${o.name} was already registered`);return this.state.registeredVariables[o.name]=o,this.incRef(o,this.backend),o}trackTensor(t,e){this.state.numTensors++,"string"===t.dtype&&this.state.numStringTensors++;let i=0;"complex64"!==t.dtype&&"string"!==t.dtype&&(i=t.size*Rt(t.dtype)),this.state.numBytes+=i,this.state.tensorInfo.has(t.dataId)||(this.state.numDataBuffers++,this.state.tensorInfo.set(t.dataId,{backend:e||this.backend,dtype:t.dtype,shape:t.shape,bytes:i})),t instanceof Ri||this.track(t)}incRef(t,e){this.trackTensor(t,e),this.backend.incRef(t.dataId)}removeDataId(t,e){this.state.tensorInfo.has(t)&&this.state.tensorInfo.get(t).backend===e&&(this.state.tensorInfo.delete(t),this.state.numDataBuffers--)}disposeTensor(t){if(!this.state.tensorInfo.has(t.dataId))return;const e=this.state.tensorInfo.get(t.dataId);if(this.state.numTensors--,"string"===t.dtype&&(this.state.numStringTensors--,this.state.numBytes-=e.bytes),"complex64"!==t.dtype&&"string"!==t.dtype){const e=t.size*Rt(t.dtype);this.state.numBytes-=e}e.backend.disposeData(t.dataId)&&this.removeDataId(t.dataId,e.backend)}disposeVariables(){for(const t in this.state.registeredVariables){const e=this.state.registeredVariables[t];this.disposeVariable(e)}}disposeVariable(t){this.disposeTensor(t),null!=this.state.registeredVariables[t.name]&&delete this.state.registeredVariables[t.name]}memory(){const t=this.backend.memory();return t.numTensors=this.state.numTensors,t.numDataBuffers=this.state.numDataBuffers,t.numBytes=this.state.numBytes,this.state.numStringTensors>0&&(t.unreliable=!0,null==t.reasons&&(t.reasons=[]),t.reasons.push("Memory usage by string tensors is approximate (2 bytes per character)")),t}async profile(t){this.state.profiling=!0;const e=this.state.numBytes,i=this.state.numTensors;this.state.activeProfile.kernels=[],this.state.activeProfile.result=await t(),this.state.profiling=!1,this.state.activeProfile.peakBytes=Math.max(...this.state.activeProfile.kernels.map((t=>t.totalBytesSnapshot))),this.state.activeProfile.newBytes=this.state.numBytes-e,this.state.activeProfile.newTensors=this.state.numTensors-i;for(const t of this.state.activeProfile.kernels)t.kernelTimeMs=await t.kernelTimeMs,t.extraInfo=await t.extraInfo;return this.state.activeProfile}isTapeOn(){return this.state.gradientDepth>0&&0===this.state.kernelDepth}addTapeNode(t,e,i,s,o,r){const u={id:this.state.nextTapeNodeId++,kernelName:t,inputs:e,outputs:i,saved:o},a=Ai(t);null!=a&&(s=a.gradFunc),null!=s&&(u.gradient=t=>(t=t.map(((t,e)=>{if(null==t){const t=i[e],s=se(t.size,t.dtype);return this.makeTensor(s,t.shape,t.dtype)}return t})),s(t.length>1?t:t[0],o,r))),this.state.activeTape.push(u)}keep(t){return t.kept=!0,t}startTape(){0===this.state.gradientDepth&&(this.state.activeTape=[]),this.state.gradientDepth++}endTape(){this.state.gradientDepth--}startScope(t){const e={track:[],name:"unnamed scope",id:this.state.nextScopeId++};t&&(e.name=t),this.state.scopeStack.push(e),this.state.activeScope=e}endScope(t){const e=_i(t),i=new Set(e.map((t=>t.id)));for(let t=0;t<this.state.activeScope.track.length;t++){const e=this.state.activeScope.track[t];e.kept||i.has(e.id)||e.dispose()}const s=this.state.scopeStack.pop();this.state.activeScope=0===this.state.scopeStack.length?null:this.state.scopeStack[this.state.scopeStack.length-1],e.forEach((t=>{t.kept||t.scopeId!==s.id||this.track(t)}))}gradients(t,e,i,s=!1){if(Kt(e.length>0,(()=>"gradients() received an empty list of xs.")),null!=i&&"float32"!==i.dtype)throw new Error(`dy must have 'float32' dtype, but has '${i.dtype}'`);const o=this.scopedRun((()=>this.startTape()),(()=>this.endTape()),(()=>this.tidy("forward",t)));Kt(o instanceof Wi,(()=>"The result y returned by f() must be a tensor."));const r=ki(this.state.activeTape,e,o);if(!s&&0===r.length&&e.length>0)throw new Error("Cannot compute gradient of y=f(x) with respect to x. Make sure that the f you passed encloses all operations that lead from x to y.");return this.tidy("backward",(()=>{const t={};t[o.id]=null==i?os(o.shape):i,backpropagateGradients(t,r,(t=>this.tidy(t)),as);const s=e.map((e=>t[e.id]));return 0===this.state.gradientDepth&&(this.state.activeTape.forEach((t=>{for(const e of t.saved)e.dispose()})),this.state.activeTape=null),{value:o,grads:s}}))}customGrad(t){return Kt(Xt(t),(()=>"The f passed in customGrad(f) must be a function.")),(...e)=>{let i;Kt(e.every((t=>t instanceof Wi)),(()=>"The args passed in customGrad(f)(x1, x2,...) must all be tensors"));const s={};e.forEach(((t,e)=>{s[e]=t}));return this.runKernelFunc({forwardFunc:(s,o)=>(i=t(...e,o),Kt(i.value instanceof Wi,(()=>"The function f passed in customGrad(f) must return an object where `obj.value` is a tensor")),Kt(Xt(i.gradFunc),(()=>"The function f passed in customGrad(f) must return an object where `obj.gradFunc` is a function.")),i.value),backwardsFunc:(t,s)=>{const o=i.gradFunc(t,s),r=Array.isArray(o)?o:[o];Kt(r.length===e.length,(()=>"The function f passed in customGrad(f) must return an object where `obj.gradFunc` is a function that returns the same number of tensors as inputs passed to f(...).")),Kt(r.every((t=>t instanceof Wi)),(()=>"The function f passed in customGrad(f) must return an object where `obj.gradFunc` is a function that returns a list of only tensors."));const u={};return r.forEach(((t,e)=>{u[e]=()=>t})),u},inputs:s})}}readSync(t){return this.state.tensorInfo.get(t).backend.readSync(t)}read(t){return this.state.tensorInfo.get(t).backend.read(t)}readToGPU(t,e){return this.state.tensorInfo.get(t).backend.readToGPU(t,e)}async time(t){const e=Si(),i=await this.backend.time(t);return i.wallMs=Si()-e,i}track(t){return null!=this.state.activeScope&&(t.scopeId=this.state.activeScope.id,this.state.activeScope.track.push(t)),t}get registeredVariables(){return this.state.registeredVariables}reset(){this.pendingBackendInitId++,this.state.dispose(),this.ENV.reset(),this.state=new is;for(const t in this.registry)this.disposeRegisteredKernels(t),this.registry[t].dispose(),delete this.registry[t];this.backendName=null,this.backendInstance=null,this.pendingBackendInit=null}}function os(t){const e=ie(bt(t),"float32");return us.makeTensor(e,t,"float32")}function rs(){const t=le();if(null==t._tfengine){const e=new Le(t);t._tfengine=new ss(e)}return De(t._tfengine.ENV),Ui((()=>t._tfengine)),t._tfengine}ss.nextTensorId=0,ss.nextVariableId=0;const us=rs();function as(t,e){const i={a:t,b:e};return us.runKernel(Ae,i)}function ns(t){if(t||"undefined"!=typeof navigator&&null!=navigator){if(t||(t=navigator),"ReactNative"===t.product)return!0;const e=t.userAgent||t.vendor||("undefined"!=typeof window?window.opera:"");if(!e){const e=t;return e.userAgentData&&e.userAgentData.mobile}return/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(e)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(e.substr(0,4))}return!1}function Ls(){return"undefined"!=typeof window&&null!=window.document||"undefined"!=typeof WorkerGlobalScope}const Ms=we();function Cs(t,e){let i=t;if(Ft(t))return"string"===e?[]:[t.length];if(!Array.isArray(t))return[];const s=[];for(;Array.isArray(i)||Ft(i)&&"string"!==e;)s.push(i.length),i=i[0];return Array.isArray(t)&&we().getBool("TENSORLIKE_CHECK_SHAPE_CONSISTENCY")&&deepAssertShapeConsistency(t,s,[]),s}function ws(t,e,i,s){if("string_or_numeric"!==t){if(null==t)throw new Error("Expected dtype cannot be null.");if("numeric"!==t&&t!==e||"numeric"===t&&"string"===e)throw new Error(`Argument '${i}' passed to '${s}' must be ${t} tensor, but got ${e} tensor`)}}function ys(t,e,i,s="numeric"){if(t instanceof Wi)return ws(s,t.dtype,e,i),t;let o=Zt(t);if("string"!==o&&["bool","int32","float32"].indexOf(s)>=0&&(o=s),ws(s,o,e,i),null==t||!Ft(t)&&!Array.isArray(t)&&"number"!=typeof t&&"boolean"!=typeof t&&"string"!=typeof t){const s=null==t?"null":t.constructor.name;throw new Error(`Argument '${e}' passed to '${i}' must be a Tensor or TensorLike, but got '${s}'`)}const r=Cs(t,o);Ft(t)||Array.isArray(t)||(t=[t]);const u="string"!==o?Ti(t,o):Qt(t,[],!0);return us.makeTensor(u,r,o)}function vs(t,e,i,s="numeric"){if(!Array.isArray(t))throw new Error(`Argument ${e} passed to ${i} must be a \`Tensor[]\` or \`TensorLike[]\``);return t.map(((t,o)=>ys(t,`${e}[${o}]`,i,s)))}Ms.registerFlag("DEBUG",(()=>!1),(t=>{t&&console.warn("Debugging mode is ON. The output of every math call will be downloaded to CPU and checked for NaNs. This significantly impacts performance.")})),Ms.registerFlag("IS_BROWSER",(()=>Ls())),Ms.registerFlag("IS_NODE",(()=>"undefined"!=typeof process&&void 0!==process.versions&&void 0!==process.versions.node)),Ms.registerFlag("IS_CHROME",(()=>"undefined"!=typeof navigator&&null!=navigator&&null!=navigator.userAgent&&/Chrome/.test(navigator.userAgent)&&/Google Inc/.test(navigator.vendor))),Ms.registerFlag("PROD",(()=>!1)),Ms.registerFlag("TENSORLIKE_CHECK_SHAPE_CONSISTENCY",(()=>Ms.getBool("DEBUG"))),Ms.registerFlag("DEPRECATION_WARNINGS_ENABLED",(()=>!0)),Ms.registerFlag("IS_TEST",(()=>!1)),Ms.registerFlag("CHECK_COMPUTATION_FOR_ERRORS",(()=>!0)),Ms.registerFlag("WRAP_TO_IMAGEBITMAP",(()=>!1)),Ms.registerFlag("ENGINE_COMPILE_ONLY",(()=>!1));const Ds="__op";function ls(t){const e=Object.keys(t);if(1!==e.length)throw new Error(`Please provide an object with a single key (operation name) mapping to a function. Got an object with ${e.length} keys.`);let i=e[0];const s=t[i];i.endsWith("_")&&(i=i.substring(0,i.length-1)),i+=Ds;const o=(...t)=>{us.startScope(i);try{const e=s(...t);return ae(e)&&console.error("Cannot return a Promise inside of tidy."),us.endScope(e),e}catch(t){throw us.endScope(null),t}};return Object.defineProperty(o,"name",{value:i,configurable:!0}),o}function gs(t,e){const i=ys(t,"real","complex"),s=ys(e,"imag","complex");Pt(i.shape,s.shape,`real and imag shapes, ${i.shape} and ${s.shape}, must match in call to tf.complex().`);const o={real:i,imag:s};return us.runKernel(he,o)}const ps=ls({complex_:gs});function js(t,e,i,s){if(null==s&&(s=Zt(t)),"complex64"===s)throw new Error("Cannot construct a complex64 tensor directly. Please use tf.complex(real, imag).");if(!Ft(t)&&!Array.isArray(t)&&"number"!=typeof t&&"boolean"!=typeof t&&"string"!=typeof t)throw new Error("values passed to tensor(values) must be a number/boolean/string or an array of numbers/booleans/strings, or a TypedArray");if(null!=e){oe(e);const t=bt(e),s=bt(i);Kt(t===s,(()=>`Based on the provided shape, [${e}], the tensor should have ${t} values but has ${s}`));for(let t=0;t<i.length;++t){const s=i[t],o=t!==i.length-1||s!==bt(e.slice(t));Kt(i[t]===e[t]||!o,(()=>`Error creating a new Tensor. Inferred shape (${i}) does not match the provided shape (${e}). `))}}return Ft(t)||Array.isArray(t)||(t=[t]),e=e||i,t="string"!==s?Ti(t,s):Qt(t,[],!0),us.makeTensor(t,e,s)}function As(t,e,i){return js(t,e,Cs(t,i),i)}const cs={float32:4,float16:2,int32:4,uint16:2,uint8:1,bool:1,complex64:8},Is=4;function ms(t,e){const i={};let s,o=0;for(const r of e){const e=r.name,u=r.dtype,a=r.shape,n=bt(a);let L;if("quantization"in r){const i=r.quantization;if("uint8"===i.dtype||"uint16"===i.dtype){if(!("min"in i)||!("scale"in i))throw new Error(`Weight ${r.name} with quantization ${i.dtype} doesn't have corresponding metadata min and scale.`)}else{if("float16"!==i.dtype)throw new Error(`Weight ${r.name} has unknown quantization dtype ${i.dtype}. Supported quantization dtypes are: 'uint8', 'uint16', and 'float16'.`);if("float32"!==u)throw new Error(`Weight ${r.name} is quantized with ${i.dtype} which only supports weights of type float32 not ${u}.`)}const a=cs[i.dtype],M=t.slice(o,o+n*a),C="uint8"===i.dtype?new Uint8Array(M):new Uint16Array(M);if("float32"===u)if("uint8"===i.dtype||"uint16"===i.dtype){L=new Float32Array(C.length);for(let t=0;t<C.length;t++){const e=C[t];L[t]=e*i.scale+i.min}}else{if("float16"!==i.dtype)throw new Error(`Unsupported quantization type ${i.dtype} for weight type float32.`);void 0===s&&(s=getFloat16Decoder()),L=s(C)}else{if("int32"!==u)throw new Error(`Unsupported dtype in weight '${e}': ${u}`);if("uint8"!==i.dtype&&"uint16"!==i.dtype)throw new Error(`Unsupported quantization type ${i.dtype} for weight type int32.`);L=new Int32Array(C.length);for(let t=0;t<C.length;t++){const e=C[t];L[t]=Math.round(e*i.scale+i.min)}}o+=n*a}else if("string"===u){const e=bt(r.shape);L=[];for(let i=0;i<e;i++){const e=new Uint32Array(t.slice(o,o+Is))[0];o+=Is;const i=new Uint8Array(t.slice(o,o+e));L.push(i),o+=e}}else{const s=cs[u],r=t.slice(o,o+n*s);if("float32"===u)L=new Float32Array(r);else if("int32"===u)L=new Int32Array(r);else if("bool"===u)L=new Uint8Array(r);else{if("complex64"!==u)throw new Error(`Unsupported dtype in weight '${e}': ${u}`);{L=new Float32Array(r);const t=new Float32Array(L.length/2),s=new Float32Array(L.length/2);for(let e=0;e<t.length;e++)t[e]=L[2*e],s[e]=L[2*e+1];const o=As(t,a,"float32"),u=As(s,a,"float32");i[e]=ps(o,u),o.dispose(),u.dispose()}}o+=n*s}"complex64"!==u&&(i[e]=As(L,a,u))}return i}function hs(t){if(1===t.length)return t[0];let e=0;t.forEach((t=>{e+=t.byteLength}));const i=new Uint8Array(e);let s=0;return t.forEach((t=>{i.set(new Uint8Array(t),s),s+=t.byteLength})),i.buffer}function Os(t,e){const i={modelTopology:t.modelTopology,format:t.format,generatedBy:t.generatedBy,convertedBy:t.convertedBy,weightsManifest:e};return null!=t.signature&&(i.signature=t.signature),null!=t.userDefinedMetadata&&(i.userDefinedMetadata=t.userDefinedMetadata),null!=t.modelInitializer&&(i.modelInitializer=t.modelInitializer),null!=t.trainingConfig&&(i.trainingConfig=t.trainingConfig),i}async function zs(t,e){const i={modelTopology:t.modelTopology,format:t.format,generatedBy:t.generatedBy,convertedBy:t.convertedBy};if(null!=t.trainingConfig&&(i.trainingConfig=t.trainingConfig),null!=t.weightsManifest){const[s,o]=await e(t.weightsManifest);i.weightSpecs=s,i.weightData=o}return null!=t.signature&&(i.signature=t.signature),null!=t.userDefinedMetadata&&(i.userDefinedMetadata=t.userDefinedMetadata),null!=t.modelInitializer&&(i.modelInitializer=t.modelInitializer),i}function xs(t){if(t.modelTopology instanceof ArrayBuffer)throw new Error("Expected JSON model topology, received ArrayBuffer.");return{dateSaved:new Date,modelTopologyType:"JSON",modelTopologyBytes:null==t.modelTopology?0:stringByteLength(JSON.stringify(t.modelTopology)),weightSpecsBytes:null==t.weightSpecs?0:stringByteLength(JSON.stringify(t.weightSpecs)),weightDataBytes:null==t.weightData?0:t.weightData.byteLength}}class ds{constructor(){this.saveRouters=[],this.loadRouters=[]}static getInstance(){return null==ds.instance&&(ds.instance=new ds),ds.instance}static registerSaveRouter(t){ds.getInstance().saveRouters.push(t)}static registerLoadRouter(t){ds.getInstance().loadRouters.push(t)}static getSaveHandlers(t){return ds.getHandlers(t,"save")}static getLoadHandlers(t,e){return ds.getHandlers(t,"load",e)}static getHandlers(t,e,i){const s=[];return("load"===e?ds.getInstance().loadRouters:ds.getInstance().saveRouters).forEach((e=>{const o=e(t,i);null!==o&&s.push(o)})),s}}const Ks=t=>ds.registerSaveRouter(t),Ps=t=>ds.registerLoadRouter(t),Ys=t=>ds.getSaveHandlers(t),Qs=(t,e)=>ds.getLoadHandlers(t,e),bs="tensorflowjs",Es=1,Ts="models_store",Ss="model_info_store";class fs{constructor(t){if(this.indexedDB=getIndexedDBFactory(),null==t||!t)throw new Error("For IndexedDB, modelPath must not be null, undefined or empty.");this.modelPath=t}async save(t){if(t.modelTopology instanceof ArrayBuffer)throw new Error("BrowserLocalStorage.save() does not support saving model topology in binary formats yet.");return this.databaseAction(this.modelPath,t)}async load(){return this.databaseAction(this.modelPath)}databaseAction(t,e){return new Promise(((t,i)=>{const s=this.indexedDB.open(bs,Es);s.onupgradeneeded=()=>setUpDatabase(s),s.onsuccess=()=>{const o=s.result;if(null==e){const e=o.transaction(Ts,"readonly"),s=e.objectStore(Ts).get(this.modelPath);s.onsuccess=()=>{if(null==s.result)return o.close(),i(new Error(`Cannot find model with path '${this.modelPath}' in IndexedDB.`));t(s.result.modelArtifacts)},s.onerror=t=>(o.close(),i(s.error)),e.oncomplete=()=>o.close()}else{const s=xs(e),r=o.transaction(Ss,"readwrite");let u=r.objectStore(Ss);const a=u.put({modelPath:this.modelPath,modelArtifactsInfo:s});let n;a.onsuccess=()=>{n=o.transaction(Ts,"readwrite");const a=n.objectStore(Ts).put({modelPath:this.modelPath,modelArtifacts:e,modelArtifactsInfo:s});a.onsuccess=()=>t({modelArtifactsInfo:s}),a.onerror=t=>{u=r.objectStore(Ss);const e=u.delete(this.modelPath);e.onsuccess=()=>(o.close(),i(a.error)),e.onerror=t=>(o.close(),i(a.error))}},a.onerror=t=>(o.close(),i(a.error)),r.oncomplete=()=>{null==n?o.close():n.oncomplete=()=>o.close()}}},s.onerror=t=>i(s.error)}))}}fs.URL_SCHEME="indexeddb://";const qs=t=>we().getBool("IS_BROWSER")&&!Array.isArray(t)&&t.startsWith(fs.URL_SCHEME)?browserIndexedDB(t.slice(fs.URL_SCHEME.length)):null;ds.registerSaveRouter(qs),ds.registerLoadRouter(qs);class ks{constructor(){this.indexedDB=getIndexedDBFactory()}async listModels(){return new Promise(((t,e)=>{const i=this.indexedDB.open(bs,Es);i.onupgradeneeded=()=>setUpDatabase(i),i.onsuccess=()=>{const s=i.result,o=s.transaction(Ss,"readonly"),r=o.objectStore(Ss).getAll();r.onsuccess=()=>{const e={};for(const t of r.result)e[t.modelPath]=t.modelArtifactsInfo;t(e)},r.onerror=t=>(s.close(),e(r.error)),o.oncomplete=()=>s.close()},i.onerror=t=>e(i.error)}))}async removeModel(t){return t=maybeStripScheme$1(t),new Promise(((e,i)=>{const s=this.indexedDB.open(bs,Es);s.onupgradeneeded=()=>setUpDatabase(s),s.onsuccess=()=>{const o=s.result,r=o.transaction(Ss,"readwrite"),u=r.objectStore(Ss),a=u.get(t);let n;a.onsuccess=()=>{if(null==a.result)return o.close(),i(new Error(`Cannot find model with path '${t}' in IndexedDB.`));{const s=u.delete(t),r=()=>{n=o.transaction(Ts,"readwrite");const s=n.objectStore(Ts).delete(t);s.onsuccess=()=>e(a.result.modelArtifactsInfo),s.onerror=t=>i(a.error)};s.onsuccess=r,s.onerror=t=>(r(),o.close(),i(a.error))}},a.onerror=t=>(o.close(),i(a.error)),r.oncomplete=()=>{null==n?o.close():n.oncomplete=()=>o.close()}},s.onerror=t=>i(s.error)}))}}const Gs="/",Ns="tensorflowjs_models",Bs="info",Us="model_topology",Js="weight_specs",Ws="weight_data",Fs="model_metadata";function Rs(t){return{info:[Ns,t,Bs].join(Gs),topology:[Ns,t,Us].join(Gs),weightSpecs:[Ns,t,Js].join(Gs),weightData:[Ns,t,Ws].join(Gs),modelMetadata:[Ns,t,Fs].join(Gs)}}function Hs(t){for(const e of Object.values(t))window.localStorage.removeItem(e)}function Vs(t){const e=t.split(Gs);if(e.length<3)throw new Error(`Invalid key format: ${t}`);return e.slice(1,e.length-1).join(Gs)}class Zs{constructor(t){if(!we().getBool("IS_BROWSER")||"undefined"==typeof window||void 0===window.localStorage)throw new Error("The current environment does not support local storage.");if(this.LS=window.localStorage,null==t||!t)throw new Error("For local storage, modelPath must not be null, undefined or empty.");this.modelPath=t,this.keys=Rs(this.modelPath)}async save(t){if(t.modelTopology instanceof ArrayBuffer)throw new Error("BrowserLocalStorage.save() does not support saving model topology in binary formats yet.");{const e=JSON.stringify(t.modelTopology),i=JSON.stringify(t.weightSpecs),s=xs(t);try{this.LS.setItem(this.keys.info,JSON.stringify(s)),this.LS.setItem(this.keys.topology,e),this.LS.setItem(this.keys.weightSpecs,i),this.LS.setItem(this.keys.weightData,arrayBufferToBase64String(t.weightData));const o={format:t.format,generatedBy:t.generatedBy,convertedBy:t.convertedBy,signature:null!=t.signature?t.signature:void 0,userDefinedMetadata:null!=t.userDefinedMetadata?t.userDefinedMetadata:void 0,modelInitializer:null!=t.modelInitializer?t.modelInitializer:void 0,trainingConfig:null!=t.trainingConfig?t.trainingConfig:void 0};return this.LS.setItem(this.keys.modelMetadata,JSON.stringify(o)),{modelArtifactsInfo:s}}catch(t){throw Hs(this.keys),new Error(`Failed to save model '${this.modelPath}' to local storage: size quota being exceeded is a possible cause of this failure: modelTopologyBytes=${s.modelTopologyBytes}, weightSpecsBytes=${s.weightSpecsBytes}, weightDataBytes=${s.weightDataBytes}.`)}}}async load(){const t=JSON.parse(this.LS.getItem(this.keys.info));if(null==t)throw new Error(`In local storage, there is no model with name '${this.modelPath}'`);if("JSON"!==t.modelTopologyType)throw new Error("BrowserLocalStorage does not support loading non-JSON model topology yet.");const e={},i=JSON.parse(this.LS.getItem(this.keys.topology));if(null==i)throw new Error(`In local storage, the topology of model '${this.modelPath}' is missing.`);e.modelTopology=i;const s=JSON.parse(this.LS.getItem(this.keys.weightSpecs));if(null==s)throw new Error(`In local storage, the weight specs of model '${this.modelPath}' are missing.`);e.weightSpecs=s;const o=this.LS.getItem(this.keys.modelMetadata);if(null!=o){const t=JSON.parse(o);e.format=t.format,e.generatedBy=t.generatedBy,e.convertedBy=t.convertedBy,null!=t.signature&&(e.signature=t.signature),null!=t.userDefinedMetadata&&(e.userDefinedMetadata=t.userDefinedMetadata),null!=t.modelInitializer&&(e.modelInitializer=t.modelInitializer),null!=t.trainingConfig&&(e.trainingConfig=t.trainingConfig)}const r=this.LS.getItem(this.keys.weightData);if(null==r)throw new Error(`In local storage, the binary weight values of model '${this.modelPath}' are missing.`);return e.weightData=base64StringToArrayBuffer(r),e}}Zs.URL_SCHEME="localstorage://";const Xs=t=>we().getBool("IS_BROWSER")&&!Array.isArray(t)&&t.startsWith(Zs.URL_SCHEME)?browserLocalStorage(t.slice(Zs.URL_SCHEME.length)):null;ds.registerSaveRouter(Xs),ds.registerLoadRouter(Xs);class _s{constructor(){Kt(we().getBool("IS_BROWSER"),(()=>"Current environment is not a web browser")),Kt("undefined"==typeof window||void 0!==window.localStorage,(()=>"Current browser does not appear to support localStorage")),this.LS=window.localStorage}async listModels(){const t={},e=Ns+Gs,i=Gs+Bs;for(let s=0;s<this.LS.length;++s){const o=this.LS.key(s);if(o.startsWith(e)&&o.endsWith(i)){t[Vs(o)]=JSON.parse(this.LS.getItem(o))}}return t}async removeModel(t){const e=Rs(t=maybeStripScheme(t));if(null==this.LS.getItem(e.info))throw new Error(`Cannot find model at path '${t}'`);const i=JSON.parse(this.LS.getItem(e.info));return Hs(e),i}}const $s="://";class to{constructor(){this.managers={}}static getInstance(){return null==to.instance&&(to.instance=new to),to.instance}static registerManager(t,e){Kt(null!=t,(()=>"scheme must not be undefined or null.")),t.endsWith($s)&&(t=t.slice(0,t.indexOf($s))),Kt(t.length>0,(()=>"scheme must not be an empty string."));const i=to.getInstance();Kt(null==i.managers[t],(()=>`A model store manager is already registered for scheme '${t}'.`)),i.managers[t]=e}static getManager(t){const e=to.getInstance().managers[t];if(null==e)throw new Error(`Cannot find model manager for scheme '${t}'`);return e}static getSchemes(){return Object.keys(to.getInstance().managers)}}class eo{fetch(t,e){return fetch(t,e)}now(){return performance.now()}encode(t,e){if("utf-8"!==e&&"utf8"!==e)throw new Error(`Browser's encoder only supports utf-8, but got ${e}`);return null==this.textEncoder&&(this.textEncoder=new TextEncoder),this.textEncoder.encode(t)}decode(t,e){return new TextDecoder(e).decode(t)}}if(we().get("IS_BROWSER")){we().setPlatform("browser",new eo);try{to.registerManager(Zs.URL_SCHEME,new _s)}catch(It){}try{to.registerManager(fs.URL_SCHEME,new ks)}catch(It){}}function io(t,e="float32",i){return e=e||"float32",oe(t),new Gi(t,e,i)}function so(t,e){const i=ys(t,"x","cast");if(!Jt(e))throw new Error(`Failed to cast to unknown dtype ${e}`);if("string"===e&&"string"!==i.dtype||"string"!==e&&"string"===i.dtype)throw new Error("Only strings can be casted to strings");const s={x:i},o={dtype:e};return us.runKernel(me,s,o)}const oo=ls({cast_:so});function ro(t){const e={x:ys(t,"x","clone","string_or_numeric")};return us.runKernel(qe,e)}const uo=ls({clone_:ro});function ao(t,e=!1){console.log(t.toString(e))}rs();Ji({buffer:io,cast:oo,clone:uo,print:ao});const no="model",Lo=".json",Mo=".weights.bin";class Co{constructor(t){if(!we().getBool("IS_BROWSER"))throw new Error("browserDownloads() cannot proceed because the current environment is not a browser.");t.startsWith(Co.URL_SCHEME)&&(t=t.slice(Co.URL_SCHEME.length)),null!=t&&0!==t.length||(t=no),this.modelJsonFileName=t+Lo,this.weightDataFileName=t+Mo}async save(t){if("undefined"==typeof document)throw new Error("Browser downloads are not supported in this environment since `document` is not present");const e=window.URL.createObjectURL(new Blob([t.weightData],{type:"application/octet-stream"}));if(t.modelTopology instanceof ArrayBuffer)throw new Error("BrowserDownloads.save() does not support saving model topology in binary formats yet.");{const i=Os(t,[{paths:["./"+this.weightDataFileName],weights:t.weightSpecs}]),s=window.URL.createObjectURL(new Blob([JSON.stringify(i)],{type:"application/json"})),o=null==this.modelJsonAnchor?document.createElement("a"):this.modelJsonAnchor;if(o.download=this.modelJsonFileName,o.href=s,await defer((()=>o.dispatchEvent(new MouseEvent("click")))),null!=t.weightData){const t=null==this.weightDataAnchor?document.createElement("a"):this.weightDataAnchor;t.download=this.weightDataFileName,t.href=e,await defer((()=>t.dispatchEvent(new MouseEvent("click"))))}return{modelArtifactsInfo:xs(t)}}}}Co.URL_SCHEME="downloads://";const wo=t=>we().getBool("IS_BROWSER")&&!Array.isArray(t)&&t.startsWith(Co.URL_SCHEME)?browserDownloads(t.slice(Co.URL_SCHEME.length)):null;async function yo(t,e){null==e&&(e={});const i=null==e.fetchFunc?we().platform.fetch:e.fetchFunc,s=t.map((t=>i(t,e.requestInit,{isBinary:!0}))),o=(null==e.onProgress?await Promise.all(s):await monitorPromisesProgress(s,e.onProgress,0,.5)).map((t=>t.arrayBuffer()));return null==e.onProgress?await Promise.all(o):await monitorPromisesProgress(o,e.onProgress,.5,1)}function vo(t){return async(e,i="",s)=>{const o=e.map((()=>!1)),r={},u=null!=s?s.map((()=>!1)):[],a=[];if(e.forEach(((t,e)=>{let i=0;t.weights.forEach((t=>{const n="quantization"in t?t.quantization.dtype:t.dtype,L=cs[n]*bt(t.shape),M=()=>{o[e]=!0,null==r[e]&&(r[e]=[]),r[e].push({manifestEntry:t,groupOffset:i,sizeBytes:L})};null!=s?s.forEach(((e,i)=>{e===t.name&&(M(),u[i]=!0)})):M(),a.push(t.name),i+=L}))})),!u.every((t=>t))){const t=s.filter(((t,e)=>!u[e]));throw new Error(`Could not find weights in manifest with names: ${t.join(", ")}. \nManifest JSON has weights with names: ${a.join(", ")}.`)}const n=o.reduce(((t,e,i)=>(e&&t.push(i),t)),[]),L=[];n.forEach((t=>{e[t].paths.forEach((t=>{const e=i+(i.endsWith("/")?"":"/")+t;L.push(e)}))}));const M=await t(L),C={};let w=0;return n.forEach((t=>{const i=e[t].paths.length;let s=0;for(let t=0;t<i;t++)s+=M[w+t].byteLength;const o=new ArrayBuffer(s),u=new Uint8Array(o);let a=0;for(let t=0;t<i;t++){const e=new Uint8Array(M[w+t]);u.set(e,a),a+=e.byteLength}r[t].forEach((t=>{const e=ms(o.slice(t.groupOffset,t.groupOffset+t.sizeBytes),[t.manifestEntry]);for(const t in e)C[t]=e[t]})),w+=i})),C}}ds.registerSaveRouter(wo);const Do="application/octet-stream",lo="application/json";class go{constructor(t,e){if(this.DEFAULT_METHOD="POST",null==e&&(e={}),this.weightPathPrefix=e.weightPathPrefix,this.onProgress=e.onProgress,this.weightUrlConverter=e.weightUrlConverter,null!=e.fetchFunc?(Kt("function"==typeof e.fetchFunc,(()=>"Must pass a function that matches the signature of `fetch` (see https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)")),this.fetch=e.fetchFunc):this.fetch=we().platform.fetch,Kt(null!=t&&t.length>0,(()=>"URL path for http must not be null, undefined or empty.")),Array.isArray(t)&&Kt(2===t.length,(()=>`URL paths for http must have a length of 2, (actual length is ${t.length}).`)),this.path=t,null!=e.requestInit&&null!=e.requestInit.body)throw new Error("requestInit is expected to have no pre-existing body, but has one.");this.requestInit=e.requestInit||{}}async save(t){if(t.modelTopology instanceof ArrayBuffer)throw new Error("BrowserHTTPRequest.save() does not support saving model topology in binary formats yet.");const e=Object.assign({method:this.DEFAULT_METHOD},this.requestInit);e.body=new FormData;const i=Os(t,[{paths:["./model.weights.bin"],weights:t.weightSpecs}]);e.body.append("model.json",new Blob([JSON.stringify(i)],{type:lo}),"model.json"),null!=t.weightData&&e.body.append("model.weights.bin",new Blob([t.weightData],{type:Do}),"model.weights.bin");const s=await this.fetch(this.path,e);if(s.ok)return{modelArtifactsInfo:xs(t),responses:[s]};throw new Error(`BrowserHTTPRequest.save() failed due to HTTP response status ${s.status}.`)}async load(){const t=await this.fetch(this.path,this.requestInit);if(!t.ok)throw new Error(`Request to ${this.path} failed with status code ${t.status}. Please verify this URL points to the model JSON of the model to load.`);let e;try{e=await t.json()}catch(t){let e=`Failed to parse model JSON of response from ${this.path}.`;throw this.path.endsWith(".pb")?e+=" Your path contains a .pb file extension. Support for .pb models have been removed in TensorFlow.js 1.0 in favor of .json models. You can re-convert your Python TensorFlow model using the TensorFlow.js 1.0 conversion scripts or you can convert your.pb models with the 'pb2json'NPM script in the tensorflow/tfjs-converter repository.":e+=" Please make sure the server is serving valid JSON for this request.",new Error(e)}const i=e.modelTopology,s=e.weightsManifest;if(null==i&&null==s)throw new Error(`The JSON from HTTP path ${this.path} contains neither model topology or manifest for weights.`);return zs(e,(t=>this.loadWeights(t)))}async loadWeights(t){const e=Array.isArray(this.path)?this.path[1]:this.path,[i,s]=po(e),o=this.weightPathPrefix||i,r=[];for(const e of t)r.push(...e.weights);const u=[],a=[];for(const e of t)for(const t of e.paths)null!=this.weightUrlConverter?a.push(this.weightUrlConverter(t)):u.push(o+t+s);this.weightUrlConverter&&u.push(...await Promise.all(a));return[r,hs(await yo(u,{requestInit:this.requestInit,fetchFunc:this.fetch,onProgress:this.onProgress}))]}}function po(t){const e=t.lastIndexOf("/"),i=t.lastIndexOf("?");return[t.substring(0,e)+"/",i>e?t.substring(i):""]}function jo(t){return null!=t.match(go.URL_SCHEME_REGEX)}go.URL_SCHEME_REGEX=/^https?:\/\//;const Ao=(t,e)=>{if("undefined"==typeof fetch&&(null==e||null==e.fetchFunc))return null;{let i=!0;if(i=Array.isArray(t)?t.every((t=>jo(t))):jo(t),i)return co(t,e)}return null};function co(t,e){return new go(t,e)}function Io(t,e){return co(t,e)}ds.registerSaveRouter(Ao),ds.registerLoadRouter(Ao);var O=Object.freeze({__proto__:null,browserFiles:()=>{},browserHTTPRequest:Io,concatenateArrayBuffers:hs,decodeWeights:ms,encodeWeights:()=>{},fromMemory:()=>{},fromMemorySync:()=>{},getLoadHandlers:Qs,getModelArtifactsForJSON:zs,getModelArtifactsInfoForJSON:xs,getSaveHandlers:Ys,http:co,isHTTPScheme:jo,loadWeights:()=>{},registerLoadRouter:Ps,registerSaveRouter:Ks,weightsLoaderFactory:vo,withSaveHandler:()=>{},withSaveHandlerSync:()=>{},copyModel:()=>{},listModels:()=>{},moveModel:()=>{},removeModel:()=>{}});function mo(t,e,i=!1,s=!1){let o=ys(t,"a","matMul"),r=ys(e,"b","matMul");[o,r]=Xi(o,r);const u={a:o,b:r},a={transposeA:i,transposeB:s};return us.runKernel(ce,u,a)}const ho=ls({matMul_:mo});function Oo(t,e,i=1,s=0){if(e<2)throw new Error(`Error in oneHot: depth must be >=2, but it is ${e}`);const o={indices:ys(t,"indices","oneHot","int32")},r={depth:e,onValue:i,offValue:s};return us.runKernel(Ze,o,r)}const zo=ls({oneHot_:Oo});function xo(){we().set("PROD",!0)}function Ko(){return us}function Po(t,e){return us.tidy(t,e)}function Yo(t){_i(t).forEach((t=>t.dispose()))}function Qo(t){return us.keep(t)}function bo(t,e,i=1){return us.registerBackend(t,e,i)}function Eo(t){const e={x:ys(t,"x","neg")};return us.runKernel(He,e)}const To=ls({neg_:Eo});function So(t){const e={input:ys(t,"input","real")};return us.runKernel(ii,e)}const fo=ls({real_:So});function qo(t,e){const i=t.length,s=[];for(let o=0;o<i;o++){const r=i-1-o,u=t[r]||1;(e[e.length-1-o]||1)>1&&1===u&&s.unshift(r)}return s}function ko(t,e){const i=[];for(let s=0;s<e.length;s++){const o=t[t.length-s-1],r=e.length-s-1,u=e[r];(null==o||1===o&&u>1)&&i.unshift(r)}return i}function Go(t,e){const i=[],s=Math.max(t.length,e.length);for(let o=0;o<s;o++){let s=t[t.length-o-1];null==s&&(s=1);let r=e[e.length-o-1];if(null==r&&(r=1),1===s)i.unshift(r);else if(1===r)i.unshift(s);else{if(s!==r){throw Error(`Operands could not be broadcast together with shapes ${t} and ${e}.`)}i.unshift(s)}}return i}function No(t,e,i){if(e.rank<1)throw new Error(`tf.scatterND() expects the indices to be rank 1 or higher, but the rank was ${e.rank}.`);if(t.rank<1)throw new Error(`tf.scatterND() expects the updates to be rank 1 or higher, but the rank was ${t.rank}.`);if("int32"!==e.dtype)throw new Error(`The dtype of 'indices' should be int32, but got dtype: ${e.dtype}`);if(i.length<1)throw new Error(`Output rank must be greater or equal to 1, but got shape: ${i}`);if(0===i.length){if(0===e.size)throw new Error(`Indices specified for empty output. indices shape: ${e.shape}`);if(0===t.size)throw new Error(`Updates specified for empty output. updates shape: ${t.shape}`)}validateUpdateShape(i,e,t)}function Bo(t,e,i){const s=t.shape.length;Kt(s===e.length,(()=>`Error in slice${s}D: Length of begin ${e} must match the rank of the array (${s}).`)),Kt(s===i.length,(()=>`Error in slice${s}D: Length of size ${i} must match the rank of the array (${s}).`));for(let o=0;o<s;++o)Kt(e[o]+i[o]<=t.shape[o],(()=>`Error in slice${s}D: begin[${o}] + size[${o}] (${e[o]+i[o]}) would overflow input.shape[${o}] (${t.shape[o]})`))}function Uo(t,e,i){let s=i.length;for(let t=0;t<i.length;t++)if(i[t]>1){s=t;break}for(let o=s+1;o<i.length;o++)if(e[o]>0||i[o]!==t[o])return!1;return!0}function Jo(t,e){let i=t.length>0?t[t.length-1]:1;for(let s=0;s<t.length-1;s++)i+=t[s]*e[s];return i}function Wo(t,e,i){let s;const o=t.shape.length;let r;return s="number"==typeof e?[e,...new Array(o-1).fill(0)]:e.length<o?e.concat(new Array(o-e.length).fill(0)):e.slice(),s.forEach((t=>{Kt(-1!==t,(()=>"slice() does not support negative begin indexing."))})),r=null==i?new Array(o).fill(-1):"number"==typeof i?[i,...new Array(o-1).fill(-1)]:i.length<o?i.concat(new Array(o-i.length).fill(-1)):i,r=r.map(((e,i)=>e>=0?e:(Kt(-1===e,(()=>`Negative size values should be exactly -1 but got ${e} for the slice() size at index ${i}.`)),t.shape[i]-s[i]))),[s,r]}ls({confusionMatrix_:()=>{}}),ls({fromPixels_:()=>{}});var z=Object.freeze({__proto__:null,assertParamsValid:Bo,maskToAxes:()=>{},computeOutShape$2:()=>{},stridesWithElidedDims:()=>{},getNormalizedAxes:()=>{},startIndicesWithElidedDims:()=>{},stopIndicesWithElidedDims:()=>{},stridesForAxis:()=>{},startForAxis:()=>{},stopForAxis:()=>{},isSliceContinous:Uo,computeFlatOffset:Jo,parseSliceParams:Wo,sliceInfo:()=>{}});class Fo{getClassName(){return this.constructor.className}static fromConfig(t,e){return new t(e)}}class Ro{constructor(){this.classNameMap={}}static getMap(){return null==Ro.instance&&(Ro.instance=new Ro),Ro.instance}static register(t){Ro.getMap().classNameMap[t.className]=[t,t.fromConfig]}}function Ho(t){Kt(null!=t.className,(()=>"Class being registered does not have the static className property defined.")),Kt("string"==typeof t.className,(()=>"className is required to be a string, but got type "+typeof t.className)),Kt(t.className.length>0,(()=>"Class being registered has an empty-string as its className, which is disallowed.")),Ro.register(t)}function Vo(t,e){let i=ys(t,"a","add"),s=ys(e,"b","add");[i,s]=Xi(i,s);const o={a:i,b:s};return us.runKernel(Ae,o)}const Zo=ls({add_:Vo});function Xo(t,e){let i=ys(t,"a","div"),s=ys(e,"b","div");if([i,s]=Xi(i,s),"int32"===i.dtype&&"int32"===s.dtype)return floorDiv(i,s);const o={a:i,b:s};return us.runKernel(Ye,o,{})}const _o=ls({div_:Xo});function $o(t,e){let i=ys(t,"a","mul"),s=ys(e,"b","mul");[i,s]=Xi(i,s);const o={a:i,b:s};return us.runKernel(Re,o)}const tr=ls({mul_:$o});function er(t){const e=ys(t,"x","abs");if("complex64"===e.dtype){const t={x:e};return us.runKernel(Oe,t)}{const t={x:e};return us.runKernel(je,t)}}const ir=ls({abs_:er});function sr(t,e,i,s,o,r,u="channelsLast"){const[a,n]=parseTupleParam(e);let L;if("channelsLast"===u)L=[a,n,t[3],t[3]];else{if("channelsFirst"!==u)throw new Error(`Unknown dataFormat ${u}`);L=[a,n,t[1],t[1]]}return or(t,L,i,s,o,r,!1,u)}function or(t,e,i,s,o,r,u=!1,a="channelsLast"){let[n,L,M,C]=[-1,-1,-1,-1];if("channelsLast"===a)[n,L,M,C]=t;else{if("channelsFirst"!==a)throw new Error(`Unknown dataFormat ${a}`);[n,C,L,M]=t}const[w,y,,v]=e,[D,l]=parseTupleParam(i),[g,p]=parseTupleParam(s),j=rr(w,g),A=rr(y,p),{padInfo:c,outHeight:I,outWidth:m}=getPadAndOutInfo(o,L,M,D,l,j,A,r,a),h=u?v*C:v;let O;return"channelsFirst"===a?O=[n,h,I,m]:"channelsLast"===a&&(O=[n,I,m,h]),{batchSize:n,dataFormat:a,inHeight:L,inWidth:M,inChannels:C,outHeight:I,outWidth:m,outChannels:h,padInfo:c,strideHeight:D,strideWidth:l,filterHeight:w,filterWidth:y,effectiveFilterHeight:j,effectiveFilterWidth:A,dilationHeight:g,dilationWidth:p,inShape:t,outShape:O,filterShape:e}}function rr(t,e){return e<=1?t:t+(t-1)*(e-1)}function ur(t){if("NHWC"===t)return"channelsLast";if("NCHW"===t)return"channelsFirst";throw new Error(`Unknown dataFormat ${t}`)}function ar(t,e){const i={x:ys(t,"x","reshape","string_or_numeric")},s={shape:e};return us.runKernel(oi,i,s)}const nr=ls({reshape_:ar});function Lr(t,e=0){Kt(t.length>=1,(()=>"Pass at least one tensor to concat"));const i=vs(t,"tensors","concat","string_or_numeric");if("complex64"===i[0].dtype&&i.forEach((t=>{if("complex64"!==t.dtype)throw new Error(`Cannot concatenate complex64 tensors with a tensor\n          with dtype ${t.dtype}. `)})),1===i.length)return uo(i[0]);const s=i,o={axis:e};return us.runKernel(ze,s,o)}const Mr=ls({concat_:Lr});function Cr(t){const e={x:ys(t,"x","sigmoid","float32")};return us.runKernel(ni,e)}const wr=ls({sigmoid_:Cr});function yr(t,e,i){const s=ys(t,"x","slice","string_or_numeric");if(0===s.rank)throw new Error("Slicing scalar is not possible");const o={x:s},r={begin:e,size:i};return us.runKernel(ai,o,r)}const vr=ls({slice_:yr});function Dr(t,e,i){const s=ys(t,"x","bincount"),o=ys(e,"weights","bincount");Kt("int32"===s.dtype,(()=>`Error in bincount: input dtype must be int32, but got ${s.dtype}`)),Kt(i>=0,(()=>`size must be non-negative, but got ${i}.`)),Kt(o.size===s.size||0===o.size,(()=>`Error in bincount: weights must have the same size as input or0-length, but got input shape: ${s.shape}, weights shape: ${o.shape}.`));const r={x:s,weights:o},u={size:i};return us.runKernel(Ie,r,u)}ls({batchNorm2d_:()=>{}}),ls({batchNorm3d_:()=>{}}),ls({batchNorm4d_:()=>{}});const lr=ls({bincount_:Dr});function gr(t,e){let i=ys(t,"broadcastTo","x");const s=i.shape;if(e.some((t=>!(t>0)||t%1!=0)))throw new Error(`broadcastTo(): Invalid broadcast shape [${e}].`);if(e.length<i.rank)throw new Error(`broadcastTo(): shape.length=${e.length} < input.rank=${i.rank}.`);if(e.length>i.rank){const t=i.shape.slice();for(;t.length<e.length;)t.unshift(1);i=nr(i,t)}const o=i.shape,r=Array.from(e);for(let t=e.length-1;t>=0;t--)if(o[t]===e[t])r[t]=1;else if(1!==i.shape[t])throw new Error(`broadcastTo(): [${s}] cannot be broadcast to [${e}].`);const u=r.map(((t,e)=>t>1?e:-1)).filter((t=>t>=0));if(0===u.length)return uo(i);const a={x:i},n={reps:r};return us.runKernel(wi,a,n)}const pr=ls({broadcastTo_:gr});function jr(t,e,i,s,o,r="NHWC",u){Kt(t.length===e.rank,(()=>`Length of inShape (${t.length}) and rank of dy (${e.rank}) must match`));let a=t,n=e,L=!1;3===e.rank&&(L=!0,n=nr(e,[1,e.shape[0],e.shape[1],e.shape[2]]),a=[1,t[0],t[1],t[2]]),Kt(4===a.length,(()=>`Error in conv2dDerInput: inShape must be length 4, but got length ${a.length}.`)),Kt(4===n.rank,(()=>`Error in conv2dDerInput: dy must be rank 4, but got rank ${n.rank}`)),Kt(4===i.rank,(()=>`Error in conv2dDerInput: filter must be rank 4, but got rank ${i.rank}`));const M="NHWC"===r?a[3]:a[1],C="NHWC"===r?n.shape[3]:n.shape[1];Kt(M===i.shape[2],(()=>`Error in conv2dDerInput: depth of input (${M}) must match input depth for filter ${i.shape[2]}.`)),Kt(C===i.shape[3],(()=>`Error in conv2dDerInput: depth of output (${C}) must match output depth for filter ${i.shape[3]}.`)),checkPadOnDimRoundingMode("conv2dDerInput",o,u);const w={dy:n,filter:i},y={strides:s,pad:o,dataFormat:r,dimRoundingMode:u,inputShape:a},v=us.runKernel(de,w,y);return L?nr(v,[v.shape[1],v.shape[2],v.shape[3]]):v}function Ar(t,e){let i=ys(t,"a","equal","string_or_numeric"),s=ys(e,"b","equal","string_or_numeric");[i,s]=Xi(i,s),Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(Qe,o)}ls({concat1d_:()=>{}}),ls({concat2d_:()=>{}}),ls({concat3d_:()=>{}}),ls({concat4d_:()=>{}}),ls({conv1d_:()=>{}}),ls({conv2DBackpropInput_:jr}),ls({conv2dTranspose_:()=>{}}),ls({conv3dTranspose_:()=>{}});const cr=ls({equal_:Ar});function Ir(t,e,i){const s=ys(e,"a","where"),o=ys(i,"b","where"),r=ys(t,"condition","where","bool"),u=Go(Go(r.shape,s.shape),o.shape),a={condition:pr(r,u),t:pr(s,u),e:pr(o,u)};return us.runKernel(ui,a)}const mr=ls({where_:Ir});function hr(t){const e={x:ys(t,"x","zerosLike")};return us.runKernel(vi,e)}const Or=ls({zerosLike_:hr});function zr(t,e){const i=ys(t,"t1","dot"),s=ys(e,"t2","dot");Kt(!(1!==i.rank&&2!==i.rank||1!==s.rank&&2!==s.rank),(()=>`Error in dot: inputs must all be rank 1 or 2, but got ranks ${i.rank} and ${s.rank}.`));const o=1===i.rank?i.size:i.shape[1],r=1===s.rank?s.size:s.shape[0];if(Kt(o===r,(()=>`Error in dot: inner dimensions of inputs must match, but got ${o} and ${r}.`)),1===i.rank&&1===s.rank){const t=nr(i,[1,-1]),e=nr(s,[-1,1]),o=ho(t,e);return nr(o,[])}if(1===i.rank&&2===s.rank){const t=nr(i,[1,-1]),e=nr(s,[s.shape[0],s.shape[1]]),o=ho(t,e);return nr(o,[o.size])}if(2===i.rank&&1===s.rank){const t=nr(s,[-1,1]),e=ho(i,t);return nr(e,[e.size])}{const t=nr(s,[s.shape[0],s.shape[1]]);return ho(i,t)}}const xr=ls({dot_:zr});function dr(t,e){for(let i=0;i<t.length;++i)if(t[t.length-i-1]!==e-1-i)return!1;return!0}function Kr(t,e){const i=[],s=t.length;for(let o=0;o<s;o++)-1===e.indexOf(o)&&i.push(t[o]);return[i,e.map((e=>t[e]))]}function Pr(t,e){const i=e.map((t=>1));return combineLocations(t,i,e)}function Yr(t,e,i){Kt(dr(e,i),(()=>`${t} supports only inner-most axes for now. Got axes ${e} and rank-${i} input.`))}function Qr(t,e){if(dr(t,e))return null;const i=[];for(let s=0;s<e;++s)-1===t.indexOf(s)&&i.push(s);return t.forEach((t=>i.push(t))),i}function br(t,e){const i=[];for(let s=e-t;s<e;++s)i.push(s);return i}function Er(t,e=null,i=!1){const s={x:ys(t,"x","max")},o={reductionIndices:e,keepDims:i};return us.runKernel(Ue,s,o)}const Tr=ls({max_:Er});function Sr(t,e){if((Ft(t)&&"string"!==e||Array.isArray(t))&&"complex64"!==e)throw new Error("Error creating a new Scalar: value must be a primitive (number|boolean|string)");if("string"===e&&Ft(t)&&!(t instanceof Uint8Array))throw new Error("When making a scalar from encoded string, the value must be `Uint8Array`.");return js(t,[],[],e)}function fr(t){const e=ys(t,"x","square");return us.runKernel("Square",{x:e},{})}const qr=ls({square_:fr});function kr(t,e=null,i=!1){let s=ys(t,"x","sum");"bool"===s.dtype&&(s=oo(s,"int32"));const o={x:s},r={axis:e,keepDims:i};return us.runKernel(Li,o,r)}const Gr=ls({sum_:kr});function Nr(t,e="euclidean",i=null,s=!1){const o=Br(t=ys(t,"x","norm"),e,i);let r=o.shape;if(s){const e=Gt(i,t.shape);r=Pr(o.shape,e)}return nr(o,r)}function Br(t,e,i=null){if(0===t.rank)return ir(t);if(1!==t.rank&&null===i)return Br(nr(t,[-1]),e,i);if(1===t.rank||"number"==typeof i||Array.isArray(i)&&1===i.length){if(1===e)return Gr(ir(t),i);if(e===1/0)return Tr(ir(t),i);if(e===-1/0)return min(ir(t),i);if("euclidean"===e||2===e)return sqrt(Gr(pow$1(ir(t),Sr(2,"int32")),i));throw new Error(`Error in norm: invalid ord value: ${e}`)}if(Array.isArray(i)&&2===i.length){if(1===e)return Tr(Gr(ir(t),i[0]),i[1]-1);if(e===1/0)return Tr(Gr(ir(t),i[1]),i[0]);if(e===-1/0)return min(Gr(ir(t),i[1]),i[0]);if("fro"===e||"euclidean"===e)return sqrt(Gr(qr(t),i));throw new Error(`Error in norm: invalid ord value: ${e}`)}throw new Error(`Error in norm: invalid axis: ${i}`)}const Ur=ls({norm_:Nr});function Jr(t){const e={x:ys(t,"x","exp")};return us.runKernel(be,e)}const Wr=ls({exp_:Jr});function Fr(t,e=0){const i=ys(t,"x","expandDims","string_or_numeric");Kt(e<=i.rank,(()=>"Axis must be <= rank of the tensor"));const s={input:i},o={dim:e};return us.runKernel(Ee,s,o)}const Rr=ls({expandDims_:Fr});function Hr(t,e,i=0,s=0){const o={x:ys(t,"x","gather"),indices:ys(e,"indices","gather","int32")},r={axis:i,batchDims:s};return us.runKernel(Se,o,r)}const Vr=ls({gather_:Hr});function Zr(t,e){let i=ys(t,"a","greater","string_or_numeric"),s=ys(e,"b","greater","string_or_numeric");[i,s]=Xi(i,s),Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(fe,o)}const Xr=ls({greater_:Zr});function _r(t){const e={x:ys(t,"x","log","float32")};return us.runKernel(Ge,e)}const $r=ls({log_:_r});function tu(t){const e={x:ys(t,"x","log1p")};return us.runKernel(Ne,e)}const eu=ls({log1p_:tu});function iu(t){return us.customGrad(t)}function su(t,e){let i=ys(t,"a","sub"),s=ys(e,"b","sub");[i,s]=Xi(i,s);const o={a:i,b:s};return us.runKernel(Ci,o)}const ou=ls({sub_:su});function ru(t,e=null,i=!1){const s=ys(t,"x","logSumExp"),o=Gt(e,s.shape),r=Tr(s,o,!0),u=ou(s,r),a=Wr(u),n=Gr(a,o),L=$r(n),M=Zo(nr(r,L.shape),L);if(i){const t=Pr(M.shape,o);return nr(M,t)}return M}const uu=ls({logSumExp_:ru});function au(t,e){const i=ys(t,"a","logicalAnd","bool"),s=ys(e,"b","logicalAnd","bool");Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(Be,o)}const nu=ls({logicalAnd_:au});function Lu(t,e){let i=ys(t,"a","maximum"),s=ys(e,"b","maximum");[i,s]=Xi(i,s),"bool"===i.dtype&&(i=oo(i,"int32"),s=oo(s,"int32")),Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(Je,o)}ls({searchSorted_:()=>{}});const Mu=ls({maximum_:Lu});function Cu(t,e=null,i=!1){const s={x:ys(t,"x","mean")},o={axis:e,keepDims:i};return us.runKernel(We,s,o)}const wu=ls({mean_:Cu});function yu(t,e="float32"){if("complex64"===e){const e=yu(t,"float32"),i=yu(t,"float32");return ps(e,i)}const i=se(bt(t),e);return us.makeTensor(i,t,e)}function vu(t,e="float32"){if("complex64"===e){const e=vu(t,"float32"),i=yu(t,"float32");return ps(e,i)}const i=ie(bt(t),e);return us.makeTensor(i,t,e)}function Du(t,e){let i=ys(t,"a","minimum"),s=ys(e,"b","minimum");[i,s]=Xi(i,s),"bool"===i.dtype&&(i=oo(i,"int32"),s=oo(s,"int32")),Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(Fe,o)}const lu=ls({minimum_:Du});function gu(t,e){let i=ys(t,"a","notEqual","string_or_numeric"),s=ys(e,"b","notEqual","string_or_numeric");[i,s]=Xi(i,s),Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(Ve,o)}ls({multiRNNCell_:()=>{}});const pu=ls({notEqual_:gu});function ju(t,e,i=0){const s=ys(t,"x","pad");if(0===s.rank)throw new Error("pad(scalar) is not defined. Pass non-scalar to pad");const o={paddings:e,constantValue:i},r={x:s};return us.runKernel(_e,r,o)}ls({outerProduct_:()=>{}});const Au=ls({pad_:ju});function cu(t,e=null,i=!1){let s=ys(t,"x","prod");"bool"===s.dtype&&(s=oo(s,"int32"));const o={x:s},r={axis:e,keepDims:i};return us.runKernel(ti,o,r)}ls({pad1d_:()=>{}}),ls({pad2d_:()=>{}}),ls({pad3d_:()=>{}}),ls({pad4d_:()=>{}});const Iu=ls({prod_:cu});var x={exports:{}};!function(t){!function(t,e,i){function s(t){var e=this,i=function(){var t=4022871197,e=function(e){e=String(e);for(var i=0;i<e.length;i++){var s=.02519603282416938*(t+=e.charCodeAt(i));s-=t=s>>>0,t=(s*=t)>>>0,t+=4294967296*(s-=t)}return 2.3283064365386963e-10*(t>>>0)};return e}();e.next=function(){var t=2091639*e.s0+2.3283064365386963e-10*e.c;return e.s0=e.s1,e.s1=e.s2,e.s2=t-(e.c=0|t)},e.c=1,e.s0=i(" "),e.s1=i(" "),e.s2=i(" "),e.s0-=i(t),e.s0<0&&(e.s0+=1),e.s1-=i(t),e.s1<0&&(e.s1+=1),e.s2-=i(t),e.s2<0&&(e.s2+=1),i=null}function o(t,e){return e.c=t.c,e.s0=t.s0,e.s1=t.s1,e.s2=t.s2,e}function r(t,e){var i=new s(t),r=e&&e.state,u=i.next;return u.int32=function(){return 4294967296*i.next()|0},u.double=function(){return u()+11102230246251565e-32*(2097152*u()|0)},u.quick=u,r&&("object"==typeof r&&o(r,i),u.state=function(){return o(i,{})}),u}e&&e.exports?e.exports=r:i&&i.amd?i((function(){return r})):this.alea=r}(0,t,!1)}(x);var d={exports:{}};!function(t){!function(t,e,i){function s(t){var e=this,i="";e.x=0,e.y=0,e.z=0,e.w=0,e.next=function(){var t=e.x^e.x<<11;return e.x=e.y,e.y=e.z,e.z=e.w,e.w^=e.w>>>19^t^t>>>8},t===(0|t)?e.x=t:i+=t;for(var s=0;s<i.length+64;s++)e.x^=0|i.charCodeAt(s),e.next()}function o(t,e){return e.x=t.x,e.y=t.y,e.z=t.z,e.w=t.w,e}function r(t,e){var i=new s(t),r=e&&e.state,u=function(){return(i.next()>>>0)/4294967296};return u.double=function(){do{var t=((i.next()>>>11)+(i.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},u.int32=i.next,u.quick=u,r&&("object"==typeof r&&o(r,i),u.state=function(){return o(i,{})}),u}e&&e.exports?e.exports=r:i&&i.amd?i((function(){return r})):this.xor128=r}(0,t,!1)}(d);var K={exports:{}};!function(t){!function(t,e,i){function s(t){var e=this,i="";e.next=function(){var t=e.x^e.x>>>2;return e.x=e.y,e.y=e.z,e.z=e.w,e.w=e.v,(e.d=e.d+362437|0)+(e.v=e.v^e.v<<4^t^t<<1)|0},e.x=0,e.y=0,e.z=0,e.w=0,e.v=0,t===(0|t)?e.x=t:i+=t;for(var s=0;s<i.length+64;s++)e.x^=0|i.charCodeAt(s),s==i.length&&(e.d=e.x<<10^e.x>>>4),e.next()}function o(t,e){return e.x=t.x,e.y=t.y,e.z=t.z,e.w=t.w,e.v=t.v,e.d=t.d,e}function r(t,e){var i=new s(t),r=e&&e.state,u=function(){return(i.next()>>>0)/4294967296};return u.double=function(){do{var t=((i.next()>>>11)+(i.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},u.int32=i.next,u.quick=u,r&&("object"==typeof r&&o(r,i),u.state=function(){return o(i,{})}),u}e&&e.exports?e.exports=r:i&&i.amd?i((function(){return r})):this.xorwow=r}(0,t,!1)}(K);var P={exports:{}};!function(t){!function(t,e,i){function s(t){var e=this;e.next=function(){var t,i,s=e.x,o=e.i;return t=s[o],i=(t^=t>>>7)^t<<24,i^=(t=s[o+1&7])^t>>>10,i^=(t=s[o+3&7])^t>>>3,i^=(t=s[o+4&7])^t<<7,t=s[o+7&7],i^=(t^=t<<13)^t<<9,s[o]=i,e.i=o+1&7,i},function(t,e){var i,s=[];if(e===(0|e))s[0]=e;else for(e=""+e,i=0;i<e.length;++i)s[7&i]=s[7&i]<<15^e.charCodeAt(i)+s[i+1&7]<<13;for(;s.length<8;)s.push(0);for(i=0;i<8&&0===s[i];++i);for(8==i?s[7]=-1:s[i],t.x=s,t.i=0,i=256;i>0;--i)t.next()}(e,t)}function o(t,e){return e.x=t.x.slice(),e.i=t.i,e}function r(t,e){null==t&&(t=+new Date);var i=new s(t),r=e&&e.state,u=function(){return(i.next()>>>0)/4294967296};return u.double=function(){do{var t=((i.next()>>>11)+(i.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},u.int32=i.next,u.quick=u,r&&(r.x&&o(r,i),u.state=function(){return o(i,{})}),u}e&&e.exports?e.exports=r:i&&i.amd?i((function(){return r})):this.xorshift7=r}(0,t,!1)}(P);var Y={exports:{}};!function(t){!function(t,e,i){function s(t){var e=this;e.next=function(){var t,i,s=e.w,o=e.X,r=e.i;return e.w=s=s+1640531527|0,i=o[r+34&127],t=o[r=r+1&127],i^=i<<13,t^=t<<17,i^=i>>>15,t^=t>>>12,i=o[r]=i^t,e.i=r,i+(s^s>>>16)|0},function(t,e){var i,s,o,r,u,a=[],n=128;for(e===(0|e)?(s=e,e=null):(e+="\0",s=0,n=Math.max(n,e.length)),o=0,r=-32;r<n;++r)e&&(s^=e.charCodeAt((r+32)%e.length)),0===r&&(u=s),s^=s<<10,s^=s>>>15,s^=s<<4,s^=s>>>13,r>=0&&(u=u+1640531527|0,o=0==(i=a[127&r]^=s+u)?o+1:0);for(o>=128&&(a[127&(e&&e.length||0)]=-1),o=127,r=512;r>0;--r)s=a[o+34&127],i=a[o=o+1&127],s^=s<<13,i^=i<<17,s^=s>>>15,i^=i>>>12,a[o]=s^i;t.w=u,t.X=a,t.i=o}(e,t)}function o(t,e){return e.i=t.i,e.w=t.w,e.X=t.X.slice(),e}function r(t,e){null==t&&(t=+new Date);var i=new s(t),r=e&&e.state,u=function(){return(i.next()>>>0)/4294967296};return u.double=function(){do{var t=((i.next()>>>11)+(i.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},u.int32=i.next,u.quick=u,r&&(r.X&&o(r,i),u.state=function(){return o(i,{})}),u}e&&e.exports?e.exports=r:i&&i.amd?i((function(){return r})):this.xor4096=r}(0,t,!1)}(Y);var Q={exports:{}};!function(t){!function(t,e,i){function s(t){var e=this,i="";e.next=function(){var t=e.b,i=e.c,s=e.d,o=e.a;return t=t<<25^t>>>7^i,i=i-s|0,s=s<<24^s>>>8^o,o=o-t|0,e.b=t=t<<20^t>>>12^i,e.c=i=i-s|0,e.d=s<<16^i>>>16^o,e.a=o-t|0},e.a=0,e.b=0,e.c=-1640531527,e.d=1367130551,t===Math.floor(t)?(e.a=t/4294967296|0,e.b=0|t):i+=t;for(var s=0;s<i.length+20;s++)e.b^=0|i.charCodeAt(s),e.next()}function o(t,e){return e.a=t.a,e.b=t.b,e.c=t.c,e.d=t.d,e}function r(t,e){var i=new s(t),r=e&&e.state,u=function(){return(i.next()>>>0)/4294967296};return u.double=function(){do{var t=((i.next()>>>11)+(i.next()>>>0)/4294967296)/(1<<21)}while(0===t);return t},u.int32=i.next,u.quick=u,r&&("object"==typeof r&&o(r,i),u.state=function(){return o(i,{})}),u}e&&e.exports?e.exports=r:i&&i.amd?i((function(){return r})):this.tychei=r}(0,t,!1)}(Q);var b={exports:{}};!function(e){!function(t,i,s){var o,r=256,u="random",a=s.pow(r,6),n=s.pow(2,52),L=2*n,M=255;function C(t,e,o){var M=[],C=D(v((e=1==e?{entropy:!0}:e||{}).entropy?[t,g(i)]:null==t?l():t,3),M),p=new w(M),j=function(){for(var t=p.g(6),e=a,i=0;t<n;)t=(t+i)*r,e*=r,i=p.g(1);for(;t>=L;)t/=2,e/=2,i>>>=1;return(t+i)/e};return j.int32=function(){return 0|p.g(4)},j.quick=function(){return p.g(4)/4294967296},j.double=j,D(g(p.S),i),(e.pass||o||function(t,e,i,o){return o&&(o.S&&y(o,p),t.state=function(){return y(p,{})}),i?(s[u]=t,e):t})(j,C,"global"in e?e.global:this==s,e.state)}function w(t){var e,i=t.length,s=this,o=0,u=s.i=s.j=0,a=s.S=[];for(i||(t=[i++]);o<r;)a[o]=o++;for(o=0;o<r;o++)a[o]=a[u=M&u+t[o%i]+(e=a[o])],a[u]=e;(s.g=function(t){for(var e,i=0,o=s.i,u=s.j,a=s.S;t--;)e=a[o=M&o+1],i=i*r+a[M&(a[o]=a[u=M&u+e])+(a[u]=e)];return s.i=o,s.j=u,i})(r)}function y(t,e){return e.i=t.i,e.j=t.j,e.S=t.S.slice(),e}function v(t,e){var i,s=[],o=typeof t;if(e&&"object"==o)for(i in t)try{s.push(v(t[i],e-1))}catch(t){}return s.length?s:"string"==o?t:t+"\0"}function D(t,e){for(var i,s=t+"",o=0;o<s.length;)e[M&o]=M&(i^=19*e[M&o])+s.charCodeAt(o++);return g(e)}function l(){try{var e;return o&&(e=o.randomBytes)?e=e(r):(e=new Uint8Array(r),(t.crypto||t.msCrypto).getRandomValues(e)),g(e)}catch(e){var s=t.navigator,u=s&&s.plugins;return[+new Date,t,u,t.screen,g(i)]}}function g(t){return String.fromCharCode.apply(0,t)}if(D(s.random(),i),e.exports){e.exports=C;try{o=require("crypto")}catch(t){}}else s["seed"+u]=C}("undefined"!=typeof self?self:t,[],Math)}(b);var E=x.exports,T=d.exports,S=K.exports,f=P.exports,q=Y.exports,k=Q.exports,G=b.exports;function mu(t,e,i=1,s="float32"){if(0===i)throw new Error("Cannot have a step of zero");const o={start:t,stop:e,step:i,dtype:s};return us.runKernel(ei,{},o)}function hu(t){const e={x:ys(t,"x","relu")};return us.runKernel(si,e)}G.alea=E,G.xor128=T,G.xorwow=S,G.xorshift7=f,G.xor4096=q,G.tychei=k;const Ou=ls({relu_:hu});function zu(t,e){const i={x:ys(t,"x","reverse")},s={dims:e};return us.runKernel(ri,i,s)}const xu=ls({reverse_:zu});function du(t){Kt("complex64"===t.dtype,(()=>`The dtype for tf.spectral.fft() must be complex64 but got ${t.dtype}.`));const e={input:t};return us.runKernel(Te,e)}ls({separableConv2d_:()=>{}});const Ku=ls({fft_:du});function Pu(t,e){let i=ys(t,"a","squaredDifference"),s=ys(e,"b","squaredDifference");[i,s]=Xi(i,s),Go(i.shape,s.shape);const o={a:i,b:s};return us.runKernel(Mi,o,{})}const Yu=ls({squaredDifference_:Pu});function Qu(t,e){const i=ys(t,"x","squeeze","string_or_numeric");return nr(i,Nt(i.shape,e).newShape)}const bu=ls({squeeze_:Qu});function Eu(t,e=0){const i=vs(t,"tensors","stack","string_or_numeric");Kt(i.length>=1,(()=>"Pass at least one tensor to tf.stack")),i.length>0&&Kt(e<=i[0].rank,(()=>"Axis must be <= rank of the tensor"));const s=i,o={axis:e};return us.runKernel(Xe,s,o)}const Tu=ls({stack_:Eu});function Su(t,e){Yt(t);const i=Cs(t,e);if(1!==i.length)throw new Error("tensor1d() requires values to be a flat/TypedArray");return js(t,null,i,e)}function fu(t,e,i){if(Yt(t),null!=e&&2!==e.length)throw new Error("tensor2d() requires shape to have two numbers");const s=Cs(t,i);if(2!==s.length&&1!==s.length)throw new Error("tensor2d() requires values to be number[][] or flat/TypedArray");if(1===s.length&&null==e)throw new Error("tensor2d() requires shape to be provided when `values` are a flat/TypedArray");return js(t,e,s,i)}function qu(t,e=0){const i=ys(t,"x","unstack","string_or_numeric");Kt(e>=-i.shape.length&&e<i.shape.length,(()=>`Axis = ${e} is not in [-${i.shape.length}, ${i.shape.length})`));const s={value:i},o={axis:e};return us.runKernel(yi,s,o)}const ku=ls({unstack_:qu});function Gu(t,e,i,s,o,r="NHWC",u){let a=t;3===t.rank&&(a=nr(t,[1,t.shape[0],t.shape[1],t.shape[2]]));let n=e;3===n.rank&&(n=nr(e,[1,e.shape[0],e.shape[1],e.shape[2]])),Kt(4===a.rank,(()=>`Error in conv2dDerFilter: input must be rank 4, but got shape ${a.shape}.`)),Kt(4===n.rank,(()=>`Error in conv2dDerFilter: dy must be rank 4, but got shape ${n.shape}.`)),Kt(4===i.length,(()=>`Error in conv2dDerFilter: filterShape must be length 4, but got ${i}.`));const L="NHWC"===r?a.shape[3]:a.shape[1],M="NHWC"===r?n.shape[3]:n.shape[1];Kt(L===i[2],(()=>`Error in conv2dDerFilter: depth of input ${L}) must match input depth in filter (${i[2]}.`)),Kt(M===i[3],(()=>`Error in conv2dDerFilter: depth of dy (${M}) must match output depth for filter (${i[3]}).`)),checkPadOnDimRoundingMode("conv2dDerFilter",o,u);const C={x:a,dy:n},w={strides:s,pad:o,dataFormat:r,dimRoundingMode:u,filterShape:i};return us.runKernel(xe,C,w)}function Nu(t,e,i){if(null==i||"linear"===i)return t;if("relu"===i)return tr(t,step(e));throw new Error(`Cannot compute gradient for fused activation ${i}.`)}function Bu(t,e){let i=e;const s=ko(t.shape,e.shape);return s.length>0&&(i=Gr(i,s)),nr(i,t.shape)}ls({conv2DBackpropFilter_:Gu});const Uu=(t,e)=>!(t>0)||"linear"===e;function Ju(t,e,i,s,o,r=[1,1],u){let a=t;3===t.rank&&(a=nr(t,[1,t.shape[0],t.shape[1],t.shape[2]]));let n=e;3===n.rank&&(n=nr(e,[1,e.shape[0],e.shape[1],e.shape[2]]));const L={x:a,dy:n},M={strides:s,pad:o,dimRoundingMode:u,dilations:r,filterShape:i};return us.runKernel(Ke,L,M)}function Wu(t,e,i,s,o,r=[1,1],u){let a=e,n=!1;3===e.rank&&(n=!0,a=nr(e,[1,e.shape[0],e.shape[1],e.shape[2]]));const L={dy:a,filter:i},M={strides:s,pad:o,dimRoundingMode:u,dilations:r,inputShape:t},C=us.runKernel(Pe,L,M);return n?nr(C,[C.shape[1],C.shape[2],C.shape[3]]):C}function Fu({a:t,b:e,transposeA:i=!1,transposeB:s=!1,bias:o,activation:r="linear",preluActivationWeights:u,leakyreluAlpha:a=.2}){if(!1===Uu(us.state.gradientDepth,r)){let n=ho(t,e,i,s);return null!=o&&(n=Zo(n,o)),applyActivation(n,r,u,a)}let n=ys(t,"a","fused matMul"),L=ys(e,"b","fused matMul");[n,L]=Xi(n,L);const M=i?n.shape[n.rank-2]:n.shape[n.rank-1],C=s?L.shape[L.rank-1]:L.shape[L.rank-2],w=i?n.shape[n.rank-1]:n.shape[n.rank-2],y=s?L.shape[L.rank-2]:L.shape[L.rank-1],v=n.shape.slice(0,-2),D=L.shape.slice(0,-2),l=bt(v),g=bt(D);Kt(M===C,(()=>`Error in fused matMul: inner shapes (${M}) and (${C}) of Tensors with shapes ${n.shape} and ${L.shape} and transposeA=${i} and transposeB=${s} must match.`));const p=Go(n.shape.slice(0,-2),L.shape.slice(0,-2)).concat([w,y]),j=nr(n,i?[l,M,w]:[l,w,M]),A=nr(L,s?[g,y,C]:[g,C,y]);let c,I;null!=o&&(c=ys(o,"bias","fused matMul"),[c]=Xi(c,n),Go(p,c.shape)),null!=u&&(I=ys(u,"prelu weights","fused matMul"));const m=(t,e)=>{const[u,a,n,L]=e,M=Nu(nr(t,n.shape),n,r);let C,w;if(i||s?!i&&s?(C=ho(M,a,!1,!1),w=ho(M,u,!0,!1)):i&&!s?(C=ho(a,M,!1,!0),w=ho(u,M,!1,!1)):(C=ho(a,M,!0,!0),w=ho(M,u,!0,!0)):(C=ho(M,a,!1,!0),w=ho(u,M,!0,!1)),null!=o){return[C,w,Bu(L,M)]}return[C,w]},h={a:j,b:A,bias:c,preluActivationWeights:I},O={transposeA:i,transposeB:s,activation:r,leakyreluAlpha:a};if(null==o){const t=iu(((t,e,i)=>{const s=us.runKernel(Di,h,O);return i([t,e,s]),{value:nr(s,p),gradFunc:m}}));return t(j,A)}{const t=iu(((t,e,i,s)=>{const o=us.runKernel(Di,h,O);return s([t,e,o,i]),{value:nr(o,p),gradFunc:m}}));return t(j,A,c)}}ls({depthwiseConv2dNativeBackpropFilter_:Ju}),ls({depthwiseConv2dNativeBackpropInput_:Wu});const Ru=ls({fusedMatMul_:Fu});var N=Object.freeze({__proto__:null,conv2d_:()=>{},depthwiseConv2d_:()=>{},matMul:Ru});function Hu(t,e,i,s=!1,o=0){let r=0;const u=[];for(;r+e<=t.size;)u.push(vr(t,r,e)),r+=i;if(s)for(;r<t.size;){const s=r+e-t.size,a=Mr([vr(t,r,e-s),fill$1([s],o)]);u.push(a),r+=i}return 0===u.length?fu([],[0,e]):nr(Mr(u),[u.length,e])}const Vu=ls({frame_:Hu});var B;!function(t){t[t.NONE=0]="NONE",t[t.MEAN=1]="MEAN",t[t.SUM=2]="SUM",t[t.SUM_BY_NONZERO_WEIGHTS=3]="SUM_BY_NONZERO_WEIGHTS"}(B||(B={})),ls({computeWeightedLoss_:()=>{}}),ls({cosineDistance_:()=>{}}),ls({hingeLoss_:()=>{}}),ls({sigmoidCrossEntropy_:()=>{}}),ls({softmaxCrossEntropy_:()=>{}});const Zu={fft:Ku,ifft_:()=>{},rfft_:()=>{},irfft_:()=>{}},Xu={hammingWindow_:()=>{},hannWindow_:()=>{},frame:Vu,stft_:()=>{}},_u={flipLeftRight_:()=>{},grayscaleToRGB_:()=>{},resizeNearestNeighbor_:()=>{},resizeBilinear_:()=>{},rotateWithOffset_:()=>{},cropAndResize_:()=>{},nonMaxSuppression_:()=>{},nonMaxSuppressionAsync_:()=>{},nonMaxSuppressionWithScore_:()=>{},nonMaxSuppressionWithScoreAsync_:()=>{},nonMaxSuppressionPadded_:()=>{},nonMaxSuppressionPaddedAsync_:()=>{},threshold_:()=>{},transform_:()=>{}},$u={bandPart_:()=>{},gramSchmidt_:()=>{},qr_:()=>{}},ta={absoluteDifference_:()=>{},computeWeightedLoss_:()=>{},cosineDistance_:()=>{},hingeLoss_:()=>{},huberLoss_:()=>{},logLoss_:()=>{},meanSquaredError_:()=>{},sigmoidCrossEntropy_:()=>{},softmaxCrossEntropy_:()=>{}},ea={sparseFillEmptyRows_:()=>{},sparseReshape_:()=>{},sparseSegmentMean_:()=>{},sparseSegmentSum_:()=>{}},ia={stringNGrams_:()=>{},stringSplit_:()=>{},stringToHashBucketFast_:()=>{}};class sa extends Fo{minimize(t,e=!1,i){const{value:s,grads:o}=this.computeGradients(t,i);if(null!=i){const t=i.map((t=>({name:t.name,tensor:o[t.name]})));this.applyGradients(t)}else this.applyGradients(o);return Yo(o),e?s:(s.dispose(),null)}get iterations(){return null==this.iterations_&&(this.iterations_=0),this.iterations_}incrementIterations(){this.iterations_=this.iterations+1}computeGradients(t,e){return variableGrads(t,e)}dispose(){null!=this.iterations_&&Yo(this.iterations_)}async saveIterations(){return null==this.iterations_&&(this.iterations_=0),{name:"iter",tensor:Sr(this.iterations_,"int32")}}async getWeights(){throw new Error("getWeights() is not implemented for this optimizer yet.")}async setWeights(t){throw new Error(`setWeights() is not implemented for this optimizer class ${this.getClassName()}`)}async extractIterations(t){return this.iterations_=(await t[0].tensor.data())[0],t.slice(1)}}Object.defineProperty(sa,Symbol.hasInstance,{value:t=>null!=t.minimize&&null!=t.computeGradients&&null!=t.applyGradients});class oa extends sa{constructor(t,e,i=null){super(),this.learningRate=t,this.rho=e,this.epsilon=i,this.accumulatedGrads=[],this.accumulatedUpdates=[],null==i&&(this.epsilon=us.backend.epsilon())}applyGradients(t){(Array.isArray(t)?t.map((t=>t.name)):Object.keys(t)).forEach(((e,i)=>{const s=us.registeredVariables[e];null==this.accumulatedGrads[i]&&(this.accumulatedGrads[i]={originalName:`${e}/accum_grad`,variable:Po((()=>Or(s).variable(false)))}),null==this.accumulatedUpdates[i]&&(this.accumulatedUpdates[i]={originalName:`${e}/accum_var`,variable:Po((()=>Or(s).variable(false)))});const o=Array.isArray(t)?t[i].tensor:t[e];if(null==o)return;const r=this.accumulatedGrads[i].variable,u=this.accumulatedUpdates[i].variable;Po((()=>{const t=Zo(tr(r,this.rho),tr(qr(o),1-this.rho)),e=tr(_o(sqrt(Zo(u,this.epsilon)),sqrt(Zo(r,this.epsilon))),o),i=Zo(tr(u,this.rho),tr(qr(e),1-this.rho));r.assign(t),u.assign(i);const a=Zo(tr(e,-this.learningRate),s);s.assign(a)}))})),this.incrementIterations()}dispose(){null!=this.accumulatedUpdates&&(Yo(this.accumulatedGrads.map((t=>t.variable))),Yo(this.accumulatedUpdates.map((t=>t.variable))))}async getWeights(){const t=[...this.accumulatedGrads,...this.accumulatedUpdates];return[await this.saveIterations()].concat(t.map((t=>({name:t.originalName,tensor:t.variable}))))}async setWeights(t){const e=(t=await this.extractIterations(t)).length/2;this.accumulatedGrads=t.slice(0,e).map((t=>({originalName:t.name,variable:t.tensor.variable(false)}))),this.accumulatedUpdates=t.slice(e,2*e).map((t=>({originalName:t.name,variable:t.tensor.variable(false)})))}getConfig(){return{learningRate:this.learningRate,rho:this.rho,epsilon:this.epsilon}}static fromConfig(t,e){return new t(e.learningRate,e.rho,e.epsilon)}}oa.className="Adadelta",Ho(oa);class ra extends sa{constructor(t,e=.1){super(),this.learningRate=t,this.initialAccumulatorValue=e,this.accumulatedGrads=[]}applyGradients(t){(Array.isArray(t)?t.map((t=>t.name)):Object.keys(t)).forEach(((e,i)=>{const s=us.registeredVariables[e];if(null==this.accumulatedGrads[i]){const t=!1;this.accumulatedGrads[i]={originalName:`${e}/accumulator`,variable:Po((()=>fill$1(s.shape,this.initialAccumulatorValue).variable(t)))}}const o=Array.isArray(t)?t[i].tensor:t[e];if(null==o)return;const r=this.accumulatedGrads[i].variable;Po((()=>{const t=Zo(r,qr(o));r.assign(t);const e=Zo(tr(_o(o,sqrt(Zo(t,us.backend.epsilon()))),-this.learningRate),s);s.assign(e)}))})),this.incrementIterations()}dispose(){null!=this.accumulatedGrads&&Yo(this.accumulatedGrads.map((t=>t.variable)))}async getWeights(){return[await this.saveIterations()].concat(this.accumulatedGrads.map((t=>({name:t.originalName,tensor:t.variable}))))}async setWeights(t){t=await this.extractIterations(t);this.accumulatedGrads=t.map((t=>({originalName:t.name,variable:t.tensor.variable(false)})))}getConfig(){return{learningRate:this.learningRate,initialAccumulatorValue:this.initialAccumulatorValue}}static fromConfig(t,e){return new t(e.learningRate,e.initialAccumulatorValue)}}ra.className="Adagrad",Ho(ra);class ua extends sa{constructor(t,e,i,s=null){super(),this.learningRate=t,this.beta1=e,this.beta2=i,this.epsilon=s,this.accumulatedFirstMoment=[],this.accumulatedSecondMoment=[],Po((()=>{this.accBeta1=Sr(e).variable(),this.accBeta2=Sr(i).variable()})),null==s&&(this.epsilon=us.backend.epsilon())}applyGradients(t){const e=Array.isArray(t)?t.map((t=>t.name)):Object.keys(t);Po((()=>{const i=ou(1,this.accBeta1),s=ou(1,this.accBeta2);e.forEach(((e,o)=>{const r=us.registeredVariables[e];null==this.accumulatedFirstMoment[o]&&(this.accumulatedFirstMoment[o]={originalName:`${e}/m`,variable:Po((()=>Or(r).variable(false)))}),null==this.accumulatedSecondMoment[o]&&(this.accumulatedSecondMoment[o]={originalName:`${e}/v`,variable:Po((()=>Or(r).variable(false)))});const u=Array.isArray(t)?t[o].tensor:t[e];if(null==u)return;const a=this.accumulatedFirstMoment[o].variable,n=this.accumulatedSecondMoment[o].variable,L=Zo(tr(a,this.beta1),tr(u,1-this.beta1)),M=Zo(tr(n,this.beta2),tr(qr(u),1-this.beta2)),C=_o(L,i),w=_o(M,s);a.assign(L),n.assign(M);const y=Zo(tr(_o(C,Zo(sqrt(w),this.epsilon)),-this.learningRate),r);r.assign(y)})),this.accBeta1.assign(tr(this.accBeta1,this.beta1)),this.accBeta2.assign(tr(this.accBeta2,this.beta2))})),this.incrementIterations()}dispose(){this.accBeta1.dispose(),this.accBeta2.dispose(),null!=this.accumulatedFirstMoment&&Yo(this.accumulatedFirstMoment.map((t=>t.variable))),null!=this.accumulatedSecondMoment&&Yo(this.accumulatedSecondMoment.map((t=>t.variable)))}async getWeights(){const t=[...this.accumulatedFirstMoment,...this.accumulatedSecondMoment];return[await this.saveIterations()].concat(t.map((t=>({name:t.originalName,tensor:t.variable}))))}async setWeights(t){t=await this.extractIterations(t),Po((()=>{this.accBeta1.assign(pow$1(this.beta1,this.iterations_+1)),this.accBeta2.assign(pow$1(this.beta2,this.iterations_+1))}));const e=t.length/2;this.accumulatedFirstMoment=t.slice(0,e).map((t=>({originalName:t.name,variable:t.tensor.variable(false)}))),this.accumulatedSecondMoment=t.slice(e,2*e).map((t=>({originalName:t.name,variable:t.tensor.variable(false)})))}getConfig(){return{learningRate:this.learningRate,beta1:this.beta1,beta2:this.beta2,epsilon:this.epsilon}}static fromConfig(t,e){return new t(e.learningRate,e.beta1,e.beta2,e.epsilon)}}ua.className="Adam",Ho(ua);class aa extends sa{constructor(t,e,i,s=null,o=0){super(),this.learningRate=t,this.beta1=e,this.beta2=i,this.epsilon=s,this.decay=o,this.accumulatedFirstMoment=[],this.accumulatedWeightedInfNorm=[],Po((()=>{this.iteration=Sr(0).variable(),this.accBeta1=Sr(e).variable()})),null==s&&(this.epsilon=us.backend.epsilon())}applyGradients(t){const e=Array.isArray(t)?t.map((t=>t.name)):Object.keys(t);Po((()=>{const i=ou(1,this.accBeta1),s=_o(-this.learningRate,Zo(tr(this.iteration,this.decay),1));e.forEach(((e,o)=>{const r=us.registeredVariables[e];null==this.accumulatedFirstMoment[o]&&(this.accumulatedFirstMoment[o]={originalName:`${e}/m`,variable:Or(r).variable(false)}),null==this.accumulatedWeightedInfNorm[o]&&(this.accumulatedWeightedInfNorm[o]={originalName:`${e}/v`,variable:Or(r).variable(false)});const u=Array.isArray(t)?t[o].tensor:t[e];if(null==u)return;const a=this.accumulatedFirstMoment[o].variable,n=this.accumulatedWeightedInfNorm[o].variable,L=Zo(tr(a,this.beta1),tr(u,1-this.beta1)),M=tr(n,this.beta2),C=ir(u),w=Mu(M,C);a.assign(L),n.assign(w);const y=Zo(tr(_o(s,i),_o(L,Zo(w,this.epsilon))),r);r.assign(y)})),this.iteration.assign(Zo(this.iteration,1)),this.accBeta1.assign(tr(this.accBeta1,this.beta1))})),this.incrementIterations()}dispose(){this.accBeta1.dispose(),this.iteration.dispose(),null!=this.accumulatedFirstMoment&&Yo(this.accumulatedFirstMoment.map((t=>t.variable))),null!=this.accumulatedWeightedInfNorm&&Yo(this.accumulatedWeightedInfNorm.map((t=>t.variable)))}async getWeights(){throw new Error("getWeights() is not implemented for Adamax yet.")}async setWeights(t){throw new Error("setWeights() is not implemented for Adamax yet.")}getConfig(){return{learningRate:this.learningRate,beta1:this.beta1,beta2:this.beta2,epsilon:this.epsilon,decay:this.decay}}static fromConfig(t,e){return new t(e.learningRate,e.beta1,e.beta2,e.epsilon,e.decay)}}aa.className="Adamax",Ho(aa);class na extends sa{constructor(t){super(),this.learningRate=t,this.setLearningRate(t)}applyGradients(t){(Array.isArray(t)?t.map((t=>t.name)):Object.keys(t)).forEach(((e,i)=>{const s=Array.isArray(t)?t[i].tensor:t[e];if(null==s)return;const o=us.registeredVariables[e];Po((()=>{const t=Zo(tr(this.c,s),o);o.assign(t)}))})),this.incrementIterations()}setLearningRate(t){this.learningRate=t,null!=this.c&&this.c.dispose(),this.c=Qo(Sr(-t))}dispose(){this.c.dispose()}async getWeights(){return[await this.saveIterations()]}async setWeights(t){if(0!==(t=await this.extractIterations(t)).length)throw new Error("SGD optimizer does not have settable weights.")}getConfig(){return{learningRate:this.learningRate}}static fromConfig(t,e){return new t(e.learningRate)}}na.className="SGD",Ho(na);class La extends na{constructor(t,e,i=!1){super(t),this.learningRate=t,this.momentum=e,this.useNesterov=i,this.accumulations=[],this.m=Sr(this.momentum)}applyGradients(t){(Array.isArray(t)?t.map((t=>t.name)):Object.keys(t)).forEach(((e,i)=>{const s=us.registeredVariables[e];if(null==this.accumulations[i]){const t=!1;this.accumulations[i]={originalName:`${e}/momentum`,variable:Po((()=>Or(s).variable(t)))}}const o=this.accumulations[i].variable,r=Array.isArray(t)?t[i].tensor:t[e];null!=r&&Po((()=>{let t;const e=Zo(tr(this.m,o),r);t=this.useNesterov?Zo(tr(this.c,Zo(r,tr(e,this.m))),s):Zo(tr(this.c,e),s),o.assign(e),s.assign(t)}))})),this.incrementIterations()}dispose(){this.m.dispose(),null!=this.accumulations&&Yo(this.accumulations.map((t=>t.variable)))}setMomentum(t){this.momentum=t}async getWeights(){return[await this.saveIterations()].concat(this.accumulations.map((t=>({name:t.originalName,tensor:t.variable}))))}async setWeights(t){t=await this.extractIterations(t);this.accumulations=t.map((t=>({originalName:t.name,variable:t.tensor.variable(false)})))}getConfig(){return{learningRate:this.learningRate,momentum:this.momentum,useNesterov:this.useNesterov}}static fromConfig(t,e){return new t(e.learningRate,e.momentum,e.useNesterov)}}La.className="Momentum",Ho(La);class Ma extends sa{constructor(t,e=.9,i=0,s=null,o=!1){if(super(),this.learningRate=t,this.decay=e,this.momentum=i,this.epsilon=s,this.accumulatedMeanSquares=[],this.accumulatedMoments=[],this.accumulatedMeanGrads=[],this.centered=o,null==s&&(this.epsilon=us.backend.epsilon()),null==t)throw new Error("learningRate for RMSPropOptimizer must be defined.")}applyGradients(t){(Array.isArray(t)?t.map((t=>t.name)):Object.keys(t)).forEach(((e,i)=>{const s=us.registeredVariables[e],o=!1;null==this.accumulatedMeanSquares[i]&&(this.accumulatedMeanSquares[i]={originalName:`${e}/rms`,variable:Po((()=>Or(s).variable(o)))}),null==this.accumulatedMoments[i]&&(this.accumulatedMoments[i]={originalName:`${e}/momentum`,variable:Po((()=>Or(s).variable(o)))}),null==this.accumulatedMeanGrads[i]&&this.centered&&(this.accumulatedMeanGrads[i]={originalName:`${e}/mg`,variable:Po((()=>Or(s).variable(o)))});const r=Array.isArray(t)?t[i].tensor:t[e];if(null==r)return;const u=this.accumulatedMeanSquares[i].variable,a=this.accumulatedMoments[i].variable;Po((()=>{const t=Zo(tr(u,this.decay),tr(qr(r),1-this.decay));if(this.centered){const e=this.accumulatedMeanGrads[i].variable,o=Zo(tr(e,this.decay),tr(r,1-this.decay)),n=_o(tr(r,this.learningRate),sqrt(ou(t,Zo(qr(o),this.epsilon)))),L=Zo(tr(a,this.momentum),n);u.assign(t),e.assign(o),a.assign(L);const M=ou(s,L);s.assign(M)}else{const t=Zo(tr(u,this.decay),tr(qr(r),1-this.decay)),e=Zo(tr(a,this.momentum),_o(tr(r,this.learningRate),sqrt(Zo(t,this.epsilon))));u.assign(t),a.assign(e);const i=ou(s,e);s.assign(i)}}))})),this.incrementIterations()}dispose(){null!=this.accumulatedMeanSquares&&Yo(this.accumulatedMeanSquares.map((t=>t.variable))),null!=this.accumulatedMeanGrads&&this.centered&&Yo(this.accumulatedMeanGrads.map((t=>t.variable))),null!=this.accumulatedMoments&&Yo(this.accumulatedMoments.map((t=>t.variable)))}async getWeights(){const t=[...this.accumulatedMeanSquares,...this.accumulatedMoments];return this.centered&&t.push(...this.accumulatedMeanGrads),[await this.saveIterations()].concat(t.map((t=>({name:t.originalName,tensor:t.variable}))))}async setWeights(t){t=await this.extractIterations(t);const e=this.centered?t.length/3:t.length/2,i=!1;this.accumulatedMeanSquares=t.slice(0,e).map((t=>({originalName:t.name,variable:t.tensor.variable(i)}))),this.accumulatedMoments=t.slice(e,2*e).map((t=>({originalName:t.name,variable:t.tensor.variable(i)}))),this.centered&&(this.accumulatedMeanGrads=t.slice(2*e,3*e).map((t=>({originalName:t.name,variable:t.tensor.variable(i)}))))}getConfig(){return{learningRate:this.learningRate,decay:this.decay,momentum:this.momentum,epsilon:this.epsilon,centered:this.centered}}static fromConfig(t,e){return new t(e.learningRate,e.decay,e.momentum,e.epsilon,e.centered)}}function Ca(t,e){const i=t[0].length;t.forEach(((t,e)=>{Kt(t.length===i,(()=>`Error in concat${i}D: rank of tensors[${e}] must be the same as the rank of the rest (${i})`))})),Kt(e>=0&&e<i,(()=>`Error in concat${i}D: axis must be between 0 and ${i-1}.`));const s=t[0];t.forEach(((t,o)=>{for(let r=0;r<i;r++)Kt(r===e||t[r]===s[r],(()=>`Error in concat${i}D: Shape of tensors[${o}] (${t}) does not match the shape of the rest (${s}) along the non-concatenated axis ${o}.`))}))}function wa(t,e){const i=t[0].slice();for(let s=1;s<t.length;s++)i[e]+=t[s][e];return i}Ma.className="RMSProp",Ho(Ma),"undefined"!=typeof requestAnimationFrame?requestAnimationFrame:"undefined"!=typeof setImmediate&&setImmediate;const ya=30;function va(t){return t<=ya?t:_t(t,Math.floor(Math.sqrt(t)))}const Da=1.7580993408473768,la=1.0507009873554805,ga=.3275911,pa=.254829592,ja=-.284496736,Aa=1.421413741,ca=-1.453152027,Ia=1.061405429;function ma(t,e,i,s){const o=e.shape.length,r=t.shape.length;if(0!==s&&(s<-o||s>o))throw new Error(`Expect batchDims in the range of [-${o}, ${o}], but got ${s}`);if(s<0&&(s+=o),s>r)throw new Error(`batchDims (${s}) must be less than rank(x) (\n    ${r}).`);if(i<s)throw new Error(`batchDims (${s}) must be less than or equal to axis (${i}).`);for(let i=0;i<s;++i)if(t.shape[i]!==e.shape[i])throw new Error(`x.shape[${i}]: ${t.shape[i]} should be equal to indices.shape[${i}]: ${e.shape[i]}.`);const u=t.shape[i],a=[];let n=1,L=1,M=1;for(let e=0;e<s;++e)a.push(t.shape[e]),n*=t.shape[e];for(let e=s;e<i;e++)a.push(t.shape[e]),L*=t.shape[e];for(let t=s;t<o;t++)a.push(e.shape[t]);for(let e=i+1;e<r;e++)a.push(t.shape[e]),M*=t.shape[e];return{batchSize:n,sliceSize:M,outerSize:L,dimSize:u,outputShape:a}}var U=Object.freeze({__proto__:null,segOpComputeOptimalWindowSize:()=>{},computeOutShape$2:()=>{},collectGatherOpShapeInfo:ma}),J=Object.freeze({__proto__:null,slice_util:z,segment_util:U,fromUint8ToStringArray:()=>{},fromStringArrayToUint8:()=>{},upcastType:Vi,axesAreInnerMostDims:dr,combineLocations:()=>{},computeOutAndReduceShapes:Kr,expandShapeToKeepDim:Pr,assertAxesAreInnerMostDims:Yr,getAxesPermutation:Qr,getUndoAxesPermutation:()=>{},getInnerMostAxes:br,getBroadcastDims:qo,getReductionAxes:ko,assertAndGetBroadcastShape:Go,assertParamsConsistent:Ca,computeOutShape$2:()=>{},computeDilation2DInfo:()=>{},computePool2DInfo:sr,computePool3DInfo:()=>{},computeConv2DInfo:or,computeConv3DInfo:()=>{},computeDefaultPad:()=>{},tupleValuesAreOne:()=>{},eitherStridesOrDilationsAreOne:()=>{},convertConv2DDataFormat:ur,checkPadOnDimRoundingMode:()=>{},getFusedDyActivation:Nu,getFusedBiasGradient:Bu,applyActivation:()=>{},shouldFuse:Uu,PARALLELIZE_THRESHOLD:ya,computeOptimalWindowSize:va,getImageCenter:()=>{},getReshaped:()=>{},getPermuted:()=>{},getReshapedPermuted:()=>{},getSliceBeginCoords:()=>{},getSliceSize:()=>{},prepareAndValidate:()=>{},validateUpdateShape:()=>{},validateInput:No,calculateShapes:()=>{},SELU_SCALEALPHA:Da,SELU_SCALE:la,ERF_P:ga,ERF_A1:pa,ERF_A2:ja,ERF_A3:Aa,ERF_A4:ca,ERF_A5:Ia,warn:()=>{},log:li,mergeRealAndImagArrays:()=>{},splitRealAndImagArrays:()=>{},complexWithEvenIndex:()=>{},complexWithOddIndex:()=>{},getComplexWithIndex:()=>{},assignToTypedArray:()=>{},exponents:()=>{},exponent:()=>{},decodeEinsumEquation:()=>{},getEinsumPermutation:()=>{},checkEinsumDimSizes:()=>{},getEinsumComputePath:()=>{},isIdentityPermutation:()=>{},prepareSplitSize:()=>{},getSparseFillEmptyRowsIndicesDenseShapeMismatch:()=>{},getSparseFillEmptyRowsNegativeIndexErrorMessage:()=>{},getSparseFillEmptyRowsOutOfRangeIndexErrorMessage:()=>{},getSparseReshapeMultipleNegativeOneOutputDimErrorMessage:()=>{},getSparseReshapeNegativeOutputDimErrorMessage:()=>{},getSparseReshapeEmptyTensorZeroOutputDimErrorMessage:()=>{},getSparseReshapeInputOutputMultipleErrorMessage:()=>{},getSparseReshapeInputOutputMismatchErrorMessage:()=>{},getSparseSegmentReductionNegativeSegmentIdsErrorMessage:()=>{},getSparseSegmentReductionNonIncreasingSegmentIdsErrorMessage:()=>{},getSparseSegmentReductionSegmentIdOutOfRangeErrorMessage:()=>{},getSparseSegmentReductionIndicesOutOfRangeErrorMessage:()=>{}});var W,F;we().registerFlag("KEEP_INTERMEDIATE_TENSORS",(()=>!1),(t=>{t&&console.warn("Keep intermediate tensors is ON. This will print the values of all intermediate tensors during model inference. Not all models support this mode. For details, check e2e/benchmarks/ model_config.js. This significantly impacts performance.")})),function(t){t[t.DT_INVALID=0]="DT_INVALID",t[t.DT_FLOAT=1]="DT_FLOAT",t[t.DT_DOUBLE=2]="DT_DOUBLE",t[t.DT_INT32=3]="DT_INT32",t[t.DT_UINT8=4]="DT_UINT8",t[t.DT_INT16=5]="DT_INT16",t[t.DT_INT8=6]="DT_INT8",t[t.DT_STRING=7]="DT_STRING",t[t.DT_COMPLEX64=8]="DT_COMPLEX64",t[t.DT_INT64=9]="DT_INT64",t[t.DT_BOOL=10]="DT_BOOL",t[t.DT_QINT8=11]="DT_QINT8",t[t.DT_QUINT8=12]="DT_QUINT8",t[t.DT_QINT32=13]="DT_QINT32",t[t.DT_BFLOAT16=14]="DT_BFLOAT16",t[t.DT_QINT16=15]="DT_QINT16",t[t.DT_QUINT16=16]="DT_QUINT16",t[t.DT_UINT16=17]="DT_UINT16",t[t.DT_COMPLEX128=18]="DT_COMPLEX128",t[t.DT_HALF=19]="DT_HALF",t[t.DT_RESOURCE=20]="DT_RESOURCE",t[t.DT_VARIANT=21]="DT_VARIANT",t[t.DT_UINT32=22]="DT_UINT32",t[t.DT_UINT64=23]="DT_UINT64",t[t.DT_FLOAT_REF=101]="DT_FLOAT_REF",t[t.DT_DOUBLE_REF=102]="DT_DOUBLE_REF",t[t.DT_INT32_REF=103]="DT_INT32_REF",t[t.DT_UINT8_REF=104]="DT_UINT8_REF",t[t.DT_INT16_REF=105]="DT_INT16_REF",t[t.DT_INT8_REF=106]="DT_INT8_REF",t[t.DT_STRING_REF=107]="DT_STRING_REF",t[t.DT_COMPLEX64_REF=108]="DT_COMPLEX64_REF",t[t.DT_INT64_REF=109]="DT_INT64_REF",t[t.DT_BOOL_REF=110]="DT_BOOL_REF",t[t.DT_QINT8_REF=111]="DT_QINT8_REF",t[t.DT_QUINT8_REF=112]="DT_QUINT8_REF",t[t.DT_QINT32_REF=113]="DT_QINT32_REF",t[t.DT_BFLOAT16_REF=114]="DT_BFLOAT16_REF",t[t.DT_QINT16_REF=115]="DT_QINT16_REF",t[t.DT_QUINT16_REF=116]="DT_QUINT16_REF",t[t.DT_UINT16_REF=117]="DT_UINT16_REF",t[t.DT_COMPLEX128_REF=118]="DT_COMPLEX128_REF",t[t.DT_HALF_REF=119]="DT_HALF_REF",t[t.DT_RESOURCE_REF=120]="DT_RESOURCE_REF",t[t.DT_VARIANT_REF=121]="DT_VARIANT_REF",t[t.DT_UINT32_REF=122]="DT_UINT32_REF",t[t.DT_UINT64_REF=123]="DT_UINT64_REF"}(W||(W={})),function(t){!function(t){t[t.LEGACY=0]="LEGACY",t[t.V1=1]="V1",t[t.V2=2]="V2"}(t.CheckpointFormatVersion||(t.CheckpointFormatVersion={}))}(F||(F={}));const ha={};function Oa(t){return ha[t]}function za(t,e,i,s,o){const r=e.inputParams[t];if(r&&void 0!==r.inputIndexStart){const t=r.inputIndexStart,u=0===r.inputIndexEnd?void 0:void 0===r.inputIndexEnd?t+1:r.inputIndexEnd;if("tensor"===r.type)return xa(e.inputNames[r.inputIndexStart],i,s,o);if("tensors"===r.type){return e.inputNames.slice(t,u).map((t=>xa(t,i,s,o)))}const a=xa(e.inputNames.slice(t)[0],i,s,o),n=a.dataSync();return"number"===r.type?n[0]:ee(a.shape,n)}const u=e.attrParams[t];return u&&u.value}function xa(t,e,i,s){const[o,r]=Ya(t);if(null!=s){const t=s.getHashTableHandleByName(o);if(null!=t)return t}const u=i.currentContextIds.find((t=>!!e[Pa(o,t)]));return void 0!==u?e[Pa(o,u)][r]:void 0}function da(t,e,i){return e[Pa(t,i.currentContextId)]}function Ka(t,e){const[i,s,o]=Ya(t);return[Pa(i,e&&e.currentContextId),s,o]}function Pa(t,e){return e?`${t}-${e}`:t}function Ya(t){const e=t.split(":");if(1===e.length)return[t,0,void 0];const i=e[0],s=3===e.length?e[1]:void 0;return[i,Number(e[e.length-1]),s]}function Qa(t,e,i){let s=za("pad",t,e,i);if("explicit"===s){s=za("explicitPaddings",t,e,i);const o=[[0,0],[0,0],[0,0],[0,0]];for(let t=0;t<4;t++)o[t][0]=s[2*t],o[t][1]=s[2*t+1];return o}return s}function ba(t){return t.kept?t:uo(t)}const Ea=[{tfOpName:"Add",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"AddV2",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"AddN",category:"arithmetic",inputs:[{start:0,end:0,name:"tensors",type:"tensors"}]},{tfOpName:"BiasAdd",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0}]},{tfOpName:"Sub",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"RealDiv",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Div",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"DivNoNan",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"FloorDiv",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Mul",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Maximum",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Minimum",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Pow",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"SquaredDifference",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Mod",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"FloorMod",category:"arithmetic",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]}];var R=Object.freeze({__proto__:null,json:Ea});const Ta=[{tfOpName:"Abs",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Acos",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Asin",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Atan",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Atan2",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"y",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Ceil",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"ClipByValue",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"clipValueMin",type:"number"},{start:2,name:"clipValueMax",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Complex",category:"basic_math",inputs:[{start:0,name:"real",type:"tensor"},{start:1,name:"imag",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"ComplexAbs",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Cos",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Cosh",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Elu",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Exp",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Floor",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Log",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Imag",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"Tout",name:"outputType",type:"dtype",notSupported:!0}]},{tfOpName:"Neg",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Real",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"Tout",name:"outputType",type:"dtype",notSupported:!0}]},{tfOpName:"Prelu",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"alpha",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Relu",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Relu6",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Selu",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Sigmoid",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Sin",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Sinh",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Sqrt",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Rsqrt",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Square",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Tan",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Tanh",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Sign",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Round",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Expm1",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Log1p",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Reciprocal",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Softplus",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Asinh",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Acosh",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Atanh",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Erf",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Prod",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axes",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool",notSupported:!0},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"LeakyRelu",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"alpha",name:"alpha",type:"number",defaultValue:.2},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"IsNan",category:"basic_math",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]}];var H=Object.freeze({__proto__:null,json:Ta});const Sa=[{tfOpName:"EmptyTensorList",category:"control",inputs:[{start:0,name:"elementShape",type:"shape"},{start:1,name:"maxNumElements",type:"number"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"LoopCond",category:"control",inputs:[{start:0,name:"pred",type:"tensor"}]},{tfOpName:"Switch",category:"control",inputs:[{start:0,name:"data",type:"tensor"},{start:1,name:"pred",type:"tensor"}]},{tfOpName:"Merge",category:"control",inputs:[{start:0,end:0,name:"tensors",type:"tensors"}]},{tfOpName:"Enter",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"frame_name",name:"frameName",type:"string"},{tfName:"is_constant",name:"isConstant",type:"bool"}]},{tfOpName:"Exit",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"NextIteration",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"TensorArrayV3",category:"control",inputs:[{start:0,name:"size",type:"number"}],attrs:[{tfName:"dtype",name:"dtype",type:"dtype"},{tfName:"element_shape",name:"elementShape",type:"shape"},{tfName:"dynamic_size",name:"dynamicSize",type:"bool"},{tfName:"clear_after_read",name:"clearAfterRead",type:"bool"},{tfName:"identical_element_shapes",name:"identicalElementShapes",type:"bool"},{tfName:"tensor_array_name",name:"name",type:"string"}]},{tfOpName:"TensorArrayWriteV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"index",type:"number"},{start:2,name:"tensor",type:"tensor"},{start:3,name:"flowIn",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"TensorArrayReadV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"index",type:"number"},{start:2,name:"flowIn",type:"number"}],attrs:[{tfName:"dtype",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"TensorArrayGatherV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"indices",type:"number[]"},{start:2,name:"flowIn",type:"number"}],attrs:[{tfName:"dtype",name:"dtype",type:"dtype"},{tfName:"element_shape",name:"elementShape",type:"shape"}]},{tfOpName:"TensorArrayScatterV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"indices",type:"number[]"},{start:2,name:"tensor",type:"tensor"},{start:3,name:"flowIn",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype"}]},{tfOpName:"TensorArrayConcatV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"flowIn",type:"number"}],attrs:[{tfName:"dtype",name:"dtype",type:"dtype"},{tfName:"element_shape_except0",name:"elementShapeExcept0",type:"shape",notSupported:!0}]},{tfOpName:"TensorArraySplitV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"tensor",type:"tensor"},{start:2,name:"lengths",type:"number[]"},{start:3,name:"flowIn",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype"}]},{tfOpName:"TensorArraySizeV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"},{start:1,name:"flowIn",type:"number"}]},{tfOpName:"TensorArrayCloseV3",category:"control",inputs:[{start:0,name:"tensorArrayId",type:"tensor"}]},{tfOpName:"StatelessIf",category:"control",inputs:[{start:0,name:"cond",type:"tensor"},{start:1,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"then_branch",name:"thenBranch",type:"func"},{tfName:"else_branch",name:"elseBranch",type:"func"}]},{tfOpName:"If",category:"control",inputs:[{start:0,name:"cond",type:"tensor"},{start:1,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"then_branch",name:"thenBranch",type:"func"},{tfName:"else_branch",name:"elseBranch",type:"func"}]},{tfOpName:"StatelessWhile",category:"control",inputs:[{start:0,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"cond",name:"cond",type:"func"},{tfName:"body",name:"body",type:"func"}]},{tfOpName:"While",category:"control",inputs:[{start:0,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"cond",name:"cond",type:"func"},{tfName:"body",name:"body",type:"func"}]},{tfOpName:"TensorListScatter",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"},{start:1,name:"indices",type:"number[]"},{start:2,name:"elementShape",type:"shape"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListScatterV2",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"},{start:1,name:"indices",type:"number[]"},{start:2,name:"elementShape",type:"shape"},{start:3,name:"numElements",type:"number"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListGather",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"indices",type:"number[]"},{start:2,name:"elementShape",type:"shape"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListGetItem",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"index",type:"number"},{start:2,name:"elementShape",type:"shape"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListSetItem",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"index",type:"number"},{start:2,name:"tensor",type:"tensor"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListReserve",category:"control",inputs:[{start:0,name:"elementShape",type:"shape"},{start:1,name:"numElements",type:"number"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListFromTensor",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"},{start:1,name:"elementShape",type:"shape"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListStack",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"elementShape",type:"shape"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"},{tfName:"num_elements",name:"numElements",type:"dtype"}]},{tfOpName:"TensorListSplit",category:"control",inputs:[{start:0,name:"tensor",type:"tensor"},{start:1,name:"elementShape",type:"shape"},{start:2,name:"lengths",type:"number[]"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListConcat",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"}],attrs:[{tfName:"element_shape",name:"elementShape",type:"shape"},{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListConcatV2",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"}],attrs:[{tfName:"element_shape",name:"elementShape",type:"shape"},{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListPopBack",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"elementShape",type:"shape"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListPushBack",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"tensor",type:"tensor"}],attrs:[{tfName:"element_dtype",name:"elementDType",type:"dtype"}]},{tfOpName:"TensorListLength",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"}]},{tfOpName:"TensorListResize",category:"control",inputs:[{start:0,name:"tensorListId",type:"tensor"},{start:1,name:"size",type:"number"}]}];var V=Object.freeze({__proto__:null,json:Sa});const fa=[{tfOpName:"AvgPool",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0},{tfName:"ksize",name:"kernelSize",type:"number[]"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"MaxPool",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0},{tfName:"ksize",name:"kernelSize",type:"number[]"},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[],notSupported:!0},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"MaxPoolWithArgmax",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"ksize",name:"kernelSize",type:"number[]"},{tfName:"include_batch_in_index",name:"includeBatchInIndex",type:"bool"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"AvgPool3D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0},{tfName:"ksize",name:"kernelSize",type:"number[]"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"MaxPool3D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0},{tfName:"ksize",name:"kernelSize",type:"number[]"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Conv1D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"}],attrs:[{tfName:"stride",name:"stride",type:"number"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NWC"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"dilation",name:"dilation",type:"number",defaultValue:1}]},{tfOpName:"Conv2D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"useCudnnOnGpu",name:"useCudnnOnGpu",type:"bool"},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NHWC"},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[]},{tfName:"dilations",name:"dilations",type:"number[]"}]},{tfOpName:"_FusedConv2D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"},{start:2,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"num_args",name:"numArgs",type:"number"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[]},{tfName:"use_cudnn_on_gpu",name:"useCudnnOnGpu",type:"bool",defaultValue:!0},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NHWC"},{tfName:"dilations",name:"dilations",type:"number[]",defaultValue:[1,1,1,1]},{tfName:"fused_ops",name:"fusedOps",type:"string[]",defaultValue:[]},{tfName:"epsilon",name:"epsilon",type:"number",defaultValue:1e-4},{tfName:"leakyrelu_alpha",name:"leakyreluAlpha",type:"number",defaultValue:.2}]},{tfOpName:"Conv2DBackpropInput",category:"convolution",inputs:[{start:2,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"},{start:0,name:"outputShape",type:"number[]"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[]},{tfName:"dilations",name:"dilations",type:"number[]",notSupported:!0}]},{tfOpName:"DepthwiseConv2d",category:"convolution",inputs:[{start:0,name:"input",type:"tensor"},{start:1,name:"filter",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NHWC"},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[]},{tfName:"dilations",name:"dilations",type:"number[]"}]},{tfOpName:"DepthwiseConv2dNative",category:"convolution",inputs:[{start:0,name:"input",type:"tensor"},{start:1,name:"filter",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NHWC"},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[]},{tfName:"dilations",name:"dilations",type:"number[]"}]},{tfOpName:"FusedDepthwiseConv2dNative",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"},{start:2,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"num_args",name:"numArgs",type:"number"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NHWC"},{tfName:"dilations",name:"dilations",type:"number[]",defaultValue:[1,1,1,1]},{tfName:"fused_ops",name:"fusedOps",type:"string[]",defaultValue:[]},{tfName:"explicit_paddings",name:"explicitPaddings",type:"number[]",defaultValue:[]}]},{tfOpName:"Conv3D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"padding",name:"pad",type:"string"},{tfName:"data_format",name:"dataFormat",type:"string",defaultValue:"NHWC"},{tfName:"dilations",name:"dilations",type:"number[]"}]},{tfOpName:"Dilation2D",category:"convolution",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"filter",type:"tensor"}],attrs:[{tfName:"strides",name:"strides",type:"number[]"},{tfName:"rates",name:"dilations",type:"number[]"},{tfName:"padding",name:"pad",type:"string"}]}];var Z=Object.freeze({__proto__:null,json:fa});const qa=[{tfOpName:"Fill",category:"creation",inputs:[{start:0,name:"shape",type:"number[]"},{start:1,name:"value",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype"}]},{tfOpName:"LinSpace",category:"creation",inputs:[{start:0,name:"start",type:"number"},{start:1,name:"stop",type:"number"},{start:2,name:"num",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"OneHot",category:"creation",inputs:[{start:0,name:"indices",type:"tensor"},{start:1,name:"depth",type:"number"},{start:2,name:"onValue",type:"number",defaultValue:1},{start:3,name:"offValue",type:"number",defaultValue:0}],attrs:[{tfName:"axis",name:"axis",type:"number",notSupported:!0},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Ones",category:"creation",inputs:[{start:0,name:"shape",type:"number[]"}],attrs:[{tfName:"T",name:"dtype",type:"dtype"}]},{tfOpName:"OnesLike",category:"creation",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"dtype",name:"dtype",type:"dtype"}]},{tfOpName:"RandomStandardNormal",category:"creation",inputs:[{start:0,name:"shape",type:"number[]"}],attrs:[{tfName:"seed",name:"seed",type:"number",defaultValue:0},{tfName:"seed2",name:"seed2",type:"number",defaultValue:0,notSupported:!0},{tfName:"dtype",name:"dtype",type:"dtype"},{tfName:"T",name:"T",type:"number",notSupported:!0}]},{tfOpName:"RandomUniform",category:"creation",inputs:[{start:0,name:"shape",type:"number[]"}],attrs:[{tfName:"minval",name:"minval",type:"number",defaultValue:0},{tfName:"maxval",name:"maxval",type:"number",defaultValue:1},{tfName:"dtype",name:"dtype",type:"dtype"},{tfName:"seed",name:"seed",type:"number",defaultValue:0},{tfName:"seed2",name:"seed2",type:"number",defaultValue:0,notSupported:!0},{tfName:"T",name:"T",type:"number",notSupported:!0}]},{tfOpName:"Range",category:"creation",inputs:[{start:0,name:"start",type:"number"},{start:1,name:"stop",type:"number"},{start:2,name:"step",type:"number",defaultValue:0}],attrs:[{tfName:"Tidx",name:"dtype",type:"dtype"}]},{tfOpName:"TruncatedNormal",category:"creation",inputs:[{start:0,name:"shape",type:"number[]"}],attrs:[{tfName:"means",name:"mean",type:"number",defaultValue:0},{tfName:"stddev",name:"stdDev",type:"number",defaultValue:1},{tfName:"seed",name:"seed",type:"number"},{tfName:"seed2",name:"seed2",type:"number",defaultValue:0,notSupported:!0},{tfName:"dtype",name:"dtype",type:"dtype"},{tfName:"T",name:"T",type:"number",notSupported:!0}]},{tfOpName:"Zeros",category:"creation",inputs:[{start:0,name:"shape",type:"number[]"}],attrs:[{tfName:"T",name:"dtype",type:"dtype"}]},{tfOpName:"ZerosLike",category:"creation",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype"}]},{tfOpName:"Multinomial",category:"creation",inputs:[{start:0,name:"logits",type:"tensor"},{start:1,name:"numSamples",type:"number"}],attrs:[{tfName:"seed",name:"seed",type:"number"},{tfName:"seed2",name:"seed2",type:"number"},{tfName:"T",name:"dtype",type:"dtype"},{tfName:"output_dtype",name:"output_dtype",type:"dtype"}]}];var X=Object.freeze({__proto__:null,json:qa});const ka=[{tfOpName:"NonMaxSuppressionV2",category:"dynamic",inputs:[{start:0,name:"boxes",type:"tensor"},{start:1,name:"scores",type:"tensor"},{start:2,name:"maxOutputSize",type:"number"},{start:3,name:"iouThreshold",type:"number"}]},{tfOpName:"NonMaxSuppressionV3",category:"dynamic",inputs:[{start:0,name:"boxes",type:"tensor"},{start:1,name:"scores",type:"tensor"},{start:2,name:"maxOutputSize",type:"number"},{start:3,name:"iouThreshold",type:"number"},{start:4,name:"scoreThreshold",type:"number"}]},{tfOpName:"NonMaxSuppressionV4",category:"dynamic",inputs:[{start:0,name:"boxes",type:"tensor"},{start:1,name:"scores",type:"tensor"},{start:2,name:"maxOutputSize",type:"number"},{start:3,name:"iouThreshold",type:"number"},{start:4,name:"scoreThreshold",type:"number"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0},{tfName:"T_threshold",name:"threshold",type:"dtype",notSupported:!0},{tfName:"pad_to_max_output_size",name:"padToMaxOutputSize",type:"bool"}]},{tfOpName:"NonMaxSuppressionV5",category:"dynamic",inputs:[{start:0,name:"boxes",type:"tensor"},{start:1,name:"scores",type:"tensor"},{start:2,name:"maxOutputSize",type:"number"},{start:3,name:"iouThreshold",type:"number"},{start:4,name:"scoreThreshold",type:"number"},{start:5,name:"softNmsSigma",type:"number"}]},{tfOpName:"Where",category:"dynamic",inputs:[{start:0,name:"condition",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"ListDiff",category:"dynamic",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"y",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]}];var _=Object.freeze({__proto__:null,json:ka});const Ga=[{tfOpName:"LowerBound",category:"evaluation",inputs:[{start:0,name:"sortedSequence",type:"tensor"},{start:1,name:"values",type:"tensor"}]},{tfOpName:"TopKV2",category:"evaluation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"k",type:"number"}],attrs:[{tfName:"sorted",name:"sorted",type:"bool"}]},{tfOpName:"UpperBound",category:"evaluation",inputs:[{start:0,name:"sortedSequence",type:"tensor"},{start:1,name:"values",type:"tensor"}]},{tfOpName:"Unique",category:"evaluation",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"UniqueV2",category:"evaluation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number"}]}];var $=Object.freeze({__proto__:null,json:Ga});const Na=[{tfOpName:"PlaceholderWithDefault",category:"graph",inputs:[{start:0,name:"default",type:"tensor"}],attrs:[{tfName:"shape",name:"shape",type:"shape"},{tfName:"dtype",name:"dtype",type:"dtype"}]},{tfOpName:"Placeholder",category:"graph",attrs:[{tfName:"shape",name:"shape",type:"shape"},{tfName:"dtype",name:"dtype",type:"dtype"}]},{tfOpName:"Const",category:"graph"},{tfOpName:"Identity",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"IdentityN",category:"graph",inputs:[{start:0,end:0,name:"x",type:"tensors"}]},{tfOpName:"Snapshot",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"Rank",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"Size",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"Shape",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"ShapeN",category:"graph",inputs:[{start:0,end:0,name:"x",type:"tensors"}]},{tfOpName:"Print",category:"graph",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"data",type:"tensors"}],attrs:[{tfName:"message",name:"message",type:"string"},{tfName:"first_n",name:"firstN",type:"number",notSupported:!0},{tfName:"summarize",name:"summarize",type:"number",defaultValue:3}]},{tfOpName:"NoOp",category:"graph",inputs:[]},{tfOpName:"StopGradient",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"FakeQuantWithMinMaxVars",category:"graph",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"min",name:"min",type:"number"},{tfName:"max",name:"max",type:"number"}]}];var tt=Object.freeze({__proto__:null,json:Na});const Ba=[{tfOpName:"HashTable",category:"hash_table",inputs:[],attrs:[{tfName:"shared_name",name:"sharedName",type:"string"},{tfName:"use_node_name_sharing",name:"useNodeNameSharing",type:"bool"},{tfName:"key_dtype",name:"keyDType",type:"dtype"},{tfName:"value_dtype",name:"valueDType",type:"dtype"}]},{tfOpName:"HashTableV2",category:"hash_table",inputs:[],attrs:[{tfName:"shared_name",name:"sharedName",type:"string"},{tfName:"use_node_name_sharing",name:"useNodeNameSharing",type:"bool"},{tfName:"key_dtype",name:"keyDType",type:"dtype"},{tfName:"value_dtype",name:"valueDType",type:"dtype"}]},{tfOpName:"LookupTableImport",category:"hash_table",inputs:[{start:0,name:"tableHandle",type:"tensor"},{start:1,name:"keys",type:"tensor"},{start:2,name:"values",type:"tensor"}],attrs:[{tfName:"Tin",name:"tIn",type:"dtype",notSupported:!0},{tfName:"Tout",name:"tOut",type:"dtype",notSupported:!0}]},{tfOpName:"LookupTableImportV2",category:"hash_table",inputs:[{start:0,name:"tableHandle",type:"tensor"},{start:1,name:"keys",type:"tensor"},{start:2,name:"values",type:"tensor"}],attrs:[{tfName:"Tin",name:"tIn",type:"dtype",notSupported:!0},{tfName:"Tout",name:"tOut",type:"dtype",notSupported:!0}]},{tfOpName:"LookupTableFind",category:"hash_table",inputs:[{start:0,name:"tableHandle",type:"tensor"},{start:1,name:"keys",type:"tensor"},{start:2,name:"defaultValue",type:"tensor"}],attrs:[{tfName:"Tin",name:"tIn",type:"dtype",notSupported:!0},{tfName:"Tout",name:"tOut",type:"dtype",notSupported:!0}]},{tfOpName:"LookupTableFindV2",category:"hash_table",inputs:[{start:0,name:"tableHandle",type:"tensor"},{start:1,name:"keys",type:"tensor"},{start:2,name:"defaultValue",type:"tensor"}],attrs:[{tfName:"Tin",name:"tIn",type:"dtype",notSupported:!0},{tfName:"Tout",name:"tOut",type:"dtype",notSupported:!0}]},{tfOpName:"LookupTableSize",category:"hash_table",inputs:[{start:0,name:"tableHandle",type:"tensor"}]},{tfOpName:"LookupTableSizeV2",category:"hash_table",inputs:[{start:0,name:"tableHandle",type:"tensor"}]}];var et=Object.freeze({__proto__:null,json:Ba});const Ua=[{tfOpName:"ResizeBilinear",category:"image",inputs:[{start:0,name:"images",type:"tensor"},{start:1,name:"size",type:"number[]"}],attrs:[{tfName:"align_corners",name:"alignCorners",type:"bool"},{tfName:"half_pixel_centers",name:"halfPixelCenters",type:"bool"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"ResizeNearestNeighbor",category:"image",inputs:[{start:0,name:"images",type:"tensor"},{start:1,name:"size",type:"number[]"}],attrs:[{tfName:"align_corners",name:"alignCorners",type:"bool"},{tfName:"half_pixel_centers",name:"halfPixelCenters",type:"bool"},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"CropAndResize",category:"image",inputs:[{start:0,name:"image",type:"tensor"},{start:1,name:"boxes",type:"tensor"},{start:2,name:"boxInd",type:"tensor"},{start:3,name:"cropSize",type:"number[]"}],attrs:[{tfName:"method",name:"method",type:"string"},{tfName:"extrapolation_value",name:"extrapolationValue",type:"number"}]},{tfOpName:"ImageProjectiveTransformV3",category:"image",inputs:[{start:0,name:"images",type:"tensor"},{start:1,name:"transforms",type:"tensor"},{start:2,name:"outputShape",type:"number[]"},{start:3,name:"fillValue",type:"number"}],attrs:[{tfName:"interpolation",name:"interpolation",type:"string"},{tfName:"fill_mode",name:"fillMode",type:"string"}]}];var it=Object.freeze({__proto__:null,json:Ua});const Ja=[{tfOpName:"Equal",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"NotEqual",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Greater",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"GreaterEqual",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Less",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"LessEqual",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"LogicalAnd",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"LogicalNot",category:"logical",inputs:[{start:0,name:"a",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"LogicalOr",category:"logical",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Select",category:"logical",inputs:[{start:0,name:"condition",type:"tensor"},{start:1,name:"a",type:"tensor"},{start:2,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"SelectV2",category:"logical",inputs:[{start:0,name:"condition",type:"tensor"},{start:1,name:"a",type:"tensor"},{start:2,name:"b",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]}];var st=Object.freeze({__proto__:null,json:Ja});const Wa=[{tfOpName:"_FusedMatMul",category:"matrices",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"},{start:2,end:0,name:"args",type:"tensors"}],attrs:[{tfName:"num_args",name:"numArgs",type:"number"},{tfName:"fused_ops",name:"fusedOps",type:"string[]",defaultValue:[]},{tfName:"epsilon",name:"epsilon",type:"number",defaultValue:1e-4},{tfName:"transpose_a",name:"transposeA",type:"bool",defaultValue:!1},{tfName:"transpose_b",name:"transposeB",type:"bool",defaultValue:!1},{tfName:"leakyrelu_alpha",name:"leakyreluAlpha",type:"number",defaultValue:.2},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"MatMul",category:"matrices",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"transpose_a",name:"transposeA",type:"bool",defaultValue:!1},{tfName:"transpose_b",name:"transposeB",type:"bool",defaultValue:!1},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"BatchMatMul",category:"matrices",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"adj_x",name:"transposeA",type:"bool",defaultValue:!1},{tfName:"adj_y",name:"transposeB",type:"bool",defaultValue:!1},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"BatchMatMulV2",category:"matrices",inputs:[{start:0,name:"a",type:"tensor"},{start:1,name:"b",type:"tensor"}],attrs:[{tfName:"adj_x",name:"transposeA",type:"bool",defaultValue:!1},{tfName:"adj_y",name:"transposeB",type:"bool",defaultValue:!1},{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Transpose",category:"matrices",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"perm",type:"number[]"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"Einsum",category:"matrices",inputs:[{start:0,end:0,name:"tensors",type:"tensors"}],attrs:[{tfName:"equation",name:"equation",type:"string"},{tfName:"N",name:"n",type:"number",defaultValue:2},{tfName:"T",name:"dtype",type:"dtype"}]}];var ot=Object.freeze({__proto__:null,json:Wa});const Fa=[{tfOpName:"EuclideanNorm",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool",defaultValue:!1}]},{tfOpName:"FusedBatchNorm",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"scale",type:"tensor"},{start:2,name:"offset",type:"tensor"},{start:3,name:"mean",type:"tensor"},{start:4,name:"variance",type:"tensor"}],attrs:[{tfName:"epsilon",name:"epsilon",type:"number",defaultValue:.001},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0}]},{tfOpName:"FusedBatchNormV2",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"scale",type:"tensor"},{start:2,name:"offset",type:"tensor"},{start:3,name:"mean",type:"tensor"},{start:4,name:"variance",type:"tensor"}],attrs:[{tfName:"epsilon",name:"epsilon",type:"number",defaultValue:.001},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0}]},{tfOpName:"FusedBatchNormV3",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"scale",type:"tensor"},{start:2,name:"offset",type:"tensor"},{start:3,name:"mean",type:"tensor"},{start:4,name:"variance",type:"tensor"}],attrs:[{tfName:"epsilon",name:"epsilon",type:"number",defaultValue:.001},{tfName:"data_format",name:"dataFormat",type:"string",notSupported:!0}]},{tfOpName:"LRN",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"depth_radius",name:"radius",type:"number",defaultValue:5},{tfName:"bias",name:"bias",type:"number",defaultValue:1},{tfName:"alpha",name:"alpha",type:"number",defaultValue:1},{tfName:"beta",name:"beta",type:"number",defaultValue:.5}]},{tfOpName:"Softmax",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"LogSoftmax",category:"normalization",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"SparseToDense",category:"normalization",inputs:[{start:0,name:"sparseIndices",type:"tensor"},{start:1,name:"outputShape",type:"number[]"},{start:2,name:"sparseValues",type:"tensor"},{start:3,name:"defaultValue",type:"tensor"}],attrs:[{tfName:"validate_indices",name:"validateIndices",type:"bool",defaultValue:!0,notSupported:!0}]}];var rt=Object.freeze({__proto__:null,json:Fa});const Ra=[{tfOpName:"Bincount",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"size",type:"number"},{start:2,name:"weights",type:"tensor"}]},{tfOpName:"DenseBincount",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"size",type:"number"},{start:2,name:"weights",type:"tensor"}],attrs:[{tfName:"binary_output",name:"binaryOutput",type:"bool"}]},{tfOpName:"Max",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"Mean",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"Min",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"Sum",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"All",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"Any",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"ArgMax",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number"}]},{tfOpName:"ArgMin",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number"}]},{tfOpName:"Prod",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}],attrs:[{tfName:"keep_dims",name:"keepDims",type:"bool"}]},{tfOpName:"Cumprod",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number"}],attrs:[{tfName:"exclusive",name:"exclusive",type:"bool"},{tfName:"reverse",name:"reverse",type:"bool"}]},{tfOpName:"Cumsum",category:"reduction",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number"}],attrs:[{tfName:"exclusive",name:"exclusive",type:"bool"},{tfName:"reverse",name:"reverse",type:"bool"}]}];var ut=Object.freeze({__proto__:null,json:Ra});const Ha=[{tfOpName:"ConcatV2",category:"slice_join",inputs:[{start:0,end:-1,name:"tensors",type:"tensors"},{start:-1,name:"axis",type:"number"}],attrs:[{tfName:"N",name:"n",type:"number",defaultValue:2}]},{tfOpName:"Concat",category:"slice_join",inputs:[{start:1,end:0,name:"tensors",type:"tensors"},{start:0,name:"axis",type:"number"}],attrs:[{tfName:"N",name:"n",type:"number",defaultValue:2}]},{tfOpName:"GatherV2",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"indices",type:"tensor"},{start:2,name:"axis",type:"number",defaultValue:0}],attrs:[{tfName:"batch_dims",name:"batchDims",type:"number",defaultValue:0}]},{tfOpName:"Gather",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"indices",type:"tensor"}],attrs:[{tfName:"validate_indices",name:"validateIndices",type:"bool",notSupported:!0}]},{tfOpName:"Reverse",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"dims",type:"bool[]"}]},{tfOpName:"ReverseV2",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number[]"}]},{tfOpName:"Slice",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"begin",type:"number[]"},{start:2,name:"size",type:"number[]"}]},{tfOpName:"StridedSlice",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"begin",type:"number[]"},{start:2,name:"end",type:"number[]"},{start:3,name:"strides",type:"number[]"}],attrs:[{tfName:"begin_mask",name:"beginMask",type:"number",defaultValue:0},{tfName:"end_mask",name:"endMask",type:"number",defaultValue:0},{tfName:"new_axis_mask",name:"newAxisMask",type:"number",defaultValue:0},{tfName:"ellipsis_mask",name:"ellipsisMask",type:"number",defaultValue:0},{tfName:"shrink_axis_mask",name:"shrinkAxisMask",type:"number",defaultValue:0}]},{tfOpName:"Pack",category:"slice_join",inputs:[{start:0,end:0,name:"tensors",type:"tensors"}],attrs:[{tfName:"axis",name:"axis",type:"number",defaultValue:0}]},{tfOpName:"Unpack",category:"slice_join",inputs:[{start:0,name:"tensor",type:"tensor"}],attrs:[{tfName:"axis",name:"axis",type:"number",defaultValue:0},{tfName:"num",name:"num",type:"number",defaultValue:0,notSupported:!0}]},{tfOpName:"Tile",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"reps",type:"number[]"}]},{tfOpName:"Split",category:"slice_join",inputs:[{start:0,name:"axis",type:"number",defaultValue:0},{start:1,name:"x",type:"tensor"}],attrs:[{tfName:"num_split",name:"numOrSizeSplits",type:"number",defaultValue:1}]},{tfOpName:"SplitV",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"numOrSizeSplits",type:"number[]"},{start:2,name:"axis",type:"number",defaultValue:0}]},{tfOpName:"ScatterNd",category:"slice_join",inputs:[{start:0,name:"indices",type:"tensor"},{start:1,name:"values",type:"tensor"},{start:2,name:"shape",type:"number[]"}]},{tfOpName:"GatherNd",category:"slice_join",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"indices",type:"tensor"}]},{tfOpName:"SparseToDense",category:"slice_join",inputs:[{start:0,name:"sparseIndices",type:"tensor"},{start:1,name:"outputShape",type:"number[]"},{start:2,name:"sparseValues",type:"tensor"},{start:3,name:"defaultValue",type:"tensor"}],attrs:[{tfName:"validate_indices",name:"validateIndices",type:"bool",defaultValue:!1,notSupported:!0}]}];var at=Object.freeze({__proto__:null,json:Ha});const Va=[{tfOpName:"SparseFillEmptyRows",category:"sparse",inputs:[{start:0,name:"indices",type:"tensor"},{start:1,name:"values",type:"tensor"},{start:2,name:"denseShape",type:"tensor"},{start:3,name:"defaultValue",type:"tensor"}]},{tfOpName:"SparseReshape",category:"sparse",inputs:[{start:0,name:"inputIndices",type:"tensor"},{start:1,name:"inputShape",type:"tensor"},{start:2,name:"newShape",type:"tensor"}],attrs:[{tfName:"T",name:"dtype",type:"dtype",notSupported:!0}]},{tfOpName:"SparseSegmentMean",category:"sparse",inputs:[{start:0,name:"data",type:"tensor"},{start:1,name:"indices",type:"tensor"},{start:2,name:"segmentIds",type:"tensor"}]},{tfOpName:"SparseSegmentSum",category:"sparse",inputs:[{start:0,name:"data",type:"tensor"},{start:1,name:"indices",type:"tensor"},{start:2,name:"segmentIds",type:"tensor"}]}];var nt=Object.freeze({__proto__:null,json:Va});const Za=[{tfOpName:"FFT",category:"spectral",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"IFFT",category:"spectral",inputs:[{start:0,name:"x",type:"tensor"}]},{tfOpName:"RFFT",category:"spectral",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"fft_length",type:"number",notSupported:!0}]},{tfOpName:"IRFFT",category:"spectral",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"fft_length",type:"number",notSupported:!0}]}];var Lt=Object.freeze({__proto__:null,json:Za});const Xa=[{tfOpName:"StringNGrams",category:"string",inputs:[{start:0,name:"data",type:"tensor"},{start:1,name:"dataSplits",type:"tensor"}],attrs:[{tfName:"separator",name:"separator",type:"string"},{tfName:"ngram_widths",name:"nGramWidths",type:"number[]"},{tfName:"left_pad",name:"leftPad",type:"string"},{tfName:"right_pad",name:"rightPad",type:"string"},{tfName:"pad_width",name:"padWidth",type:"number"},{tfName:"preserve_short_sequences",name:"preserveShortSequences",type:"bool"}],outputs:["ngrams","ngrams_splits"]},{tfOpName:"StringSplit",category:"string",inputs:[{start:0,name:"input",type:"tensor"},{start:1,name:"delimiter",type:"tensor"}],attrs:[{tfName:"skip_empty",name:"skipEmpty",type:"bool"}],outputs:["indices","values","shape"]},{tfOpName:"StringToHashBucketFast",category:"string",inputs:[{start:0,name:"input",type:"tensor"}],attrs:[{tfName:"num_buckets",name:"numBuckets",type:"number"}]}];var Mt=Object.freeze({__proto__:null,json:Xa});const _a=[{tfOpName:"Cast",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"SrcT",name:"sdtype",type:"dtype",notSupported:!0},{tfName:"DstT",name:"dtype",type:"dtype"}]},{tfOpName:"ExpandDims",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"axis",type:"number"}]},{tfOpName:"MirrorPad",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"padding",type:"number[]"}],attrs:[{tfName:"mode",name:"mode",type:"string"}]},{tfOpName:"Pad",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"padding",type:"number[]"}],attrs:[{tfName:"constant_value",name:"constantValue",type:"number",defaultValue:0}]},{tfOpName:"PadV2",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"padding",type:"number[]"},{start:2,name:"constantValue",type:"number",defaultValue:0}]},{tfOpName:"Reshape",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"shape",type:"number[]"}]},{tfOpName:"Squeeze",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"axis",tfDeprecatedName:"squeeze_dims",name:"axis",type:"number[]"}]},{tfOpName:"SpaceToBatchND",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"blockShape",type:"number[]"},{start:2,name:"paddings",type:"number[]"}]},{tfOpName:"BatchToSpaceND",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"blockShape",type:"number[]"},{start:2,name:"crops",type:"number[]"}]},{tfOpName:"DepthToSpace",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"}],attrs:[{tfName:"block_size",name:"blockSize",type:"number"},{tfName:"data_format",name:"dataFormat",type:"string"}]},{tfOpName:"BroadcastTo",category:"transformation",inputs:[{start:0,name:"x",type:"tensor"},{start:1,name:"shape",type:"number[]"}],attrs:[]},{tfOpName:"BroadcastArgs",category:"transformation",inputs:[{start:0,name:"s0",type:"tensor"},{start:1,name:"s1",type:"tensor"}],attrs:[]}];var Ct=Object.freeze({__proto__:null,json:_a});class $a{static get Instance(){return this._instance||(this._instance=new this)}constructor(){const t=[].concat(...[R,H,V,Z,X,_,$,tt,et,it,st,ot,rt,ut,at,nt,Lt,Mt,Ct].map((t=>t.json)));this.opMappers=t.reduce(((t,e)=>(t[e.tfOpName]=e,t)),{})}transformGraph(t,e={}){const i=t.node,s=[],o=[],r=[],u=i.reduce(((t,e)=>(t[e.name]=this.mapNode(e),e.op.startsWith("Placeholder")?s.push(t[e.name]):"Const"===e.op?o.push(t[e.name]):null!=e.input&&0!==e.input.length||r.push(t[e.name]),t)),{});let a=[];const n=[];let L={},M={};null!=e&&(L=this.mapSignatureEntries(e.inputs),M=this.mapSignatureEntries(e.outputs));const C=Object.keys(u);C.forEach((t=>{const e=u[t];e.inputNames.forEach(((t,i)=>{const[s,,o]=Ka(t),r=u[s];if(null!=r.outputs){const t=r.outputs.indexOf(o);if(-1!==t){const o=`${s}:${t}`;e.inputNames[i]=o}}e.inputs.push(r),r.children.push(e)}))})),0===Object.keys(M).length?C.forEach((t=>{const e=u[t];0===e.children.length&&n.push(e)})):Object.keys(M).forEach((t=>{const[e]=Ka(t),i=u[e];null!=i&&(i.signatureKey=M[t],n.push(i))})),Object.keys(L).length>0?Object.keys(L).forEach((t=>{const[e]=Ka(t),i=u[e];i&&(i.signatureKey=L[t],a.push(i))})):a=s;let w={};null!=t.library&&null!=t.library.function&&(w=t.library.function.reduce(((t,e)=>(t[e.signature.name]=this.mapFunction(e),t)),{}));const y={nodes:u,inputs:a,outputs:n,weights:o,placeholders:s,signature:e,functions:w};return r.length>0&&(y.initNodes=r),y}mapSignatureEntries(t){return Object.keys(t||{}).reduce(((e,i)=>(e[t[i].name]=i,e)),{})}mapNode(t){const e=Oa(t.op)||this.opMappers[t.op]||{};null==t.attr&&(t.attr={});const i={name:t.name,op:t.op,category:e.category,inputNames:(t.input||[]).map((t=>t.startsWith("^")?t.slice(1):t)),inputs:[],children:[],inputParams:{},attrParams:{},rawAttrs:t.attr,outputs:e.outputs};return null!=e.inputs&&(i.inputParams=e.inputs.reduce(((t,e)=>(t[e.name]={type:e.type,inputIndexStart:e.start,inputIndexEnd:e.end},t)),{})),null!=e.attrs&&(i.attrParams=e.attrs.reduce(((e,i)=>{const s=i.type;let o;switch(i.type){case"string":o=sn(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=sn(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"string[]":o=Mn(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=Mn(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"number":o=rn(t.attr,i.tfName,i.defaultValue||0),void 0===o&&i.tfDeprecatedName&&(o=rn(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"number[]":o=getNumericArrayParam(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=getNumericArrayParam(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"bool":o=on(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=on(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"bool[]":o=getBoolArrayParam(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=getBoolArrayParam(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"shape":o=Ln(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=Ln(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"shape[]":o=getTensorShapeArrayParam(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=getTensorShapeArrayParam(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"dtype":o=an(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=an(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"dtype[]":o=getDtypeArrayParam(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=getDtypeArrayParam(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"func":o=getFuncParam(t.attr,i.tfName,i.defaultValue),void 0===o&&i.tfDeprecatedName&&(o=getFuncParam(t.attr,i.tfDeprecatedName,i.defaultValue));break;case"tensor":case"tensors":break;default:throw new Error(`Unsupported param type: ${i.type} for op: ${t.op}`)}return e[i.name]={value:o,type:s},e}),{})),i}mapFunction(t){const e=t.nodeDef,i=[];let s={};null!=e&&(s=e.reduce(((t,e)=>(t[e.name]=this.mapNode(e),"Const"===e.op&&i.push(t[e.name]),t)),{}));const o=[],r=[];t.signature.inputArg.forEach((t=>{const[e]=Ka(t.name),i={name:e,op:"Placeholder",inputs:[],inputNames:[],category:"graph",inputParams:{},attrParams:{dtype:{value:un(t.type),type:"dtype"}},children:[]};i.signatureKey=t.name,o.push(i),s[e]=i}));Object.keys(s).forEach((t=>{const e=s[t];e.inputNames.forEach(((t,i)=>{const[o,,r]=Ka(t),u=s[o];if(null!=u.outputs){const t=u.outputs.indexOf(r);if(-1!==t){const s=`${o}:${t}`;e.inputNames[i]=s}}e.inputs.push(u),u.children.push(e)}))}));const u=t.ret;t.signature.outputArg.forEach((t=>{const[e,i]=Ka(u[t.name]),o=s[e];null!=o&&(o.defaultOutput=i,r.push(o))}));const a=this.mapArgsToSignature(t);return{nodes:s,inputs:o,outputs:r,weights:i,placeholders:[],signature:a}}mapArgsToSignature(t){return{methodName:t.signature.name,inputs:t.signature.inputArg.reduce(((t,e)=>(t[e.name]=this.mapArgToTensorInfo(e),t)),{}),outputs:t.signature.outputArg.reduce(((e,i)=>(e[i.name]=this.mapArgToTensorInfo(i,t.ret),e)),{})}}mapArgToTensorInfo(t,e){let i=t.name;return null!=e&&(i=e[i]),{name:i,dtype:t.type}}}function tn(t){const e=we().global;if(void 0!==e.atob)return e.atob(t);if("undefined"!=typeof Buffer)return new Buffer(t,"base64").toString();throw new Error("Unable to decode base64 in this environment. Missing built-in atob() or Buffer()")}function en(t,e){const i=Array.isArray(t)?String.fromCharCode.apply(null,t):tn(t);return e?i:i.toLowerCase()}function sn(t,e,i,s=!1){const o=t[e];return null!=o?en(o.s,s):i}function on(t,e,i){const s=t[e];return s?s.b:i}function rn(t,e,i){const s=t[e]||{},o=null!=s.i?s.i:null!=s.f?s.f:i;return"number"==typeof o?o:parseInt(o,10)}function un(t){switch("string"==typeof t&&(t=W[t]),t){case W.DT_FLOAT:case W.DT_HALF:return"float32";case W.DT_INT32:case W.DT_INT64:case W.DT_INT8:case W.DT_UINT8:return"int32";case W.DT_BOOL:return"bool";case W.DT_DOUBLE:return"float32";case W.DT_STRING:return"string";default:return null}}function an(t,e,i){const s=t[e];return s&&s.type?un(s.type):i}function nn(t){if(!t.unknownRank)return null!=t.dim?t.dim.map((t=>"number"==typeof t.size?t.size:parseInt(t.size,10))):[]}function Ln(t,e,i){const s=t[e];return s&&s.shape?nn(s.shape):i}function Mn(t,e,i,s=!1){const o=t[e];return o&&o.list&&o.list.s?o.list.s.map((t=>en(t,s))):i}class Cn{constructor(t,e,i){this.node=t,this.tensorMap=e,this.context=i,this.inputs=[],this.attrs={},this.inputs=t.inputNames.map((t=>this.getInput(t))),null!=t.rawAttrs&&(this.attrs=Object.keys(t.rawAttrs).reduce(((t,e)=>(t[e]=this.getAttr(e),t)),{}))}getInput(t){return xa(t,this.tensorMap,this.context)}getAttr(t,e){const i=this.node.rawAttrs[t];if(null!=i.tensor)return xa(t,this.tensorMap,this.context);if(null!=i.i||null!=i.f)return rn(this.node.rawAttrs,t,e);if(null!=i.s)return sn(this.node.rawAttrs,t,e);if(null!=i.b)return on(this.node.rawAttrs,t,e);if(null!=i.shape)return Ln(this.node.rawAttrs,t,e);if(null!=i.type)return an(this.node.rawAttrs,t,e);if(null!=i.list){if(null!=i.list.i||null!=i.list.f)return getNumericArrayParam(this.node.rawAttrs,t,e);if(null!=i.list.s)return Mn(this.node.rawAttrs,t,e);if(null!=i.list.shape)return getTensorShapeArrayParam(this.node.rawAttrs,t,e);if(null!=i.list.b)return getBoolArrayParam(this.node.rawAttrs,t,e);if(null!=i.list.type)return getDtypeArrayParam(this.node.rawAttrs,t,e)}return e}}var wt=Object.freeze({__proto__:null,abs:ir,acos_:()=>{},acosh_:()=>{},add:Zo,addN_:()=>{},all_:()=>{},any_:()=>{},argMax_:()=>{},argMin_:()=>{},asin_:()=>{},asinh_:()=>{},atan_:()=>{},atan_:()=>{},atanh_:()=>{},avgPool_:()=>{},avgPool3d_:()=>{},basicLSTMCell_:()=>{},batchToSpaceND_:()=>{},batchNorm_:()=>{},batchNorm2d_:()=>{},batchNorm3d_:()=>{},batchNorm4d_:()=>{},bincount:lr,broadcastArgs_:()=>{},broadcastTo:pr,buffer:io,cast:oo,ceil_:()=>{},clipByValue_:()=>{},clone:uo,complex:ps,concat:Mr,concat1d_:()=>{},concat2d_:()=>{},concat3d_:()=>{},concat4d_:()=>{},conv1d_:()=>{},conv2d_:()=>{},conv2dTranspose_:()=>{},conv3d_:()=>{},conv3dTranspose_:()=>{},cos_:()=>{},cosh_:()=>{},cumprod_:()=>{},cumsum_:()=>{},denseBincount_:()=>{},depthToSpace_:()=>{},depthwiseConv2d_:()=>{},diag_:()=>{},dilation2d_:()=>{},div:_o,divNoNan_:()=>{},dot:xr,einsum_:()=>{},elu_:()=>{},equal:cr,erf_:()=>{},euclideanNorm_:()=>{},exp:Wr,expandDims:Rr,expm1_:()=>{},eye_:()=>{},fill$1:()=>{},floor_:()=>{},floorDiv_:()=>{},gather:Vr,greater:Xr,greaterEqual_:()=>{},imag_:()=>{},isFinite_:()=>{},isInf_:()=>{},isNaN_:()=>{},leakyRelu_:()=>{},less_:()=>{},lessEqual_:()=>{},linspace:()=>{},localResponseNormalization_:()=>{},log:$r,log1p:eu,logSigmoid_:()=>{},logSoftmax_:()=>{},logSumExp:uu,logicalAnd:nu,logicalNot_:()=>{},logicalOr_:()=>{},logicalXor_:()=>{},lowerBound:()=>{},matMul:ho,max:Tr,maxPool_:()=>{},maxPool3d_:()=>{},maxPoolWithArgmax_:()=>{},maximum:Mu,mean:wu,meshgrid:()=>{},min_:()=>{},minimum:lu,mirrorPad_:()=>{},mod_:()=>{},moments_:()=>{},mul:tr,multiRNNCell_:()=>{},multinomial_:()=>{},neg:To,notEqual:pu,oneHot:zo,ones:vu,onesLike_:()=>{},outerProduct_:()=>{},pad:Au,pad1d_:()=>{},pad2d_:()=>{},pad3d_:()=>{},pad4d_:()=>{},pool_:()=>{},pow_:()=>{},prelu_:()=>{},print:ao,prod:Iu,rand_:()=>{},randomGamma_:()=>{},randomNormal_:()=>{},randomStandardNormal_:()=>{},randomUniform_:()=>{},range:mu,real:fo,reciprocal_:()=>{},relu:Ou,relu6_:()=>{},reshape:nr,reverse:xu,reverse1d_:()=>{},reverse2d_:()=>{},reverse3d_:()=>{},reverse4d_:()=>{},round$1:()=>{},rsqrt_:()=>{},scalar:Sr,selu_:()=>{},separableConv2d_:()=>{},setdiff1dAsync_:()=>{},sigmoid:wr,sign_:()=>{},sin_:()=>{},sinh_:()=>{},slice:vr,slice1d_:()=>{},slice2d_:()=>{},slice3d_:()=>{},slice4d_:()=>{},softmax_:()=>{},softplus_:()=>{},spaceToBatchND_:()=>{},fft:Ku,ifft_:()=>{},irfft_:()=>{},rfft_:()=>{},split_:()=>{},sqrt_:()=>{},square:qr,squaredDifference:Yu,squeeze:bu,stack:Tu,step_:()=>{},stridedSlice_:()=>{},sub:ou,sum:Gr,tan_:()=>{},tanh_:()=>{},tensor:As,tensor1d:Su,tensor2d:fu,tensor3d:()=>{},tensor4d:()=>{},tensor5d:()=>{},tensor6d:()=>{},tile_:()=>{},topk_:()=>{},truncatedNormal_:()=>{},unique_:()=>{},unsortedSegmentSum_:()=>{},unstack:ku,upperBound:()=>{},variable:()=>{},where:mr,whereAsync_:()=>{},zeros:yu,zerosLike:Or,op:ls,OP_SCOPE_SUFFIX:Ds,booleanMaskAsync_:()=>{},transpose_:()=>{},norm:Ur,movingAverage_:()=>{},scatterND_:()=>{},searchSorted_:()=>{},sparseToDense_:()=>{},gatherND_:()=>{},dropout_:()=>{},enclosingPowerOfTwo:()=>{},cosineWindow:()=>{},inTopKAsync_:()=>{},image:_u,linalg:$u,losses:ta,spectral:Zu,fused:N,signal:Xu,sparse:ea,string:ia});const wn=(t,e,i,s=wt)=>{switch(t.op){case"BiasAdd":case"AddV2":case"Add":return[s.add(za("a",t,e,i),za("b",t,e,i))];case"AddN":return[s.addN(za("tensors",t,e,i))];case"FloorMod":case"Mod":return[s.mod(za("a",t,e,i),za("b",t,e,i))];case"Mul":return[s.mul(za("a",t,e,i),za("b",t,e,i))];case"RealDiv":case"Div":return[s.div(za("a",t,e,i),za("b",t,e,i))];case"DivNoNan":return[s.divNoNan(za("a",t,e,i),za("b",t,e,i))];case"FloorDiv":return[s.floorDiv(za("a",t,e,i),za("b",t,e,i))];case"Sub":return[s.sub(za("a",t,e,i),za("b",t,e,i))];case"Minimum":return[s.minimum(za("a",t,e,i),za("b",t,e,i))];case"Maximum":return[s.maximum(za("a",t,e,i),za("b",t,e,i))];case"Pow":return[s.pow(za("a",t,e,i),za("b",t,e,i))];case"SquaredDifference":return[s.squaredDifference(za("a",t,e,i),za("b",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},yn=(t,e,i,s=wt)=>{switch(t.op){case"Abs":case"ComplexAbs":return[s.abs(za("x",t,e,i))];case"Acos":return[s.acos(za("x",t,e,i))];case"Acosh":return[s.acosh(za("x",t,e,i))];case"Asin":return[s.asin(za("x",t,e,i))];case"Asinh":return[s.asinh(za("x",t,e,i))];case"Atan":return[s.atan(za("x",t,e,i))];case"Atan2":return[s.atan2(za("x",t,e,i),za("y",t,e,i))];case"Atanh":return[s.atanh(za("x",t,e,i))];case"Ceil":return[s.ceil(za("x",t,e,i))];case"Complex":return[s.complex(za("real",t,e,i),za("imag",t,e,i))];case"Cos":return[s.cos(za("x",t,e,i))];case"Cosh":return[s.cosh(za("x",t,e,i))];case"Elu":return[s.elu(za("x",t,e,i))];case"Erf":return[s.erf(za("x",t,e,i))];case"Exp":return[s.exp(za("x",t,e,i))];case"Expm1":return[s.expm1(za("x",t,e,i))];case"Floor":return[s.floor(za("x",t,e,i))];case"Log":return[s.log(za("x",t,e,i))];case"Log1p":return[s.log1p(za("x",t,e,i))];case"Imag":return[s.imag(za("x",t,e,i))];case"Neg":return[s.neg(za("x",t,e,i))];case"Reciprocal":return[s.reciprocal(za("x",t,e,i))];case"Real":return[s.real(za("x",t,e,i))];case"Relu":return[s.relu(za("x",t,e,i))];case"Round":return[s.round(za("x",t,e,i))];case"Selu":return[s.selu(za("x",t,e,i))];case"Sigmoid":return[s.sigmoid(za("x",t,e,i))];case"Sin":return[s.sin(za("x",t,e,i))];case"Sign":return[s.sign(za("x",t,e,i))];case"Sinh":return[s.sinh(za("x",t,e,i))];case"Softplus":return[s.softplus(za("x",t,e,i))];case"Sqrt":return[s.sqrt(za("x",t,e,i))];case"Square":return[s.square(za("x",t,e,i))];case"Tanh":return[s.tanh(za("x",t,e,i))];case"Tan":return[s.tan(za("x",t,e,i))];case"ClipByValue":return[s.clipByValue(za("x",t,e,i),za("clipValueMin",t,e,i),za("clipValueMax",t,e,i))];case"Relu6":return[s.relu6(za("x",t,e,i))];case"Rsqrt":return[s.rsqrt(xa(t.inputNames[0],e,i))];case"Prod":return[s.prod(za("x",t,e,i),za("axes",t,e,i))];case"LeakyRelu":return[s.leakyRelu(za("x",t,e,i),za("alpha",t,e,i))];case"Prelu":return[s.prelu(za("x",t,e,i),za("alpha",t,e,i))];case"IsNan":return[s.isNaN(xa(t.inputNames[0],e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}};function vn(t,e,i){let s=Dn(t,i);const o=!fullDefinedShape(s);if(o&&0===e.length)throw new Error(`Tried to calculate elements of an empty list with non-fully-defined elementShape: ${s}`);if(o&&e.forEach((t=>{s=Dn(t.shape,s)})),!fullDefinedShape(s))throw new Error(`Non-fully-defined elementShape: ${s}`);return s}function Dn(t,e){if("number"==typeof t)return e;if("number"==typeof e)return t;if(t.length!==e.length)throw new Error(`Incompatible ranks during merge: ${t} vs. ${e}`);const i=[];for(let s=0;s<t.length;++s){const o=t[s],r=e[s];if(o>=0&&r>=0&&o!==r)throw new Error(`Incompatible shape during merge: ${t} vs. ${e}`);i[s]=o>=0?o:r}return i}class ln{constructor(t,e,i,s,o,r,u){this.name=t,this.dtype=e,this.maxSize=i,this.elementShape=s,this.identicalElementShapes=o,this.dynamicSize=r,this.clearAfterRead=u,this.tensors=[],this.closed_=!1,this.idTensor=Sr(0),Qo(this.idTensor)}get id(){return this.idTensor.id}get closed(){return this.closed_}clearAndClose(t){this.tensors.forEach((e=>{null!=t&&t.has(e.tensor.id)||e.tensor.dispose()})),this.tensors=[],this.closed_=!0,this.idTensor.dispose()}size(){return this.tensors.length}read(t){if(this.closed_)throw new Error(`TensorArray ${this.name} has already been closed.`);if(t<0||t>=this.size())throw new Error(`Tried to read from index ${t}, but array size is: ${this.size()}`);const e=this.tensors[t];if(e.cleared)throw new Error(`TensorArray ${this.name}: Could not read index ${t} twice because it was cleared after a previous read (perhaps try setting clear_after_read = false?).`);return this.clearAfterRead&&(e.cleared=!0),e.read=!0,e.tensor}readMany(t){return t.map((t=>this.read(t)))}write(t,e){if(this.closed_)throw new Error(`TensorArray ${this.name} has already been closed.`);if(t<0||!this.dynamicSize&&t>=this.maxSize)throw new Error(`Tried to write to index ${t}, but array is not resizeable and size is: ${this.maxSize}`);const i=this.tensors[t]||{};if(e.dtype!==this.dtype)throw new Error(`TensorArray ${this.name}: Could not write to TensorArray index ${t},\n          because the value dtype is ${e.dtype}, but TensorArray dtype is ${this.dtype}.`);if(0!==this.size()||null!=this.elementShape&&0!==this.elementShape.length||(this.elementShape=e.shape),assertShapesMatchAllowUndefinedSize(this.elementShape,e.shape,`TensorArray ${this.name}: Could not write to TensorArray index ${t}.`),i.read)throw new Error(`TensorArray ${this.name}: Could not write to TensorArray index ${t}, because it has already been read.`);if(i.written)throw new Error(`TensorArray ${this.name}: Could not write to TensorArray index ${t}, because it has already been written.`);i.tensor=e,Qo(e),i.written=!0,this.tensors[t]=i}writeMany(t,e){if(t.length!==e.length)throw new Error(`TensorArray ${this.name}: could not write multiple tensors,because the index size: ${t.length} is not the same as tensors size: ${e.length}.`);t.forEach(((t,i)=>this.write(t,e[i])))}gather(t,e){if(e&&e!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but gather requested dtype ${e}`);if(t)t=t.slice(0,this.size());else{t=[];for(let e=0;e<this.size();e++)t.push(e)}if(0===t.length)return As([],[0].concat(this.elementShape));const i=this.readMany(t);return assertShapesMatchAllowUndefinedSize(this.elementShape,i[0].shape,"TensorArray shape mismatch: "),Tu(i,0)}concat(t){if(t&&t!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but concat requested dtype ${t}`);if(0===this.size())return As([],[0].concat(this.elementShape));const e=[];for(let t=0;t<this.size();t++)e.push(t);const i=this.readMany(e);return assertShapesMatchAllowUndefinedSize(this.elementShape,i[0].shape,`TensorArray shape mismatch: tensor array shape (${this.elementShape}) vs first tensor shape (${i[0].shape})`),Mr(i,0)}scatter(t,e){if(e.dtype!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but tensor has dtype ${e.dtype}`);if(t.length!==e.shape[0])throw new Error(`Expected len(indices) == tensor.shape[0], but saw: ${t.length} vs. ${e.shape[0]}`);const i=Math.max(...t);if(!this.dynamicSize&&i>=this.maxSize)throw new Error(`Max index must be < array size (${i}  vs. ${this.maxSize})`);this.writeMany(t,ku(e,0))}split(t,e){if(e.dtype!==this.dtype)throw new Error(`TensorArray dtype is ${this.dtype} but tensor has dtype ${e.dtype}`);let i=0;const s=t.map((t=>(i+=t,i)));if(i!==e.shape[0])throw new Error(`Expected sum of lengths to be equal to\n          tensor.shape[0], but sum of lengths is\n        ${i}, and tensor's shape is: ${e.shape}`);if(!this.dynamicSize&&t.length!==this.maxSize)throw new Error(`TensorArray's size is not equal to the size of lengths (${this.maxSize} vs. ${t.length}), and the TensorArray is not marked as dynamically resizeable`);const o=0===i?0:e.size/i,r=[];Po((()=>{e=nr(e,[1,i,o]);for(let i=0;i<t.length;++i){const u=[0,0===i?0:s[i-1],0],a=[1,t[i],o];r[i]=nr(vr(e,u,a),this.elementShape)}return r}));const u=[];for(let e=0;e<t.length;e++)u[e]=e;this.writeMany(u,r)}}class gn{constructor(t,e,i,s=-1){this.tensors=t,this.elementShape=e,this.elementDtype=i,null!=t&&t.forEach((t=>{if(i!==t.dtype)throw new Error(`Invalid data types; op elements ${i}, but list elements ${t.dtype}`);assertShapesMatchAllowUndefinedSize(e,t.shape,"TensorList shape mismatch: "),Qo(t)})),this.idTensor=Sr(0),this.maxNumElements=s,Qo(this.idTensor)}get id(){return this.idTensor.id}copy(){return new gn([...this.tensors],this.elementShape,this.elementDtype)}clearAndClose(t){this.tensors.forEach((e=>{null!=t&&t.has(e.id)||e.dispose()})),this.tensors.length=0,this.idTensor.dispose()}size(){return this.tensors.length}stack(t,e,i=-1){if(e!==this.elementDtype)throw new Error(`Invalid data types; op elements ${e}, but list elements ${this.elementDtype}`);if(-1!==i&&this.tensors.length!==i)throw new Error(`Operation expected a list with ${i} elements but got a list with ${this.tensors.length} elements.`);assertShapesMatchAllowUndefinedSize(t,this.elementShape,"TensorList shape mismatch: ");const s=vn(this.elementShape,this.tensors,t);return Po((()=>{const t=this.tensors.map((t=>nr(t,s)));return Tu(t,0)}))}popBack(t,e){if(e!==this.elementDtype)throw new Error(`Invalid data types; op elements ${e}, but list elements ${this.elementDtype}`);if(0===this.size())throw new Error("Trying to pop from an empty list.");const i=vn(this.elementShape,this.tensors,t),s=this.tensors.pop();return assertShapesMatchAllowUndefinedSize(s.shape,t,"TensorList shape mismatch: "),nr(s,i)}pushBack(t){if(t.dtype!==this.elementDtype)throw new Error(`Invalid data types; op elements ${t.dtype}, but list elements ${this.elementDtype}`);if(assertShapesMatchAllowUndefinedSize(t.shape,this.elementShape,"TensorList shape mismatch: "),this.maxNumElements===this.size())throw new Error("Trying to push element into a full list.");Qo(t),this.tensors.push(t)}resize(t){if(t<0)throw new Error(`TensorListResize expects size to be non-negative. Got: ${t}`);if(-1!==this.maxNumElements&&t>this.maxNumElements)throw new Error(`TensorListResize input size ${t} is greater maxNumElement ${this.maxNumElements}.`);const e=new gn([],this.elementShape,this.elementDtype,this.maxNumElements);e.tensors.length=t;for(let i=0;i<Math.min(this.tensors.length,t);++i)e.tensors[i]=this.tensors[i];return e}getItem(t,e,i){if(i!==this.elementDtype)throw new Error(`Invalid data types; op elements ${i}, but list elements ${this.elementDtype}`);if(t<0||t>this.tensors.length)throw new Error(`Trying to access element ${t} in a list with ${this.tensors.length} elements.`);if(null==this.tensors[t])throw new Error(`element at index ${t} is null.`);assertShapesMatchAllowUndefinedSize(this.tensors[t].shape,e,"TensorList shape mismatch: ");const s=vn(this.elementShape,this.tensors,e);return nr(this.tensors[t],s)}setItem(t,e){if(e.dtype!==this.elementDtype)throw new Error(`Invalid data types; op elements ${e.dtype}, but list elements ${this.elementDtype}`);if(t<0||-1!==this.maxNumElements&&t>=this.maxNumElements)throw new Error(`Trying to set element ${t} in a list with max ${this.maxNumElements} elements.`);assertShapesMatchAllowUndefinedSize(this.elementShape,e.shape,"TensorList shape mismatch: "),Qo(e),this.tensors[t]=e}gather(t,e,i){if(e!==this.elementDtype)throw new Error(`Invalid data types; op elements ${e}, but list elements ${this.elementDtype}`);assertShapesMatchAllowUndefinedSize(this.elementShape,i,"TensorList shape mismatch: "),t=t.slice(0,this.size());const s=vn(this.elementShape,this.tensors,i);return 0===t.length?As([],[0].concat(s)):Po((()=>{const e=t.map((t=>nr(this.tensors[t],s)));return Tu(e,0)}))}concat(t,e){if(t&&t!==this.elementDtype)throw new Error(`TensorList dtype is ${this.elementDtype} but concat requested dtype ${t}`);assertShapesMatchAllowUndefinedSize(this.elementShape,e,"TensorList shape mismatch: ");const i=vn(this.elementShape,this.tensors,e);return 0===this.size()?As([],[0].concat(i)):Po((()=>{const t=this.tensors.map((t=>nr(t,i)));return Mr(t,0)}))}}function pn(t,e,i){const s=t.dtype;if(t.shape.length<1)throw new Error(`Tensor must be at least a vector, but saw shape: ${t.shape}`);if(t.dtype!==i)throw new Error(`Invalid data types; op elements ${t.dtype}, but list elements ${i}`);const o=t.shape.slice(1);assertShapesMatchAllowUndefinedSize(o,e,"TensorList shape mismatch: ");const r=ku(t);return new gn(r,e,s)}function jn(t,e,i,s){return new gn([],t,e,s)}function An(t,e,i,s){if(e.length!==t.shape[0])throw new Error(`Expected len(indices) == tensor.shape[0], but saw: ${e.length} vs. ${t.shape[0]}`);const o=Math.max(...e);if(null!=s&&-1!==s&&o>=s)throw new Error(`Max index must be < array size (${o}  vs. ${s})`);const r=new gn([],i,t.dtype,s),u=ku(t,0);return e.forEach(((t,e)=>{r.setItem(t,u[e])})),r}const cn=async(t,e,i)=>{switch(t.op){case"If":case"StatelessIf":{const s=za("thenBranch",t,e,i),o=za("elseBranch",t,e,i),r=za("cond",t,e,i),u=za("args",t,e,i);return(await r.data())[0]?i.functionMap[s].executeFunctionAsync(u,i.tensorArrayMap,i.tensorListMap):i.functionMap[o].executeFunctionAsync(u,i.tensorArrayMap,i.tensorListMap)}case"While":case"StatelessWhile":{const s=za("body",t,e,i),o=za("cond",t,e,i),r=za("args",t,e,i),u=await i.functionMap[o].executeFunctionAsync(r,i.tensorArrayMap,i.tensorListMap),a=r.map((t=>t.id));let n=await u[0].data();u.forEach((t=>{t.kept||-1!==a.indexOf(t.id)||t.dispose()}));let L=r;for(;n[0];){const t=L;L=await i.functionMap[s].executeFunctionAsync(L,i.tensorArrayMap,i.tensorListMap);const e=L.map((t=>t.id));t.forEach((t=>{t.kept||-1!==a.indexOf(t.id)||-1!==e.indexOf(t.id)||t.dispose()}));const r=await i.functionMap[o].executeFunctionAsync(L,i.tensorArrayMap,i.tensorListMap);n=await r[0].data(),r.forEach((t=>{t.kept||-1!==a.indexOf(t.id)||-1!==e.indexOf(t.id)||t.dispose()}))}return L}case"LoopCond":return[ba(za("pred",t,e,i))];case"Switch":{const s=za("pred",t,e,i);let o=za("data",t,e,i);return o.kept||(o=ba(o)),(await s.data())[0]?[void 0,o]:[o,void 0]}case"Merge":{const s=t.inputNames.find((t=>void 0!==xa(t,e,i)));if(s){return[ba(xa(s,e,i))]}return}case"Enter":{const s=za("frameName",t,e,i),o=za("tensor",t,e,i);return i.enterFrame(s),[ba(o)]}case"Exit":{const s=za("tensor",t,e,i);return i.exitFrame(),[ba(s)]}case"NextIteration":{const s=za("tensor",t,e,i);return i.nextIteration(),[ba(s)]}case"TensorArrayV3":{const s=za("size",t,e,i),o=za("dtype",t,e,i),r=za("elementShape",t,e,i),u=za("dynamicSize",t,e,i),a=za("clearAfterRead",t,e,i),n=za("identicalElementShapes",t,e,i),L=za("name",t,e,i),M=new ln(L,o,s,r,n,u,a);return i.addTensorArray(M),[M.idTensor,Sr(1)]}case"TensorArrayWriteV3":{const s=za("tensorArrayId",t,e,i),o=za("index",t,e,i),r=za("tensor",t,e,i),u=i.getTensorArray(s.id);return u.write(o,r),[u.idTensor]}case"TensorArrayReadV3":{const s=za("tensorArrayId",t,e,i),o=za("index",t,e,i);return[i.getTensorArray(s.id).read(o)]}case"TensorArrayGatherV3":{const s=za("tensorArrayId",t,e,i),o=za("indices",t,e,i),r=za("dtype",t,e,i);return[i.getTensorArray(s.id).gather(o,r)]}case"TensorArrayScatterV3":{const s=za("tensorArrayId",t,e,i),o=za("indices",t,e,i),r=za("tensor",t,e,i),u=i.getTensorArray(s.id);return u.scatter(o,r),[u.idTensor]}case"TensorArrayConcatV3":{const s=za("tensorArrayId",t,e,i),o=i.getTensorArray(s.id),r=za("dtype",t,e,i);return[o.concat(r)]}case"TensorArraySplitV3":{const s=za("tensorArrayId",t,e,i),o=za("tensor",t,e,i),r=za("lengths",t,e,i),u=i.getTensorArray(s.id);return u.split(r,o),[u.idTensor]}case"TensorArraySizeV3":{const s=za("tensorArrayId",t,e,i);return[Sr(i.getTensorArray(s.id).size(),"int32")]}case"TensorArrayCloseV3":{const s=za("tensorArrayId",t,e,i),o=i.getTensorArray(s.id);return o.clearAndClose(),[o.idTensor]}case"TensorListSetItem":{const s=za("tensorListId",t,e,i),o=za("index",t,e,i),r=za("tensor",t,e,i),u=i.getTensorList(s.id);return u.setItem(o,r),[u.idTensor]}case"TensorListGetItem":{const s=za("tensorListId",t,e,i),o=za("index",t,e,i),r=za("elementShape",t,e,i),u=za("elementDType",t,e,i);return[i.getTensorList(s.id).getItem(o,r,u)]}case"TensorListScatterV2":case"TensorListScatter":{const s=za("indices",t,e,i),o=An(za("tensor",t,e,i),s,za("elementShape",t,e,i),za("numElements",t,e,i));return i.addTensorList(o),[o.idTensor]}case"TensorListReserve":case"EmptyTensorList":{const s=za("elementShape",t,e,i),o=za("elementDType",t,e,i);let r;r="TensorListReserve"===t.op?"numElements":"maxNumElements";const u=za(r,t,e,i),a=jn(s,o,0,"TensorListReserve"===t.op?-1:u);return i.addTensorList(a),[a.idTensor]}case"TensorListGather":{const s=za("tensorListId",t,e,i),o=za("indices",t,e,i),r=za("elementShape",t,e,i),u=za("elementDType",t,e,i);return[i.getTensorList(s.id).gather(o,u,r)]}case"TensorListStack":{const s=za("tensorListId",t,e,i),o=za("elementShape",t,e,i),r=za("elementDType",t,e,i),u=za("numElements",t,e,i);return[i.getTensorList(s.id).stack(o,r,u)]}case"TensorListFromTensor":{const s=pn(za("tensor",t,e,i),za("elementShape",t,e,i),za("elementDType",t,e,i));return i.addTensorList(s),[s.idTensor]}case"TensorListConcat":case"TensorListConcatV2":{const s=za("tensorListId",t,e,i),o=i.getTensorList(s.id),r=za("dtype",t,e,i),u=za("elementShape",t,e,i);return[o.concat(r,u)]}case"TensorListPushBack":{const s=za("tensorListId",t,e,i),o=za("tensor",t,e,i),r=i.getTensorList(s.id);return r.pushBack(o),[r.idTensor]}case"TensorListPopBack":{const s=za("tensorListId",t,e,i),o=za("elementShape",t,e,i),r=za("elementDType",t,e,i);return[i.getTensorList(s.id).popBack(o,r)]}case"TensorListSplit":{const s=za("tensor",t,e,i),o=za("elementShape",t,e,i),r=za("lengths",t,e,i),u=split$1(s,r,o);return i.addTensorList(u),[u.idTensor]}case"TensorListLength":{const s=za("tensorListId",t,e,i);return[Sr(i.getTensorList(s.id).size(),"int32")]}case"TensorListResize":{const s=za("tensorListId",t,e,i),o=za("size",t,e,i),r=i.getTensorList(s.id).resize(o);return i.addTensorList(r),[r.idTensor]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},In=(t,e,i,s=wt)=>{switch(t.op){case"Conv1D":{const o=za("stride",t,e,i),r=za("pad",t,e,i),u=za("dataFormat",t,e,i).toUpperCase(),a=za("dilation",t,e,i);return[s.conv1d(za("x",t,e,i),za("filter",t,e,i),o,r,u,a)]}case"Conv2D":{const o=za("strides",t,e,i),r=Qa(t,e,i),u=za("dataFormat",t,e,i).toUpperCase(),a=za("dilations",t,e,i);return[s.conv2d(za("x",t,e,i),za("filter",t,e,i),[o[1],o[2]],r,u,[a[1],a[2]])]}case"_FusedConv2D":{const{stride:o,pad:r,dataFormat:u,dilations:a,biasArg:n,preluArg:L,activationFunc:M,leakyreluAlpha:C}=fusedConvAndDepthWiseParams(t,e,i);return[s.fused.conv2d({x:za("x",t,e,i),filter:za("filter",t,e,i),strides:[o[1],o[2]],pad:r,dataFormat:u,dilations:[a[1],a[2]],bias:n,activation:M,preluActivationWeights:L,leakyreluAlpha:C})]}case"FusedDepthwiseConv2dNative":{const{stride:o,pad:r,dataFormat:u,dilations:a,biasArg:n,preluArg:L,activationFunc:M,leakyreluAlpha:C}=fusedConvAndDepthWiseParams(t,e,i);return[s.fused.depthwiseConv2d({x:za("x",t,e,i),filter:za("filter",t,e,i),strides:[o[1],o[2]],pad:r,dataFormat:u,dilations:[a[1],a[2]],bias:n,activation:M,preluActivationWeights:L,leakyreluAlpha:C})]}case"Conv2DBackpropInput":case"Conv2dTranspose":{const o=za("outputShape",t,e,i),r=za("strides",t,e,i),u=Qa(t,e,i);return[s.conv2dTranspose(za("x",t,e,i),za("filter",t,e,i),o,[r[1],r[2]],u)]}case"DepthwiseConv2dNative":case"DepthwiseConv2d":{const o=za("strides",t,e,i),r=Qa(t,e,i),u=za("dilations",t,e,i),a=za("dataFormat",t,e,i).toUpperCase();return[s.depthwiseConv2d(za("input",t,e,i),za("filter",t,e,i),[o[1],o[2]],r,a,[u[1],u[2]])]}case"Conv3D":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("dataFormat",t,e,i).toUpperCase(),a=za("dilations",t,e,i);return[s.conv3d(za("x",t,e,i),za("filter",t,e,i),[o[1],o[2],o[3]],r,u,[a[1],a[2],a[3]])]}case"AvgPool":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("kernelSize",t,e,i);return[s.avgPool(za("x",t,e,i),[u[1],u[2]],[o[1],o[2]],r)]}case"MaxPool":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("kernelSize",t,e,i);return[s.maxPool(za("x",t,e,i),[u[1],u[2]],[o[1],o[2]],r)]}case"MaxPoolWithArgmax":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("kernelSize",t,e,i),a=za("includeBatchInIndex",t,e,i),{result:n,indexes:L}=s.maxPoolWithArgmax(za("x",t,e,i),[u[1],u[2]],[o[1],o[2]],r,a);return[n,L]}case"AvgPool3D":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("kernelSize",t,e,i);return[s.avgPool3d(za("x",t,e,i),[u[1],u[2],u[3]],[o[1],o[2],o[3]],r)]}case"MaxPool3D":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("kernelSize",t,e,i);return[s.maxPool3d(za("x",t,e,i),[u[1],u[2],u[3]],[o[1],o[2],o[3]],r)]}case"Dilation2D":{const o=za("strides",t,e,i),r=za("pad",t,e,i),u=za("dilations",t,e,i),a=o[1],n=o[2],L=u[1],M=u[2];return[s.dilation2d(za("x",t,e,i),za("filter",t,e,i),[a,n],r,[L,M],"NHWC")]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},mn=(t,e,i,s=wt)=>{switch(t.op){case"Fill":{const o=za("shape",t,e,i),r=za("dtype",t,e,i),u=za("value",t,e,i);return[s.fill(o,u,r)]}case"LinSpace":{const o=za("start",t,e,i),r=za("stop",t,e,i),u=za("num",t,e,i);return[s.linspace(o,r,u)]}case"Multinomial":{const o=za("logits",t,e,i),r=za("numSamples",t,e,i),u=za("seed",t,e,i);return[s.multinomial(o,r,u)]}case"OneHot":{const o=za("indices",t,e,i),r=za("depth",t,e,i),u=za("onValue",t,e,i),a=za("offValue",t,e,i);return[s.oneHot(o,r,u,a)]}case"Ones":return[s.ones(za("shape",t,e,i),za("dtype",t,e,i))];case"OnesLike":return[s.onesLike(za("x",t,e,i))];case"RandomStandardNormal":return[s.randomStandardNormal(za("shape",t,e,i),za("dtype",t,e,i),za("seed",t,e,i))];case"RandomUniform":return[s.randomUniform(za("shape",t,e,i),za("minval",t,e,i),za("maxval",t,e,i),za("dtype",t,e,i))];case"Range":{const o=za("start",t,e,i),r=za("stop",t,e,i),u=za("step",t,e,i);return[s.range(o,r,u,za("dtype",t,e,i))]}case"TruncatedNormal":{const o=za("shape",t,e,i),r=za("mean",t,e,i),u=za("stdDev",t,e,i),a=za("seed",t,e,i);return[s.truncatedNormal(o,r,u,za("dtype",t,e,i),a)]}case"Zeros":return[s.zeros(za("shape",t,e,i),za("dtype",t,e,i))];case"ZerosLike":return[s.zerosLike(za("x",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},hn=async(t,e,i,s,o=wt)=>{switch(t.op){case"NonMaxSuppressionV5":{const{boxes:s,scores:r,maxOutputSize:u,iouThreshold:a,scoreThreshold:n,softNmsSigma:L}=nmsParams(t,e,i),M=await o.image.nonMaxSuppressionWithScoreAsync(s,r,u,a,n,L);return[M.selectedIndices,M.selectedScores]}case"NonMaxSuppressionV4":{const{boxes:s,scores:r,maxOutputSize:u,iouThreshold:a,scoreThreshold:n}=nmsParams(t,e,i),L=za("padToMaxOutputSize",t,e,i),M=await o.image.nonMaxSuppressionPaddedAsync(s,r,u,a,n,L);return[M.selectedIndices,M.validOutputs]}case"NonMaxSuppressionV3":case"NonMaxSuppressionV2":{const{boxes:s,scores:r,maxOutputSize:u,iouThreshold:a,scoreThreshold:n}=nmsParams(t,e,i);return[await o.image.nonMaxSuppressionAsync(s,r,u,a,n)]}case"Where":{const s=o.cast(za("condition",t,e,i),"bool"),r=[await o.whereAsync(s)];return s.dispose(),r}case"ListDiff":return o.setdiff1dAsync(za("x",t,e,i),za("y",t,e,i));default:throw TypeError(`Node type ${t.op} is not implemented`)}},On=(t,e,i,s=wt)=>{switch(t.op){case"LowerBound":{const o=za("sortedSequence",t,e,i),r=za("values",t,e,i);return[s.lowerBound(o,r)]}case"TopKV2":{const o=za("x",t,e,i),r=za("k",t,e,i),u=za("sorted",t,e,i),a=s.topk(o,r,u);return[a.values,a.indices]}case"UpperBound":{const o=za("sortedSequence",t,e,i),r=za("values",t,e,i);return[s.upperBound(o,r)]}case"Unique":{const o=za("x",t,e,i),r=s.unique(o);return[r.values,r.indices]}case"UniqueV2":{const o=za("x",t,e,i),r=za("axis",t,e,i),u=s.unique(o,r);return[u.values,u.indices]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},zn=(t,e,i,s=wt)=>{switch(t.op){case"Const":return e[t.name];case"PlaceholderWithDefault":const o=za("default",t,e,i);return[xa(t.name,e,i)||o];case"Placeholder":return[xa(t.name,e,i)];case"Identity":case"StopGradient":case"FakeQuantWithMinMaxVars":return[ba(za("x",t,e,i))];case"IdentityN":return za("x",t,e,i).map((t=>ba(t)));case"Snapshot":return[ba(za("x",t,e,i))];case"Shape":return[s.tensor1d(za("x",t,e,i).shape,"int32")];case"ShapeN":return za("x",t,e,i).map((t=>s.tensor1d(t.shape)));case"Size":return[s.scalar(za("x",t,e,i).size,"int32")];case"Rank":return[s.scalar(za("x",t,e,i).rank,"int32")];case"NoOp":return[s.scalar(1)];case"Print":const r=za("x",t,e,i),u=za("data",t,e,i),a=za("message",t,e,i),n=za("summarize",t,e,i);console.warn("The graph has a tf.print() operation,usually used for debugging, which slows down performance."),console.log(a);for(let t=0;t<u.length;t++)console.log(Array.prototype.slice.call(u[t].dataSync()).slice(0,n));return[r];default:throw TypeError(`Node type ${t.op} is not implemented`)}};class xn{constructor(t,e){this.keyDType=t,this.valueDType=e,this.handle=Sr(0),this.tensorMap=new Map,Qo(this.handle)}get id(){return this.handle.id}clearAndClose(){this.tensorMap.forEach((t=>t.dispose())),this.tensorMap.clear(),this.handle.dispose()}size(){return this.tensorMap.size}tensorSize(){return Sr(this.size(),"int32")}async import(t,e){this.checkKeyAndValueTensor(t,e);const i=await t.data();return this.tensorMap.forEach((t=>t.dispose())),this.tensorMap.clear(),Po((()=>{const t=ku(e),s=i.length,o=t.length;Kt(s===o,(()=>`The number of elements doesn't match, keys has ${s} elements, the values has ${o} elements.`));for(let e=0;e<s;e++){const s=i[e],o=t[e];Qo(o),this.tensorMap.set(s,o)}return this.handle}))}async find(t,e){this.checkKeyAndValueTensor(t,e);const i=await t.data();return Po((()=>{const t=[];for(let s=0;s<i.length;s++){const o=i[s],r=this.findWithDefault(o,e);t.push(r)}return Tu(t)}))}findWithDefault(t,e){const i=this.tensorMap.get(t);return null!=i?i:e}checkKeyAndValueTensor(t,e){if(t.dtype!==this.keyDType)throw new Error(`Expect key dtype ${this.keyDType}, but got ${t.dtype}`);if(e.dtype!==this.valueDType)throw new Error(`Expect value dtype ${this.valueDType}, but got ${e.dtype}`)}}const dn=async(t,e,i,s)=>{switch(t.op){case"HashTable":case"HashTableV2":{const o=za("keyDType",t,e,i),r=za("valueDType",t,e,i),u=new xn(o,r);return s.addHashTable(t.name,u),[u.handle]}case"LookupTableImport":case"LookupTableImportV2":{const o=za("tableHandle",t,e,i,s),r=za("keys",t,e,i),u=za("values",t,e,i),a=s.getHashTableById(o.id);return[await a.import(r,u)]}case"LookupTableFind":case"LookupTableFindV2":{const o=za("tableHandle",t,e,i,s),r=za("keys",t,e,i),u=za("defaultValue",t,e,i),a=s.getHashTableById(o.id);return[await a.find(r,u)]}case"LookupTableSize":case"LookupTableSizeV2":{const o=za("tableHandle",t,e,i,s);return[s.getHashTableById(o.id).tensorSize()]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},Kn=(t,e,i,s=wt)=>{switch(t.op){case"ResizeBilinear":{const o=za("images",t,e,i),r=za("size",t,e,i),u=za("alignCorners",t,e,i),a=za("halfPixelCenters",t,e,i);return[s.image.resizeBilinear(o,[r[0],r[1]],u,a)]}case"ResizeNearestNeighbor":{const o=za("images",t,e,i),r=za("size",t,e,i),u=za("alignCorners",t,e,i),a=za("halfPixelCenters",t,e,i);return[s.image.resizeNearestNeighbor(o,[r[0],r[1]],u,a)]}case"CropAndResize":{const o=za("image",t,e,i),r=za("boxes",t,e,i),u=za("boxInd",t,e,i),a=za("cropSize",t,e,i),n=za("method",t,e,i),L=za("extrapolationValue",t,e,i);return[s.image.cropAndResize(o,r,u,a,n,L)]}case"ImageProjectiveTransformV3":{const o=za("images",t,e,i),r=za("transforms",t,e,i),u=za("outputShape",t,e,i),a=za("fillValue",t,e,i),n=za("interpolation",t,e,i),L=za("fillMode",t,e,i);return[s.image.transform(o,r,n.toLowerCase(),L.toLowerCase(),a,u)]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},Pn=(t,e,i,s=wt)=>{switch(t.op){case"Equal":return[s.equal(za("a",t,e,i),za("b",t,e,i))];case"NotEqual":return[s.notEqual(za("a",t,e,i),za("b",t,e,i))];case"Greater":return[s.greater(za("a",t,e,i),za("b",t,e,i))];case"GreaterEqual":return[s.greaterEqual(za("a",t,e,i),za("b",t,e,i))];case"Less":return[s.less(za("a",t,e,i),za("b",t,e,i))];case"LessEqual":return[s.lessEqual(za("a",t,e,i),za("b",t,e,i))];case"LogicalAnd":return[s.logicalAnd(za("a",t,e,i),za("b",t,e,i))];case"LogicalNot":return[s.logicalNot(za("a",t,e,i))];case"LogicalOr":return[s.logicalOr(za("a",t,e,i),za("b",t,e,i))];case"Select":case"SelectV2":return[s.where(za("condition",t,e,i),za("a",t,e,i),za("b",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},Yn=(t,e,i,s=wt)=>{switch(t.op){case"BatchMatMul":case"BatchMatMulV2":case"MatMul":return[s.matMul(za("a",t,e,i),za("b",t,e,i),za("transposeA",t,e,i),za("transposeB",t,e,i))];case"Einsum":return[s.einsum(za("equation",t,e,i),...za("tensors",t,e,i))];case"Transpose":return[s.transpose(za("x",t,e,i),za("perm",t,e,i))];case"_FusedMatMul":const[o,r]=za("fusedOps",t,e,i),u="biasadd"===o,a="prelu"===r,n=za("numArgs",t,e,i),L=za("leakyreluAlpha",t,e,i);if(u){if(a&&2!==n)throw new Error("Fused MatMul with BiasAdd and Prelu must have two extra arguments: bias and alpha.");if(!a&&1!==n)throw new Error("Fused MatMul with BiasAdd must have one extra argument: bias.")}const[M,C]=za("args",t,e,i);return[s.fused.matMul({a:za("a",t,e,i),b:za("b",t,e,i),transposeA:za("transposeA",t,e,i),transposeB:za("transposeB",t,e,i),bias:M,activation:r,preluActivationWeights:C,leakyreluAlpha:L})];default:throw TypeError(`Node type ${t.op} is not implemented`)}},Qn=(t,e,i,s=wt)=>{switch(t.op){case"EuclideanNorm":return[s.euclideanNorm(za("x",t,e,i),za("axis",t,e,i),za("keepDims",t,e,i))];case"FusedBatchNorm":case"FusedBatchNormV2":case"FusedBatchNormV3":return[s.batchNorm(za("x",t,e,i),za("mean",t,e,i),za("variance",t,e,i),za("offset",t,e,i),za("scale",t,e,i),za("epsilon",t,e,i))];case"LRN":return[s.localResponseNormalization(za("x",t,e,i),za("radius",t,e,i),za("bias",t,e,i),za("alpha",t,e,i),za("beta",t,e,i))];case"Softmax":return[s.softmax(za("x",t,e,i))];case"LogSoftmax":return[s.logSoftmax(za("x",t,e,i))];case"SparseToDense":return[s.sparseToDense(za("sparseIndices",t,e,i),za("outputShape",t,e,i),za("sparseValues",t,e,i),za("defaultValue",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},bn=(t,e,i,s=wt)=>{switch(t.op){case"Max":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.max(za("x",t,e,i),o,r)]}case"Mean":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.mean(za("x",t,e,i),o,r)]}case"Min":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.min(za("x",t,e,i),o,r)]}case"Sum":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.sum(za("x",t,e,i),o,r)]}case"All":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.all(za("x",t,e,i),o,r)]}case"Any":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.any(za("x",t,e,i),o,r)]}case"ArgMax":{const o=za("axis",t,e,i);return[s.argMax(za("x",t,e,i),o)]}case"ArgMin":{const o=za("axis",t,e,i);return[s.argMin(za("x",t,e,i),o)]}case"Prod":{const o=za("axis",t,e,i),r=za("keepDims",t,e,i);return[s.prod(za("x",t,e,i),o,r)]}case"Cumprod":{const o=za("axis",t,e,i),r=za("exclusive",t,e,i),u=za("reverse",t,e,i);return[s.cumprod(za("x",t,e,i),o,r,u)]}case"Cumsum":{const o=za("axis",t,e,i),r=za("exclusive",t,e,i),u=za("reverse",t,e,i);return[s.cumsum(za("x",t,e,i),o,r,u)]}case"Bincount":const o=za("x",t,e,i),r=za("weights",t,e,i),u=za("size",t,e,i);return[s.bincount(o,r,u)];case"DenseBincount":{const o=za("x",t,e,i),r=za("weights",t,e,i),u=za("size",t,e,i),a=za("binaryOutput",t,e,i);return[s.denseBincount(o,r,u,a)]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},En=(t,e,i,s=wt)=>{switch(t.op){case"ConcatV2":case"Concat":{const o=za("n",t,e,i),r=za("axis",t,e,i);let u=za("tensors",t,e,i);return u=u.slice(0,o),[s.concat(u,r)]}case"Gather":{const o=za("x",t,e,i),r=za("indices",t,e,i);return[s.gather(o,s.cast(r,"int32"),0)]}case"GatherV2":{const o=za("axis",t,e,i),r=za("batchDims",t,e,i),u=za("x",t,e,i),a=za("indices",t,e,i);return[s.gather(u,s.cast(a,"int32"),o,r)]}case"Reverse":{const o=za("dims",t,e,i),r=[];for(let t=0;t<o.length;t++)o[t]&&r.push(t);const u=za("x",t,e,i);return[s.reverse(u,r)]}case"ReverseV2":{const o=za("axis",t,e,i),r=za("x",t,e,i);return[s.reverse(r,o)]}case"Slice":{const o=za("begin",t,e,i),r=za("size",t,e,i);return[s.slice(za("x",t,e,i),o,r)]}case"StridedSlice":{const o=za("begin",t,e,i),r=za("end",t,e,i),u=za("strides",t,e,i),a=za("beginMask",t,e,i),n=za("endMask",t,e,i),L=za("ellipsisMask",t,e,i),M=za("newAxisMask",t,e,i),C=za("shrinkAxisMask",t,e,i),w=za("x",t,e,i);return[s.stridedSlice(w,o,r,u,a,n,L,M,C)]}case"Pack":return Po((()=>{const o=za("axis",t,e,i),r=za("tensors",t,e,i),u=r[0].shape,a=s.squeeze(r[0]).shape,n=r.map((t=>{const e=Et(t.shape,u);if(!e&&!Et(s.squeeze(t).shape,a))throw new Error("the input tensors shape does not match");return e?t:s.reshape(t,u)}));return[s.stack(n,o)]}));case"Unpack":{const o=za("axis",t,e,i),r=za("tensor",t,e,i);return s.unstack(r,o)}case"Tile":{const o=za("reps",t,e,i);return[s.tile(za("x",t,e,i),o)]}case"Split":case"SplitV":{const o=za("axis",t,e,i),r=za("numOrSizeSplits",t,e,i),u=za("x",t,e,i);return s.split(u,r,o)}case"ScatterNd":{const o=za("indices",t,e,i),r=za("values",t,e,i),u=za("shape",t,e,i);return[s.scatterND(o,r,u)]}case"GatherNd":{const o=za("x",t,e,i),r=za("indices",t,e,i);return[s.gatherND(o,r)]}case"SparseToDense":{const o=za("sparseIndices",t,e,i),r=za("outputShape",t,e,i),u=za("sparseValues",t,e,i),a=za("defaultValue",t,e,i);return[s.sparseToDense(o,u,r,u.dtype===a.dtype?a:s.cast(a,u.dtype))]}default:throw TypeError(`Node type ${t.op} is not implemented`)}},Tn=(t,e,i,s=wt)=>{switch(t.op){case"SparseFillEmptyRows":{const{outputIndices:o,outputValues:r,emptyRowIndicator:u,reverseIndexMap:a}=s.sparse.sparseFillEmptyRows(za("indices",t,e,i),za("values",t,e,i),za("denseShape",t,e,i),za("defaultValue",t,e,i));return[o,r,u,a]}case"SparseReshape":{const{outputIndices:o,outputShape:r}=s.sparse.sparseReshape(za("inputIndices",t,e,i),za("inputShape",t,e,i),za("newShape",t,e,i));return[o,r]}case"SparseSegmentMean":return[s.sparse.sparseSegmentMean(za("data",t,e,i),za("indices",t,e,i),za("segmentIds",t,e,i))];case"SparseSegmentSum":return[s.sparse.sparseSegmentSum(za("data",t,e,i),za("indices",t,e,i),za("segmentIds",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},Sn=(t,e,i,s=wt)=>{switch(t.op){case"FFT":return[s.fft(za("x",t,e,i))];case"IFFT":return[s.ifft(za("x",t,e,i))];case"RFFT":return[s.rfft(za("x",t,e,i))];case"IRFFT":return[s.irfft(za("x",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},fn=(t,e,i,s=wt)=>{switch(t.op){case"StringNGrams":{const{nGrams:o,nGramsSplits:r}=s.string.stringNGrams(za("data",t,e,i),za("dataSplits",t,e,i),za("separator",t,e,i),za("nGramWidths",t,e,i),za("leftPad",t,e,i),za("rightPad",t,e,i),za("padWidth",t,e,i),za("preserveShortSequences",t,e,i));return[o,r]}case"StringSplit":{const{indices:o,values:r,shape:u}=s.string.stringSplit(za("input",t,e,i),za("delimiter",t,e,i),za("skipEmpty",t,e,i));return[o,r,u]}case"StringToHashBucketFast":return[s.string.stringToHashBucketFast(za("input",t,e,i),za("numBuckets",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}},qn=(t,e,i,s=wt)=>{switch(t.op){case"Cast":return[s.cast(za("x",t,e,i),za("dtype",t,e,i))];case"ExpandDims":{const o=za("axis",t,e,i);return[s.expandDims(za("x",t,e,i),o)]}case"Squeeze":{const o=za("axis",t,e,i);return[s.squeeze(za("x",t,e,i),o)]}case"Reshape":return[s.reshape(za("x",t,e,i),za("shape",t,e,i))];case"MirrorPad":return[s.mirrorPad(za("x",t,e,i),za("padding",t,e,i),za("mode",t,e,i))];case"PadV2":case"Pad":return[s.pad(za("x",t,e,i),za("padding",t,e,i),za("constantValue",t,e,i))];case"SpaceToBatchND":{const o=za("blockShape",t,e,i),r=za("paddings",t,e,i);return[s.spaceToBatchND(za("x",t,e,i),o,r)]}case"BatchToSpaceND":{const o=za("blockShape",t,e,i),r=za("crops",t,e,i);return[s.batchToSpaceND(za("x",t,e,i),o,r)]}case"DepthToSpace":{const o=za("blockSize",t,e,i),r=za("dataFormat",t,e,i).toUpperCase();return[s.depthToSpace(za("x",t,e,i),o,r)]}case"BroadcastTo":return[s.broadcastTo(za("x",t,e,i),za("shape",t,e,i))];case"BroadcastArgs":return[s.broadcastArgs(za("s0",t,e,i),za("s1",t,e,i))];default:throw TypeError(`Node type ${t.op} is not implemented`)}};function kn(t,e,i,s,o=Po){const r=((t,e,i)=>{switch(t.category){case"arithmetic":return o((()=>wn(t,e,i)));case"basic_math":return o((()=>yn(t,e,i)));case"control":return cn(t,e,i);case"convolution":return o((()=>In(t,e,i)));case"creation":return o((()=>mn(t,e,i)));case"dynamic":return hn(t,e,i);case"evaluation":return o((()=>On(t,e,i)));case"image":return o((()=>Kn(t,e,i)));case"graph":return o((()=>zn(t,e,i)));case"logical":return o((()=>Pn(t,e,i)));case"matrices":return o((()=>Yn(t,e,i)));case"normalization":return o((()=>Qn(t,e,i)));case"reduction":return o((()=>bn(t,e,i)));case"slice_join":return o((()=>En(t,e,i)));case"sparse":return o((()=>Tn(t,e,i)));case"spectral":return o((()=>Sn(t,e,i)));case"string":return o((()=>fn(t,e,i)));case"transformation":return o((()=>qn(t,e,i)));case"hash_table":return dn(t,e,i,s);case"custom":const r=Oa(t.op);if(r&&r.customExecutor)return r.customExecutor(new Cn(t,e,i));throw TypeError(`Custom op ${t.op} is not registered.`);default:throw TypeError(`Unknown op '${t.op}'. File an issue at https://github.com/tensorflow/tfjs/issues so we can add it, or register a custom execution with tf.registerOp()`)}})(t,e,i);return ae(r)?r.then((t=>[].concat(t))):[].concat(r)}class Gn{constructor(t={},e={},i={},s={}){this.weightMap=t,this.tensorArrayMap=e,this.tensorListMap=i,this.functionMap=s,this.rootContext={id:0,frameName:"",iterationId:0},this.contexts=[this.rootContext],this.lastId=0,this.generateCurrentContextIds()}newFrame(t,e){return{id:t,frameName:e,iterationId:0}}set currentContext(t){this.contexts!==t&&(this.contexts=t,this.generateCurrentContextIds())}get currentContext(){return this.contexts}get currentContextId(){return this._currentContextIds[0]}get currentContextIds(){return this._currentContextIds}generateCurrentContextIds(){const t=[];for(let e=0;e<this.contexts.length-1;e++){const i=this.contexts.slice(0,this.contexts.length-e);t.push(this.contextIdforContexts(i))}t.push(""),this._currentContextIds=t}contextIdforContexts(t){return t?t.map((t=>0===t.id&&0===t.iterationId?"":`${t.frameName}-${t.iterationId}`)).join("/"):""}enterFrame(t){this.contexts&&(this.lastId++,this.contexts=this.contexts.slice(),this.contexts.push(this.newFrame(this.lastId,t)),this._currentContextIds.unshift(this.contextIdforContexts(this.contexts)))}exitFrame(){if(!(this.contexts&&this.contexts.length>1))throw new Error("Cannot exit frame, the context is empty");this.contexts=this.contexts.slice(),this.contexts.splice(-1),this.currentContextIds.shift()}nextIteration(){if(!(this.contexts&&this.contexts.length>0))throw new Error("Cannot increase frame iteration, the context is empty");{this.contexts=this.contexts.slice(),this.lastId++;const t=Object.assign({},this.contexts[this.contexts.length-1]);t.iterationId+=1,t.id=this.lastId,this.contexts.splice(-1,1,t),this._currentContextIds.splice(0,1,this.contextIdforContexts(this.contexts))}}getWeight(t){return this.weightMap[t]}addTensorArray(t){this.tensorArrayMap[t.id]=t}getTensorArray(t){return this.tensorArrayMap[t]}addTensorList(t){this.tensorListMap[t.id]=t}getTensorList(t){return this.tensorListMap[t]}dispose(t){for(const e in this.tensorArrayMap)this.tensorArrayMap[e].clearAndClose(t);for(const e in this.tensorListMap)this.tensorListMap[e].clearAndClose(t)}}function Nn(t,e,i,s){const o=new Set,r=[];let u=null,a=null;const n=new Set,L=Object.keys(t).map((t=>Ya(t)[0]));let M=[];null!=s&&(M=s.map((t=>Ya(t.name)[0])));const C=[...e];for(;C.length>0;){const t=C.pop();(Fn(t)||Rn(t)||Hn(t))&&null==u&&(u=t,a=u.children.map((t=>t.name)).filter((t=>o.has(t)))),o.add(t.name),null==i[t.name]&&(-1===L.indexOf(t.name)&&-1===M.indexOf(t.name)&&(0!==t.inputs.length?t.inputs.forEach((t=>{n.has(t.name)||(n.add(t.name),C.push(t))})):r.push(t.name)))}return{inputs:t,outputs:e,usedNodes:o,missingInputs:r,dynamicNode:u,syncInputs:a}}function Bn(t,e,i){const{usedNodes:s,inputs:o}=i,r=[],u=Object.keys(o).map((t=>Ya(t)[0])).map((e=>t.nodes[e])),a=t.initNodes;u.forEach((t=>{s.has(t.name)&&r.push(t)})),t.weights.forEach((t=>{s.has(t.name)&&r.push(t)})),null!=a&&a.forEach((t=>{s.has(t.name)&&r.push(t)}));const n=new Set,L=[];for(;r.length>0;){const t=r.pop();n.add(t.name),e[t.name]||L.push(t),t.children.forEach((t=>{!n.has(t.name)&&s.has(t.name)&&t.inputs.every((t=>n.has(t.name)))&&r.push(t)}))}return L}const Un=["Switch","Merge","Enter","Exit","NextIteration","StatelessIf","StatelessWhile","if","While"],Jn=["NonMaxSuppressionV2","NonMaxSuppressionV3","NonMaxSuppressionV5","Where"],Wn=["HashTable","HashTableV2","LookupTableImport","LookupTableImportV2","LookupTableFind","LookupTableFindV2","LookupTableSize","LookupTableSizeV2"];function Fn(t){return Un.indexOf(t.op)>=0}function Rn(t){return Jn.indexOf(t.op)>=0}function Hn(t){return Wn.indexOf(t.op)>=0}class Vn{constructor(t,e){this.graph=t,this.parent=e,this.compiledMap=new Map,this._weightMap={},this.SEPERATOR=",",this._functions={},this._functionExecutorMap={},this.intermediateTensors={},this.keepTensorForDebug=!1,this._outputs=t.outputs,this._inputs=t.inputs,this._initNodes=t.initNodes,this._signature=t.signature,this._functions=t.functions,null!=t.functions&&Object.keys(t.functions).forEach((e=>{this._functionExecutorMap[e]=new Vn(t.functions[e],this)}))}get weightIds(){return this.parent?this.parent.weightIds:this._weightIds}get functionExecutorMap(){return this.parent?this.parent.functionExecutorMap:this._functionExecutorMap}get weightMap(){return this.parent?this.parent.weightMap:this._weightMap}set weightMap(t){const e=Object.keys(t).map((e=>t[e].map((t=>t.id))));this._weightIds=[].concat(...e),this._weightMap=t}set resourceManager(t){this._resourceManager=t}get inputs(){return this._inputs.map((t=>({name:t.name,shape:t.attrParams.shape?t.attrParams.shape.value:void 0,dtype:t.attrParams.dtype?t.attrParams.dtype.value:void 0})))}get outputs(){return this._outputs.map((t=>({name:t.name,shape:t.attrParams.shape?t.attrParams.shape.value:void 0,dtype:t.attrParams.dtype?t.attrParams.dtype.value:void 0})))}get inputNodes(){return this._inputs.map((t=>t.signatureKey||t.name))}get outputNodes(){return this._outputs.map((t=>{const e=t.signatureKey||t.name;return t.defaultOutput?`${e}:${t.defaultOutput}`:e}))}get functions(){return Object.keys(this._functions).reduce(((t,e)=>(t[e]=this._functions[e].signature,t)),{})}getCompilationKey(t,e){const i=t.map((t=>t.name)).sort(),s=e.map((t=>t.name)).sort();return i.join(this.SEPERATOR)+"--"+s.join(this.SEPERATOR)}compile(t,e){const i=Nn(t,e,this.weightMap,this._initNodes),{missingInputs:s,dynamicNode:o,syncInputs:r}=i;if(null!=o)throw new Error(`This execution contains the node '${o.name}', which has the dynamic op '${o.op}'. Please use model.executeAsync() instead. Alternatively, to avoid the dynamic ops, specify the inputs [${r}]`);if(s.length>0){const i=e.map((t=>t.name)),o=Object.keys(t);throw new Error(`Cannot compute the outputs [${i}] from the provided inputs [${o}]. Missing the following inputs: [${s}]`)}return Bn(this.graph,this.weightMap,i)}execute(t,e){t=this.mapInputs(t);const i=Object.keys(t).sort();this.checkInputs(t),this.checkInputShapeAndType(t),e=this.mapOutputs(e),this.checkOutputs(e);const s=i.map((t=>this.graph.nodes[Ya(t)[0]])),o=e.map((t=>Ya(t)[0]));let r=o.map((t=>this.graph.nodes[t]));this.resetIntermediateTensors(),0===r.length&&(r=this._outputs);const u=this.getCompilationKey(s,r);let a=this.compiledMap.get(u);null==a&&(a=this.compile(t,r),this.compiledMap.set(u,a));const n={},L={};return Po((()=>{const i=new Gn(this.weightMap,n,L,this.functionExecutorMap),s=Object.assign({},this.weightMap);Object.keys(t).forEach((e=>{const[i,o]=Ya(e),r=[];r[o]=t[e],s[i]=r}));const r=this.getFrozenTensorIds(s),u={};for(let t=0;t<a.length;t++){const e=a[t];if(!s[e.name]){const t=kn(e,s,i,this._resourceManager);if(ae(t))throw new Error(`The execution of the op '${e.op}' returned a promise. Please use model.executeAsync() instead.`);s[e.name]=t,this.checkTensorForDisposal(e.name,e,s,i,r,o,u)}}return null==this.parent&&i.dispose(r),e.map((t=>xa(t,s,i)))}))}getFrozenTensorIds(t){const e=[].concat.apply([],Object.keys(t).map((e=>t[e])).map((t=>t.map((t=>t.id)))));return new Set(e)}checkTensorForDisposal(t,e,i,s,o,r,u){"control"!==e.category&&-1===r.indexOf(t)&&(i[t].forEach((t=>{null!=t&&(u[t.id]=(u[t.id]||0)+e.children.length)})),e.inputs.forEach((t=>{if("control"!==t.category){const r=da(t.name,i,s);null!=r&&r.forEach((t=>{if(t&&!t.kept&&!o.has(t.id)){const i=u[t.id];if(1===i){if(this.keepTensorForDebug){const[i,o]=Ka(e.name,s);this.intermediateTensors[i]||(this.intermediateTensors[i]=[]),this.intermediateTensors[i][o]=t}else t.dispose();delete u[t.id]}else null!=i&&u[t.id]--}}))}})))}async executeAsync(t,e){return this._executeAsync(t,e)}disposeIntermediateTensors(){this.intermediateTensors&&(Object.keys(this.intermediateTensors).forEach((t=>this.intermediateTensors[t].forEach((t=>t.dispose())))),this.disposeTensorsMap())}disposeTensorsMap(){this.tensorsMap&&Object.keys(this.tensorsMap).forEach((t=>{this.tensorsMap[t].forEach((t=>{!t||t.kept||t.isDisposed||this.keepIds.has(t.id)||t.dispose()}))}))}getIntermediateTensors(){return this.tensorsMap}resetIntermediateTensors(){for(const t in this.intermediateTensors)this.intermediateTensors[t].forEach((t=>t.dispose())),delete this.intermediateTensors[t]}async _executeAsync(t,e,i=!1,s={},o={}){i||(t=this.mapInputs(t),this.checkInputs(t),this.checkInputShapeAndType(t),e=this.mapOutputs(e),this.checkOutputs(e));try{this.keepTensorForDebug=we().getBool("KEEP_INTERMEDIATE_TENSORS")}catch(t){console.warn(t.message)}this.resetIntermediateTensors();const r=new Gn(this.weightMap,s,o,this.functionExecutorMap);this.tensorsMap=await this.executeWithControlFlow(t,r,e,i);const u=e.map((t=>xa(t,this.tensorsMap,r))),a=u.map((t=>t.id)),n=Object.keys(t).map((e=>t[e].id));return this.keepIds=new Set([...a,...n,...this.weightIds]),this.keepTensorForDebug||this.disposeTensorsMap(),null==this.parent&&r.dispose(this.keepIds),u}async executeFunctionAsync(t,e,i){const s=t.reduce(((t,e,i)=>(t[this.inputs[i].name]=e,t)),{});return this._executeAsync(s,this.outputNodes,!0,e,i)}async executeWithControlFlow(t,e,i,s){const o=Object.keys(t),r=o.map((t=>this.graph.nodes[Ya(t)[0]])),u=i.map((t=>Ya(t)[0]));let a=u.map((t=>this.graph.nodes[t]));0===a.length&&(a=this._outputs);const{usedNodes:n,missingInputs:L,dynamicNode:M,syncInputs:C}=Nn(t,a,this.weightMap,this._initNodes),w=[...r,...this.graph.weights,...this._initNodes||[]].map((t=>({node:t,contexts:e.currentContext}))),y=Object.assign({},this.weightMap);Object.keys(t).forEach((e=>{const[i,s]=Ya(e),o=[];o[s]=t[e],y[i]=o}));const v={},D=this.getFrozenTensorIds(y),l={};for(;w.length>0;){const t=this.processStack(r,w,e,y,l,D,u,v,n);await Promise.all(t)}null!=M||s||console.warn("This model execution did not contain any nodes with control flow or dynamic output shapes. You can use model.execute() instead.");const g=a.filter((t=>!Fn(t)&&!xa(t.name,y,e))).map((t=>t.name));if(g.length>0){let t="";throw null!=M&&(t=`Alternatively, to avoid the dynamic ops, use model.execute() and specify the inputs [${C}]`),new Error(`Cannot compute the outputs [${g}] from the provided inputs [${o}]. Consider providing the following inputs: [${L}]. ${t}`)}return y}processStack(t,e,i,s,o,r,u,a,n){const L=[];for(;e.length>0;){const t=e.pop();i.currentContext=t.contexts;let M="";if("Enter"===t.node.op&&za("isConstant",t.node,s,i)&&([M]=Ka(t.node.name,i)),null==s[t.node.name]){const C=kn(t.node,s,i,this._resourceManager);M||([M]=Ka(t.node.name,i));const w=i.currentContext;ae(C)?L.push(C.then((L=>(s[M]=L,i.currentContext=w,this.checkTensorForDisposal(M,t.node,s,i,r,u,a),this.processChildNodes(t.node,e,i,s,o,n),L)))):(s[M]=C,this.checkTensorForDisposal(M,t.node,s,i,r,u,a),this.processChildNodes(t.node,e,i,s,o,n))}else this.processChildNodes(t.node,e,i,s,o,n)}return L}processChildNodes(t,e,i,s,o,r){t.children.forEach((t=>{const[u]=Ka(t.name,i);!o[u]&&r.has(t.name)&&("Merge"===t.op?t.inputNames.some((t=>!!xa(t,s,i)))&&(o[u]=!0,e.push({contexts:i.currentContext,node:t})):t.inputNames.every((t=>!!xa(t,s,i)))&&(o[u]=!0,e.push({contexts:i.currentContext,node:t})))}))}dispose(){Object.keys(this.weightMap).forEach((t=>this.weightMap[t].forEach((t=>t.dispose()))))}checkInputShapeAndType(t){Object.keys(t).forEach((e=>{const i=t[e],[s]=Ya(e),o=this.graph.nodes[s];if(o.attrParams.shape&&o.attrParams.shape.value){const t=o.attrParams.shape.value;Kt(t.length===i.shape.length&&i.shape.every(((e,i)=>-1===t[i]||t[i]===e)),(()=>`The shape of dict['${o.name}'] provided in model.execute(dict) must be [${t}], but was [${i.shape}]`))}o.attrParams.dtype&&o.attrParams.dtype.value&&Kt(i.dtype===o.attrParams.dtype.value,(()=>`The dtype of dict['${o.name}'] provided in model.execute(dict) must be ${o.attrParams.dtype.value}, but was ${i.dtype}`))}))}mapInputs(t){const e={};for(const i in t)if(null!=this._signature&&null!=this._signature.inputs&&null!=this._signature.inputs[i]){e[this._signature.inputs[i].name]=t[i]}else e[i]=t[i];return e}checkInputs(t){const e=Object.keys(t).filter((t=>{const[e]=Ya(t);return null==this.graph.nodes[e]}));if(e.length>0)throw new Error(`The dict provided in model.execute(dict) has keys: [${e}] that are not part of graph`)}mapOutputs(t){return t.map((t=>{if(null!=this._signature&&null!=this._signature.outputs&&null!=this._signature.outputs[t]){return this._signature.outputs[t].name}return t}),{})}checkOutputs(t){t.forEach((t=>{const[e]=Ya(t);if(!this.graph.nodes[e])throw new Error(`The output '${t}' is not found in the graph`)}))}}class Zn{constructor(t={},e={}){this.hashTableNameToHandle=t,this.hashTableMap=e}addHashTable(t,e){this.hashTableNameToHandle[t]=e.handle,this.hashTableMap[e.id]=e}getHashTableHandleByName(t){return this.hashTableNameToHandle[t]}getHashTableById(t){return this.hashTableMap[t]}dispose(){for(const t in this.hashTableMap)this.hashTableMap[t].clearAndClose(),delete this.hashTableMap[t];for(const t in this.hashTableNameToHandle)this.hashTableNameToHandle[t].dispose(),delete this.hashTableNameToHandle[t]}}class Xn{constructor(t,e={},i=O){this.modelUrl=t,this.loadOptions=e,this.version="n/a",this.io=i,null==e&&(this.loadOptions={}),this.resourceManager=new Zn}get modelVersion(){return this.version}get inputNodes(){return this.executor.inputNodes}get outputNodes(){return this.executor.outputNodes}get inputs(){return this.executor.inputs}get outputs(){return this.executor.outputs}get weights(){return this.executor.weightMap}get metadata(){return this.artifacts.userDefinedMetadata}get modelSignature(){return this.signature}get modelStructuredOutputKeys(){return this.structuredOutputKeys}findIOHandler(){const t=this.modelUrl;if(null!=t.load)this.handler=t;else if(null!=this.loadOptions.requestInit)this.handler=this.io.browserHTTPRequest(t,this.loadOptions);else{const e=this.io.getLoadHandlers(t,this.loadOptions);if(0===e.length)e.push(this.io.browserHTTPRequest(t,this.loadOptions));else if(e.length>1)throw new Error(`Found more than one (${e.length}) load handlers for URL '${[t]}'`);this.handler=e[0]}}load(){if(this.findIOHandler(),null==this.handler.load)throw new Error("Cannot proceed with model loading because the IOHandler provided does not have the `load` method implemented.");const t=this.handler.load();return ae(t)?t.then((t=>this.loadSync(t))):this.loadSync(t)}loadSync(t){this.artifacts=t;const e=this.artifacts.modelTopology;let i=this.artifacts.signature;if(null!=this.artifacts.userDefinedMetadata){const t=this.artifacts.userDefinedMetadata;null!=t.signature&&(i=t.signature),null!=t.structuredOutputKeys&&(this.structuredOutputKeys=t.structuredOutputKeys)}this.signature=i,this.version=`${e.versions.producer}.${e.versions.minConsumer}`;const s=this.io.decodeWeights(this.artifacts.weightData,this.artifacts.weightSpecs);if(this.executor=new Vn($a.Instance.transformGraph(e,this.signature)),this.executor.weightMap=this.convertTensorMapToTensorsMap(s),this.executor.resourceManager=this.resourceManager,null!=t.modelInitializer&&null!=t.modelInitializer.node){const e=$a.Instance.transformGraph(t.modelInitializer);this.initializer=new Vn(e),this.initializer.weightMap=this.executor.weightMap,this.initializer.resourceManager=this.resourceManager,this.initializer.executeAsync({},[])}return!0}async save(t,e){if("string"==typeof t){const e=this.io.getSaveHandlers(t);if(0===e.length)throw new Error(`Cannot find any save handlers for URL '${t}'`);if(e.length>1)throw new Error(`Found more than one (${e.length}) save handlers for URL '${t}'`);t=e[0]}if(null==t.save)throw new Error("GraphModel.save() cannot proceed because the IOHandler provided does not have the `save` attribute defined.");return t.save(this.artifacts)}predict(t,e){const i=this.execute(t,this.outputNodes);if(this.structuredOutputKeys){const t={};return(i instanceof Wi?[i]:i).forEach(((e,i)=>t[this.structuredOutputKeys[i]]=e)),t}return i}normalizeInputs(t){if(!(t instanceof Wi||Array.isArray(t)))return t;if((t=Array.isArray(t)?t:[t]).length!==this.inputNodes.length)throw new Error(`Input tensor count mismatch,the graph model has ${this.inputNodes.length} placeholders, while there are ${t.length} input tensors.`);return this.inputNodes.reduce(((e,i,s)=>(e[i]=t[s],e)),{})}normalizeOutputs(t){return t=t||this.outputNodes,Array.isArray(t)?t:[t]}execute(t,e){t=this.normalizeInputs(t),e=this.normalizeOutputs(e);const i=this.executor.execute(t,e);return i.length>1?i:i[0]}async executeAsync(t,e){t=this.normalizeInputs(t),e=this.normalizeOutputs(e);const i=await this.executor.executeAsync(t,e);return i.length>1?i:i[0]}getIntermediateTensors(){return this.executor.getIntermediateTensors()}disposeIntermediateTensors(){this.executor.disposeIntermediateTensors()}convertTensorMapToTensorsMap(t){return Object.keys(t).reduce(((e,i)=>(e[i]=[t[i]],e)),{})}dispose(){this.executor.dispose(),this.initializer&&this.initializer.dispose(),this.resourceManager.dispose()}}async function _n(t,e={},i=O){if(null==t)throw new Error("modelUrl in loadGraphModel() cannot be null. Please provide a url or an IOHandler that loads the model");null==e&&(e={}),e.fromTFHub&&"string"==typeof t&&(t=getTFHubUrl(t));const s=new Xn(t,e,i);return await s.load(),s}Fi().prototype.pad=function(t,e){return this.throwIfDisposed(),Au(this,t,e)},Fi().prototype.where=function(t,e){return this.throwIfDisposed(),mr(t,this,e)},Fi().prototype.mul=function(t){return this.throwIfDisposed(),tr(this,t)},Fi().prototype.dot=function(t){return this.throwIfDisposed(),xr(this,t)},Fi().prototype.add=function(t){return this.throwIfDisposed(),Zo(this,t)};const $n={},tL={alpha:!1,antialias:!1,premultipliedAlpha:!1,preserveDrawingBuffer:!1,depth:!1,stencil:!1,failIfMajorPerformanceCaveat:!0};function eL(t,e){$n[t]=e}function iL(t,e){if(!(t in $n)||null!=e){const i=oL(t,e);if(null===i)return console.log("Could not get context for WebGL version",t),null;$n[t]=i}const i=$n[t];return null==i||i.isContextLost()?(delete $n[t],iL(t)):(i.disable(i.DEPTH_TEST),i.disable(i.STENCIL_TEST),i.disable(i.BLEND),i.disable(i.DITHER),i.disable(i.POLYGON_OFFSET_FILL),i.disable(i.SAMPLE_COVERAGE),i.enable(i.SCISSOR_TEST),i.enable(i.CULL_FACE),i.cullFace(i.BACK),$n[t])}function sL(t){if("undefined"!=typeof OffscreenCanvas&&2===t)return new OffscreenCanvas(300,150);if("undefined"!=typeof document)return document.createElement("canvas");throw new Error("Cannot create a canvas in this context")}function oL(t,e){if(1!==t&&2!==t)throw new Error("Cannot get WebGL rendering context, WebGL is disabled.");const i=null==e?sL(t):e;return i.addEventListener("webglcontextlost",(e=>{e.preventDefault(),delete $n[t]}),!1),1===t?i.getContext("webgl",tL)||i.getContext("experimental-webgl",tL):i.getContext("webgl2",tL)}var yt,vt,Dt;function rL(t,e){return[e,t]}function uL(t){const e=bt(t);return St(Math.ceil(e/4))}function aL(t,e){return[Math.max(1,Math.ceil(e/2)),Math.max(1,Math.ceil(t/2))]}function nL(t,e){const i=t;let s,o,r,u,a,n,L,M,C,w;return 2===we().getNumber("WEBGL_VERSION")?(s=i.R32F,o=i.R16F,r=i.RGBA16F,u=i.RGBA32F,a=i.RED,L=4,M=1,C=i.HALF_FLOAT,w=i.FLOAT,n=i.RGBA8):(s=t.RGBA,o=t.RGBA,r=t.RGBA,u=i.RGBA,a=t.RGBA,L=4,M=4,C=null!=e?e.HALF_FLOAT_OES:null,w=t.FLOAT,n=t.RGBA),{internalFormatFloat:s,internalFormatHalfFloat:o,internalFormatPackedHalfFloat:r,internalFormatPackedFloat:u,textureFormatFloat:a,downloadTextureFormat:n,downloadUnpackNumChannels:L,defaultNumChannels:M,textureTypeHalfFloat:C,textureTypeFloat:w}}function LL(t,e){const i=e();return we().getBool("DEBUG")&&checkWebGLError(t),i}function ML(t,e){const i=hL(t,(()=>t.createShader(t.VERTEX_SHADER)),"Unable to create vertex WebGLShader.");if(LL(t,(()=>t.shaderSource(i,e))),LL(t,(()=>t.compileShader(i))),!1===t.getShaderParameter(i,t.COMPILE_STATUS))throw console.log(t.getShaderInfoLog(i)),new Error("Failed to compile vertex shader.");return i}function CL(t,e){const i=hL(t,(()=>t.createShader(t.FRAGMENT_SHADER)),"Unable to create fragment WebGLShader.");if(LL(t,(()=>t.shaderSource(i,e))),LL(t,(()=>t.compileShader(i))),we().get("ENGINE_COMPILE_ONLY"))return i;if(!1===t.getShaderParameter(i,t.COMPILE_STATUS))throw logShaderSourceAndInfoLog(e,t.getShaderInfoLog(i)),new Error("Failed to compile fragment shader.");return i}function wL(t){return hL(t,(()=>t.createProgram()),"Unable to create WebGLProgram.")}function yL(t,e){if(LL(t,(()=>t.linkProgram(e))),!we().get("ENGINE_COMPILE_ONLY")&&!1===t.getProgramParameter(e,t.LINK_STATUS))throw console.log(t.getProgramInfoLog(e)),new Error("Failed to link vertex and fragment shaders.")}function vL(t,e){const i=hL(t,(()=>t.createBuffer()),"Unable to create WebGLBuffer");return LL(t,(()=>t.bindBuffer(t.ARRAY_BUFFER,i))),LL(t,(()=>t.bufferData(t.ARRAY_BUFFER,e,t.STATIC_DRAW))),i}function DL(t,e){const i=hL(t,(()=>t.createBuffer()),"Unable to create WebGLBuffer");return LL(t,(()=>t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,i))),LL(t,(()=>t.bufferData(t.ELEMENT_ARRAY_BUFFER,e,t.STATIC_DRAW))),i}function lL(t){return hL(t,(()=>t.createTexture()),"Unable to create WebGLTexture.")}function gL(t,e){const i=we().getNumber("WEBGL_MAX_TEXTURE_SIZE");if(t<=0||e<=0){throw new Error("Requested texture size "+`[${t}x${e}]`+" is invalid.")}if(t>i||e>i){throw new Error("Requested texture size "+`[${t}x${e}]`+" greater than WebGL maximum on this browser / GPU "+`[${i}x${i}]`+".")}}function pL(t){return hL(t,(()=>t.createFramebuffer()),"Unable to create WebGLFramebuffer.")}function jL(t,e,i,s,o,r,u){const a=t.getAttribLocation(e,i);return-1!==a&&(LL(t,(()=>t.bindBuffer(t.ARRAY_BUFFER,s))),LL(t,(()=>t.vertexAttribPointer(a,o,t.FLOAT,!1,r,u))),LL(t,(()=>t.enableVertexAttribArray(a))),!0)}function AL(t,e,i){OL(t,i),LL(t,(()=>t.activeTexture(t.TEXTURE0+i))),LL(t,(()=>t.bindTexture(t.TEXTURE_2D,e)))}function cL(t,e,i){return t.getUniformLocation(e,i)}function IL(t,e,i,s){LL(t,(()=>AL(t,e,s))),LL(t,(()=>t.uniform1i(i,s)))}function mL(t,e,i){LL(t,(()=>t.bindFramebuffer(t.FRAMEBUFFER,i))),LL(t,(()=>t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,e,0)))}function hL(t,e,i){const s=LL(t,(()=>e()));if(null==s)throw new Error(i);return s}function OL(t,e){const i=t.MAX_COMBINED_TEXTURE_IMAGE_UNITS-1,s=e+t.TEXTURE0;if(s<t.TEXTURE0||s>i){throw new Error(`textureUnit must be in ${`[gl.TEXTURE0, gl.TEXTURE${i}]`}.`)}}function zL(t,e=2){return bt(t.slice(0,t.length-e))}function xL(t){if(0===t.length)throw Error("Cannot get rows and columns of an empty shape array.");return[t.length>1?t[t.length-2]:1,t[t.length-1]]}function dL(t){let e=[1,1,1];return 0===t.length||1===t.length&&1===t[0]||(e=[zL(t),...xL(t)]),e}function KL(t,e=!1){let i=we().getNumber("WEBGL_MAX_TEXTURE_SIZE");if(e&&(i*=2,t=t.map(((e,i)=>i>=t.length-2?xt(t[i]):t[i])),1===t.length&&(t=[2,t[0]])),2!==t.length){const e=Nt(t);t=e.newShape}let s=bt(t);if(t.length<=1&&s<=i)return[1,s];if(2===t.length&&t[0]<=i&&t[1]<=i)return t;if(3===t.length&&t[0]*t[1]<=i&&t[2]<=i)return[t[0]*t[1],t[2]];if(3===t.length&&t[0]<=i&&t[1]*t[2]<=i)return[t[0],t[1]*t[2]];if(4===t.length&&t[0]*t[1]*t[2]<=i&&t[3]<=i)return[t[0]*t[1]*t[2],t[3]];if(4===t.length&&t[0]<=i&&t[1]*t[2]*t[3]<=i)return[t[0],t[1]*t[2]*t[3]];if(e){const e=zL(t);let i=2,o=2;return t.length&&([i,o]=xL(t)),s=e*(i/2)*(o/2),St(s).map((t=>2*t))}return St(s)}function PL(t){return t%2==0}function YL(t,e){if(Et(t=t.slice(-2),e=e.slice(-2)))return!0;if(!t.length||!e.length)return!0;if(0===t[0]||0===t[1]||0===e[0]||0===e[1])return!0;if(t.length!==e.length){const i=t.slice(-1)[0],s=e.slice(-1)[0];if(i===s)return!0;if(PL(i)&&PL(s)&&(1===t[0]||1===e[0]))return!0}return t[1]===e[1]&&PL(t[0])&&PL(e[0])}let QL,bL;function EL(t){if(null==QL){const e=iL(t);QL=e.getParameter(e.MAX_TEXTURE_SIZE)}return QL}function TL(t){if(null==bL){const e=iL(t);bL=e.getParameter(e.MAX_TEXTURE_IMAGE_UNITS)}return Math.min(16,bL)}function SL(t,e){return null!=t.getExtension(e)}function fL(t){try{if(null!=iL(t))return!0}catch(t){return console.log("Error when getting WebGL context: ",t),!1}return!1}function qL(t){if(0===t)return!1;const e=iL(t);if(1===t){if(!SL(e,"OES_texture_float"))return!1}else if(!SL(e,"EXT_color_buffer_float"))return!1;return kL(e)}function kL(t){const e=nL(t),i=t.createTexture();t.bindTexture(t.TEXTURE_2D,i);t.texImage2D(t.TEXTURE_2D,0,e.internalFormatFloat,1,1,0,e.textureFormatFloat,e.textureTypeFloat,null);const s=t.createFramebuffer();t.bindFramebuffer(t.FRAMEBUFFER,s),t.framebufferTexture2D(t.FRAMEBUFFER,t.COLOR_ATTACHMENT0,t.TEXTURE_2D,i,0);const o=t.checkFramebufferStatus(t.FRAMEBUFFER)===t.FRAMEBUFFER_COMPLETE;return t.bindTexture(t.TEXTURE_2D,null),t.bindFramebuffer(t.FRAMEBUFFER,null),t.deleteTexture(i),t.deleteFramebuffer(s),o}function GL(t){if(2!==t)return!1;return null!=iL(t).fenceSync}!function(t){t[t.DENSE=0]="DENSE",t[t.SHARED_BATCH=1]="SHARED_BATCH"}(yt||(yt={})),function(t){t[t.RENDER=0]="RENDER",t[t.UPLOAD=1]="UPLOAD",t[t.PIXELS=2]="PIXELS",t[t.DOWNLOAD=3]="DOWNLOAD"}(vt||(vt={})),function(t){t[t.UNPACKED_FLOAT16=0]="UNPACKED_FLOAT16",t[t.UNPACKED_FLOAT32=1]="UNPACKED_FLOAT32",t[t.PACKED_4X1_UNSIGNED_BYTE=2]="PACKED_4X1_UNSIGNED_BYTE",t[t.PACKED_2X2_FLOAT32=3]="PACKED_2X2_FLOAT32",t[t.PACKED_2X2_FLOAT16=4]="PACKED_2X2_FLOAT16"}(Dt||(Dt={}));const NL=we();function BL(){let t,e,i,s,o,r,u,a,n,L;return 2===we().getNumber("WEBGL_VERSION")?(t="#version 300 es",e="in",i="out",s="in",o="texture",r="outputColor",u="out vec4 outputColor;",a="\n      bool isnan_custom(float val) {\n        uint floatToUint = floatBitsToUint(val);\n        return (floatToUint & 0x7fffffffu) > 0x7f800000u;\n      }\n\n      bvec4 isnan_custom(vec4 val) {\n        return bvec4(isnan_custom(val.x),\n          isnan_custom(val.y), isnan_custom(val.z), isnan_custom(val.w));\n      }\n\n      #define isnan(value) isnan_custom(value)\n    ",n="",L="\n      #define round(value) newRound(value)\n      int newRound(float value) {\n        return int(floor(value + 0.5));\n      }\n\n      ivec4 newRound(vec4 value) {\n        return ivec4(floor(value + vec4(0.5)));\n      }\n    "):(t="",e="attribute",i="varying",s="varying",o="texture2D",r="gl_FragColor",u="",a="\n      #define isnan(value) isnan_custom(value)\n      bool isnan_custom(float val) {\n        return (val > 0. || val < 1. || val == 0.) ? false : true;\n      }\n      bvec4 isnan_custom(vec4 val) {\n        return bvec4(isnan(val.x), isnan(val.y), isnan(val.z), isnan(val.w));\n      }\n    ",n="\n      uniform float INFINITY;\n\n      bool isinf(float val) {\n        return abs(val) == INFINITY;\n      }\n      bvec4 isinf(vec4 val) {\n        return equal(abs(val), vec4(INFINITY));\n      }\n    ",L="\n      int round(float value) {\n        return int(floor(value + 0.5));\n      }\n\n      ivec4 round(vec4 value) {\n        return ivec4(floor(value + vec4(0.5)));\n      }\n    "),{version:t,attribute:e,varyingVs:i,varyingFs:s,texture2D:o,output:r,defineOutput:u,defineSpecialNaN:a,defineSpecialInf:n,defineRound:L}}function UL(t,e,i="index"){const s=$t(e);return s.map(((e,o)=>`${`int ${t[o]} = ${i} / ${e}`}; ${o===s.length-1?`int ${t[o+1]} = ${i} - ${t[o]} * ${e}`:`index -= ${t[o]} * ${e}`};`)).join("")}function JL(t,e,i="index"){const s=$t(e);return s.map(((e,o)=>`${`int ${t[o]} = ${i} / outShapeStrides[${o}]`}; ${o===s.length-1?`int ${t[o+1]} = ${i} - ${t[o]} * outShapeStrides[${o}]`:`index -= ${t[o]} * outShapeStrides[${o}]`};`)).join("")}function WL(t,e){const i=t.length,s=t.map((t=>`${e}[${t}]`)),o=new Array(i-1);o[i-2]=s[i-1];for(let t=i-3;t>=0;--t)o[t]=`(${o[t+1]} * ${s[t+1]})`;return o}function FL(t,e,i="index"){const s=t.map(((t,e)=>e)),o=WL(s,e);return o.map(((e,s)=>`${`int ${t[s]} = ${i} / ${o[s]}`}; ${s===o.length-1?`int ${t[s+1]} = ${i} - ${t[s]} * ${o[s]}`:`index -= ${t[s]} * ${o[s]}`};`)).join("")}NL.registerFlag("HAS_WEBGL",(()=>NL.getNumber("WEBGL_VERSION")>0)),NL.registerFlag("WEBGL_VERSION",(()=>fL(2)?2:fL(1)?1:0)),NL.registerFlag("WEBGL_CHECK_NUMERICAL_PROBLEMS",(()=>!1)),NL.registerFlag("WEBGL_BUFFER_SUPPORTED",(()=>2===NL.get("WEBGL_VERSION"))),NL.registerFlag("WEBGL_CPU_FORWARD",(()=>!0)),NL.registerFlag("WEBGL_FORCE_F16_TEXTURES",(()=>!1)),NL.registerFlag("WEBGL_PACK",(()=>NL.getBool("HAS_WEBGL"))),NL.registerFlag("WEBGL_PACK_NORMALIZATION",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_CLIP",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_DEPTHWISECONV",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_BINARY_OPERATIONS",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_UNARY_OPERATIONS",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_ARRAY_OPERATIONS",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_IMAGE_OPERATIONS",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_PACK_REDUCE",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_LAZILY_UNPACK",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_CONV_IM2COL",(()=>NL.getBool("WEBGL_PACK"))),NL.registerFlag("WEBGL_MAX_TEXTURE_SIZE",(()=>EL(NL.getNumber("WEBGL_VERSION")))),NL.registerFlag("WEBGL_MAX_TEXTURES_IN_SHADER",(()=>TL(NL.getNumber("WEBGL_VERSION")))),NL.registerFlag("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION",(()=>{const t=NL.getNumber("WEBGL_VERSION");return 0===t?0:getWebGLDisjointQueryTimerVersion(t)})),NL.registerFlag("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE",(()=>NL.getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")>0&&!ns())),NL.registerFlag("WEBGL_RENDER_FLOAT32_CAPABLE",(()=>qL(NL.getNumber("WEBGL_VERSION")))),NL.registerFlag("WEBGL_RENDER_FLOAT32_ENABLED",(()=>!NL.getBool("WEBGL_FORCE_F16_TEXTURES")&&NL.getBool("WEBGL_RENDER_FLOAT32_CAPABLE"))),NL.registerFlag("WEBGL_DOWNLOAD_FLOAT_ENABLED",(()=>isDownloadFloatTextureEnabled(NL.getNumber("WEBGL_VERSION")))),NL.registerFlag("WEBGL_FENCE_API_ENABLED",(()=>GL(NL.getNumber("WEBGL_VERSION")))),NL.registerFlag("WEBGL_SIZE_UPLOAD_UNIFORM",(()=>NL.getBool("WEBGL_RENDER_FLOAT32_ENABLED")?4:0)),NL.registerFlag("WEBGL_DELETE_TEXTURE_THRESHOLD",(()=>-1),(t=>{if(t<0&&-1!==t)throw new Error(`WEBGL_DELETE_TEXTURE_THRESHOLD must be -1 (indicating never delete) or at least 0, but got ${t}.`)})),NL.registerFlag("WEBGL_FLUSH_THRESHOLD",(()=>ns()?1:-1),(t=>{if(t<0&&-1!==t)throw new Error(`WEBGL_FLUSH_THRESHOLD must be -1 (indicating never manual flush) or at least 0, but got ${t}.`)})),NL.registerFlag("CPU_HANDOFF_SIZE_THRESHOLD",(()=>128)),NL.registerFlag("WEBGL_USE_SHAPES_UNIFORMS",(()=>!1)),NL.registerFlag("TOPK_LAST_DIM_CPU_HANDOFF_SIZE_THRESHOLD",(()=>1e5)),NL.registerFlag("TOPK_K_CPU_HANDOFF_THRESHOLD",(()=>128));const RL="\n  const float FLOAT_MAX = 1.70141184e38;\n  const float FLOAT_MIN = 1.17549435e-38;\n\n  lowp vec4 encode_float(highp float v) {\n    if (isnan(v)) {\n      return vec4(255, 255, 255, 255);\n    }\n\n    highp float av = abs(v);\n\n    if(av < FLOAT_MIN) {\n      return vec4(0.0, 0.0, 0.0, 0.0);\n    } else if(v > FLOAT_MAX) {\n      return vec4(0.0, 0.0, 128.0, 127.0) / 255.0;\n    } else if(v < -FLOAT_MAX) {\n      return vec4(0.0, 0.0,  128.0, 255.0) / 255.0;\n    }\n\n    highp vec4 c = vec4(0,0,0,0);\n\n    highp float e = floor(log2(av));\n    highp float m = exp2(fract(log2(av))) - 1.0;\n\n    c[2] = floor(128.0 * m);\n    m -= c[2] / 128.0;\n    c[1] = floor(32768.0 * m);\n    m -= c[1] / 32768.0;\n    c[0] = floor(8388608.0 * m);\n\n    highp float ebias = e + 127.0;\n    c[3] = floor(ebias / 2.0);\n    ebias -= c[3] * 2.0;\n    c[2] += floor(ebias) * 128.0;\n\n    c[3] += 128.0 * step(0.0, -v);\n\n    return c / 255.0;\n  }\n",{getBroadcastDims:HL}=J;function VL(t,e,i){const s=[];if(t.forEach((t=>{const e=bt(t.shapeInfo.logicalShape);if(t.shapeInfo.isUniform?s.push(`uniform float ${t.name}${e>1?`[${e}]`:""};`):(s.push(`uniform sampler2D ${t.name};`),s.push(`uniform int offset${t.name};`)),i.enableShapeUniforms){const{uniformShape:e}=hM(i.packedInputs,t.shapeInfo.logicalShape,t.shapeInfo.texShape);switch(e.length){case 1:s.push(`uniform int ${t.name}Shape;`);break;case 2:s.push(`uniform ivec2 ${t.name}Shape;`);break;case 3:s.push(`uniform ivec3 ${t.name}Shape;`);break;case 4:s.push(`uniform ivec4 ${t.name}Shape;`)}s.push(`uniform ivec2 ${t.name}TexShape;`)}})),i.enableShapeUniforms){switch(e.logicalShape.length){case 1:s.push("uniform int outShape;");break;case 2:s.push("uniform ivec2 outShape;"),s.push("uniform int outShapeStrides;");break;case 3:s.push("uniform ivec3 outShape;"),s.push("uniform ivec2 outShapeStrides;");break;case 4:s.push("uniform ivec4 outShape;"),s.push("uniform ivec3 outShapeStrides;")}s.push("uniform ivec2 outTexShape;")}i.customUniforms&&i.customUniforms.forEach((t=>{s.push(`uniform ${t.type} ${t.name}${t.arrayIndex?`[${t.arrayIndex}]`:""};`)}));const o=s.join("\n"),r=t.map((t=>_L(t,e,i.packedInputs,i.enableShapeUniforms))).join("\n"),u=e.texShape,a=BL(),n=eM(a);let L,M,C=oM(a);e.isPacked?(L=$L(e.logicalShape,u,i.enableShapeUniforms),M=sM(a)):(L=tM(e.logicalShape,u,i.enableShapeUniforms),M=iM(a)),i.packedInputs&&(C+=nM);return[C,n,M,o,L,r,i.userCode].join("\n")}function ZL(t,e=!1){const i=t.shapeInfo.logicalShape;switch(i.length){case 0:return getSamplerScalar(t,e);case 1:return DM(t,e);case 2:return gM(t,e);case 3:return jM(t,e);case 4:return getSampler4D(t,e);case 5:return getSampler5D(t);case 6:return getSampler6D(t);default:throw new Error(`${i.length}-D input sampling is not yet supported`)}}function XL(t,e){switch(t.shapeInfo.logicalShape.length){case 0:return getPackedSamplerScalar(t);case 1:return vM(t,e);case 2:return lM(t,e);case 3:return pM(t,e);default:return AM(t,e)}}function _L(t,e,i=!1,s){let o="";o+=i?XL(t,s):ZL(t,s);const r=t.shapeInfo.logicalShape,u=e.logicalShape;return r.length<=u.length&&(o+=i?cM(t,e):IM(t,e)),o}function $L(t,e,i){switch(t.length){case 0:return getOutputScalarCoords();case 1:return getOutputPacked1DCoords(t,e,i);case 2:return CM(t,e,i);case 3:return LM(t,e,i);default:return MM(t,e,i)}}function tM(t,e,i){switch(t.length){case 0:return getOutputScalarCoords();case 1:return getOutput1DCoords(t,e,i);case 2:return wM(t,e,i);case 3:return getOutput3DCoords(t,e,i);case 4:return getOutput4DCoords(t,e,i);case 5:return getOutput5DCoords(t,e);case 6:return getOutput6DCoords(t,e);default:throw new Error(`${t.length}-D output sampling is not yet supported`)}}function eM(t){return`\n    float sampleTexture(sampler2D textureSampler, vec2 uv) {\n      return ${t.texture2D}(textureSampler, uv).r;\n    }\n  `}function iM(t){return`\n    void setOutput(float val) {\n      ${t.output} = vec4(val, 0, 0, 0);\n    }\n  `}function sM(t){return`\n    void setOutput(vec4 val) {\n      ${t.output} = val;\n    }\n  `}function oM(t){return`${t.version}\n    precision highp float;\n    precision highp int;\n    precision highp sampler2D;\n    ${t.varyingFs} vec2 resultUV;\n    ${t.defineOutput}\n    const vec2 halfCR = vec2(0.5, 0.5);\n\n    struct ivec5\n    {\n      int x;\n      int y;\n      int z;\n      int w;\n      int u;\n    };\n\n    struct ivec6\n    {\n      int x;\n      int y;\n      int z;\n      int w;\n      int u;\n      int v;\n    };\n\n    uniform float NAN;\n    ${t.defineSpecialNaN}\n    ${t.defineSpecialInf}\n    ${t.defineRound}\n\n    int imod(int x, int y) {\n      return x - y * (x / y);\n    }\n\n    int idiv(int a, int b, float sign) {\n      int res = a / b;\n      int mod = imod(a, b);\n      if (sign < 0. && mod != 0) {\n        res -= 1;\n      }\n      return res;\n    }\n\n    //Based on the work of Dave Hoskins\n    //https://www.shadertoy.com/view/4djSRW\n    #define HASHSCALE1 443.8975\n    float random(float seed){\n      vec2 p = resultUV * seed;\n      vec3 p3  = fract(vec3(p.xyx) * HASHSCALE1);\n      p3 += dot(p3, p3.yzx + 19.19);\n      return fract((p3.x + p3.y) * p3.z);\n    }\n\n    ${rM}\n    ${uM}\n    ${aM}\n  `}const rM="\nvec2 uvFromFlat(int texNumR, int texNumC, int index) {\n  int texR = index / texNumC;\n  int texC = index - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\nvec2 packedUVfrom1D(int texNumR, int texNumC, int index) {\n  int texelIndex = index / 2;\n  int texR = texelIndex / texNumC;\n  int texC = texelIndex - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n",uM="\nvec2 packedUVfrom2D(int texelsInLogicalRow, int texNumR,\n  int texNumC, int row, int col) {\n  int texelIndex = (row / 2) * texelsInLogicalRow + (col / 2);\n  int texR = texelIndex / texNumC;\n  int texC = texelIndex - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n",aM="\nvec2 packedUVfrom3D(int texNumR, int texNumC,\n    int texelsInBatch, int texelsInLogicalRow, int b,\n    int row, int col) {\n  int index = b * texelsInBatch + (row / 2) * texelsInLogicalRow + (col / 2);\n  int texR = index / texNumC;\n  int texC = index - texR * texNumC;\n  return (vec2(texC, texR) + halfCR) / vec2(texNumC, texNumR);\n}\n",nM="\n  float getChannel(vec4 frag, vec2 innerDims) {\n    vec2 modCoord = mod(innerDims, 2.);\n    return modCoord.x == 0. ?\n      (modCoord.y == 0. ? frag.r : frag.g) :\n      (modCoord.y == 0. ? frag.b : frag.a);\n  }\n  float getChannel(vec4 frag, int dim) {\n    float modCoord = mod(float(dim), 2.);\n    return modCoord == 0. ? frag.r : frag.g;\n  }\n";function LM(t,e,i){if(i)return"\n    ivec3 getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      int texelsInLogicalRow = int(ceil(float(outShape[2]) / 2.0));\n      int texelsInBatch = texelsInLogicalRow * int(ceil(float(outShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n      int index = resTexRC.x * packedTexShape[1] + resTexRC.y;\n\n      int b = index / texelsInBatch;\n      index -= b * texelsInBatch;\n\n      int r = 2 * (index / texelsInLogicalRow);\n      int c = imod(index, texelsInLogicalRow) * 2;\n\n      return ivec3(b, r, c);\n    }\n  ";const s=[Math.ceil(e[0]/2),Math.ceil(e[1]/2)],o=Math.ceil(t[2]/2),r=o*Math.ceil(t[1]/2);return`\n    ivec3 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${s[0]}, ${s[1]}));\n      int index = resTexRC.x * ${s[1]} + resTexRC.y;\n\n      int b = index / ${r};\n      index -= b * ${r};\n\n      int r = 2 * (index / ${o});\n      int c = imod(index, ${o}) * 2;\n\n      return ivec3(b, r, c);\n    }\n  `}function MM(t,e,i){if(i)return"\n    ivec4 getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n      int index = resTexRC.x * packedTexShape[1] + resTexRC.y;\n\n      int texelsInLogicalRow = int(ceil(float(outShape[3]) / 2.0));\n      int texelsInBatch = texelsInLogicalRow * int(ceil(float(outShape[2]) / 2.0));\n      int texelsInBatchN = texelsInBatch * outShape[1];\n\n      int b2 = index / texelsInBatchN;\n      index -= b2 * texelsInBatchN;\n\n      int b = index / texelsInBatch;\n      index -= b * texelsInBatch;\n\n      int r = 2 * (index / texelsInLogicalRow);\n      int c = imod(index, texelsInLogicalRow) * 2;\n\n      return ivec4(b2, b, r, c);\n    }\n  ";const s=[Math.ceil(e[0]/2),Math.ceil(e[1]/2)],o=Math.ceil(t[t.length-1]/2),r=o*Math.ceil(t[t.length-2]/2);let u=r,a="",n="b, r, c";for(let e=2;e<t.length-1;e++)u*=t[t.length-e-1],a=`\n      int b${e} = index / ${u};\n      index -= b${e} * ${u};\n    `+a,n=`b${e}, `+n;return`\n    ivec${t.length} getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${s[0]}, ${s[1]}));\n      int index = resTexRC.x * ${s[1]} + resTexRC.y;\n\n      ${a}\n\n      int b = index / ${r};\n      index -= b * ${r};\n\n      int r = 2 * (index / ${o});\n      int c = imod(index, ${o}) * 2;\n\n      return ivec${t.length}(${n});\n    }\n  `}function CM(t,e,i){const s=[Math.ceil(e[0]/2),Math.ceil(e[1]/2)];if(Et(t,e))return i?"\n      ivec2 getOutputCoords() {\n        ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n        return 2 * ivec2(resultUV.yx * vec2(packedTexShape[0], packedTexShape[1]));\n      }\n    ":`\n      ivec2 getOutputCoords() {\n        return 2 * ivec2(resultUV.yx * vec2(${s[0]}, ${s[1]}));\n      }\n    `;const o=Math.ceil(t[1]/2);return i?"\n    ivec2 getOutputCoords() {\n      ivec2 packedTexShape = ivec2(ceil(float(outTexShape[0]) / 2.0), ceil(float(outTexShape[1]) / 2.0));\n      int texelsInLogicalRow = int(ceil(float(outShape[1]) / 2.0));\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(packedTexShape[0], packedTexShape[1]));\n\n      int index = resTexRC.x * packedTexShape[1] + resTexRC.y;\n      int r = 2 * (index / texelsInLogicalRow);\n      int c = imod(index, texelsInLogicalRow) * 2;\n\n      return ivec2(r, c);\n    }\n  ":`\n    ivec2 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${s[0]}, ${s[1]}));\n\n      int index = resTexRC.x * ${s[1]} + resTexRC.y;\n      int r = 2 * (index / ${o});\n      int c = imod(index, ${o}) * 2;\n\n      return ivec2(r, c);\n    }\n  `}function wM(t,e,i){return Et(t,e)?i?"\n      ivec2 getOutputCoords() {\n        return ivec2(resultUV.yx * vec2(outTexShape[0], outTexShape[1]));\n      }\n    ":`\n      ivec2 getOutputCoords() {\n        return ivec2(resultUV.yx * vec2(${e[0]}, ${e[1]}));\n      }\n    `:1===t[1]?i?"\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(outTexShape[0], outTexShape[1]));\n        int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n        return ivec2(index, 0);\n      }\n    ":`\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(${e[0]}, ${e[1]}));\n        int index = resTexRC.x * ${e[1]} + resTexRC.y;\n        return ivec2(index, 0);\n      }\n    `:1===t[0]?i?"\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(outTexShape[0], outTexShape[1]));\n        int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n        return ivec2(0, index);\n      }\n    ":`\n      ivec2 getOutputCoords() {\n        ivec2 resTexRC = ivec2(resultUV.yx *\n                               vec2(${e[0]}, ${e[1]}));\n        int index = resTexRC.x * ${e[1]} + resTexRC.y;\n        return ivec2(0, index);\n      }\n    `:i?"\n    ivec2 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(outTexShape[0], outTexShape[1]));\n      int index = resTexRC.x * outTexShape[1] + resTexRC.y;\n      int r = index / outShape[1];\n      int c = index - r * outShape[1];\n      return ivec2(r, c);\n    }\n  ":`\n    ivec2 getOutputCoords() {\n      ivec2 resTexRC = ivec2(resultUV.yx *\n                             vec2(${e[0]}, ${e[1]}));\n      int index = resTexRC.x * ${e[1]} + resTexRC.y;\n      int r = index / ${t[1]};\n      int c = index - r * ${t[1]};\n      return ivec2(r, c);\n    }\n  `}function yM(t){return`offset${t}`}function vM(t,e){const i=t.name,s="get"+i.charAt(0).toUpperCase()+i.slice(1),o=t.shapeInfo.texShape,r=BL();if(e)return`\n    vec4 ${s}(int index) {\n      ivec2 packedTexShape = ivec2(ceil(float(${i}TexShape[0]) / 2.0), ceil(float(${i}TexShape[1]) / 2.0));\n      vec2 uv = packedUVfrom1D(\n        packedTexShape[0], packedTexShape[1], index);\n      return ${r.texture2D}(${i}, uv);\n    }\n  `;const u=[Math.ceil(o[0]/2),Math.ceil(o[1]/2)];return`\n    vec4 ${s}(int index) {\n      vec2 uv = packedUVfrom1D(\n        ${u[0]}, ${u[1]}, index);\n      return ${r.texture2D}(${i}, uv);\n    }\n  `}function DM(t,e){const i=t.name,s="get"+i.charAt(0).toUpperCase()+i.slice(1);if(t.shapeInfo.isUniform)return`\n      float ${s}(int index) {\n        ${getUniformSampler(t)}\n      }\n    `;const o=t.shapeInfo.texShape,r=o[0],u=o[1];if(1===u&&1===r)return`\n      float ${s}(int index) {\n        return sampleTexture(${i}, halfCR);\n      }\n    `;const a=yM(i);return 1===u?e?`\n      float ${s}(int index) {\n        vec2 uv = vec2(0.5, (float(index + ${a}) + 0.5) / float(${i}TexShape[0]));\n        return sampleTexture(${i}, uv);\n      }\n    `:`\n      float ${s}(int index) {\n        vec2 uv = vec2(0.5, (float(index + ${a}) + 0.5) / ${r}.0);\n        return sampleTexture(${i}, uv);\n      }\n    `:1===r?e?`\n      float ${s}(int index) {\n        vec2 uv = vec2((float(index + ${a}) + 0.5) / float(${i}TexShape[1]), 0.5);\n        return sampleTexture(${i}, uv);\n      }\n    `:`\n      float ${s}(int index) {\n        vec2 uv = vec2((float(index + ${a}) + 0.5) / ${u}.0, 0.5);\n        return sampleTexture(${i}, uv);\n      }\n    `:e?`\n    float ${s}(int index) {\n      vec2 uv = uvFromFlat(${i}TexShape[0], ${i}TexShape[1], index + ${a});\n      return sampleTexture(${i}, uv);\n    }\n  `:`\n    float ${s}(int index) {\n      vec2 uv = uvFromFlat(${r}, ${u}, index + ${a});\n      return sampleTexture(${i}, uv);\n    }\n  `}function lM(t,e){const i=t.shapeInfo.logicalShape,s=t.name,o="get"+s.charAt(0).toUpperCase()+s.slice(1),r=t.shapeInfo.texShape,u=r[0],a=r[1],n=BL();if(null!=r&&Et(i,r))return e?`\n      vec4 ${o}(int row, int col) {\n        vec2 uv = (vec2(col, row) + halfCR) / vec2(${s}TexShape[1], ${s}TexShape[0]);\n\n        return ${n.texture2D}(${s}, uv);\n      }\n    `:`\n      vec4 ${o}(int row, int col) {\n        vec2 uv = (vec2(col, row) + halfCR) / vec2(${a}.0, ${u}.0);\n\n        return ${n.texture2D}(${s}, uv);\n      }\n    `;if(e)return`\n    vec4 ${o}(int row, int col) {\n      ivec2 packedTexShape = ivec2(ceil(float(${s}TexShape[0]) / 2.0), ceil(float(${s}TexShape[1]) / 2.0));\n      int valuesPerRow = int(ceil(float(${s}Shape[1]) / 2.0));\n      vec2 uv = packedUVfrom2D(valuesPerRow, packedTexShape[0], packedTexShape[1], row, col);\n      return ${n.texture2D}(${s}, uv);\n    }\n  `;const L=[Math.ceil(r[0]/2),Math.ceil(r[1]/2)];return`\n    vec4 ${o}(int row, int col) {\n      vec2 uv = packedUVfrom2D(${Math.ceil(i[1]/2)}, ${L[0]}, ${L[1]}, row, col);\n      return ${n.texture2D}(${s}, uv);\n    }\n  `}function gM(t,e){const i=t.shapeInfo.logicalShape,s=t.name,o="get"+s.charAt(0).toUpperCase()+s.slice(1),r=t.shapeInfo.texShape;if(null!=r&&Et(i,r)){if(e)return`\n      float ${o}(int row, int col) {\n        vec2 uv = (vec2(col, row) + halfCR) / vec2(${s}TexShape[1], ${s}TexShape[0]);\n        return sampleTexture(${s}, uv);\n      }\n    `;const t=r[0];return`\n    float ${o}(int row, int col) {\n      vec2 uv = (vec2(col, row) + halfCR) / vec2(${r[1]}.0, ${t}.0);\n      return sampleTexture(${s}, uv);\n    }\n  `}const{newShape:u,keptDims:a}=Nt(i),n=u;if(n.length<i.length){const i=["row","col"];return`\n      ${ZL(OM(t,n),e)}\n      float ${o}(int row, int col) {\n        return ${o}(${zM(i,a)});\n      }\n    `}if(t.shapeInfo.isUniform)return`\n      float ${o}(int row, int col) {\n        int index = round(dot(vec2(row, col), vec2(${i[1]}, 1)));\n        ${getUniformSampler(t)}\n      }\n    `;const L=r[0],M=r[1],C=yM(s);return 1===M?e?`\n      float ${o}(int row, int col) {\n        float index = dot(vec3(row, col, ${C}), vec3(${s}Shape[1], 1, 1));\n        vec2 uv = vec2(0.5, (index + 0.5) / float(${s}TexShape[0]));\n        return sampleTexture(${s}, uv);\n      }\n    `:`\n    float ${o}(int row, int col) {\n      float index = dot(vec3(row, col, ${C}), vec3(${i[1]}, 1, 1));\n      vec2 uv = vec2(0.5, (index + 0.5) / ${L}.0);\n      return sampleTexture(${s}, uv);\n    }\n  `:1===L?e?`\n      float ${o}(int row, int col) {\n        float index = dot(vec3(row, col, ${C}), vec3(${s}Shape[1], 1, 1));\n        vec2 uv = vec2((index + 0.5) / float(${s}TexShape[1]), 0.5);\n        return sampleTexture(${s}, uv);\n      }\n    `:`\n    float ${o}(int row, int col) {\n      float index = dot(vec3(row, col, ${C}), vec3(${i[1]}, 1, 1));\n      vec2 uv = vec2((index + 0.5) / ${M}.0, 0.5);\n      return sampleTexture(${s}, uv);\n    }\n  `:e?`\n      float ${o}(int row, int col) {\n        // Explicitly use integer operations as dot() only works on floats.\n        int index = row * ${s}Shape[1] + col + ${C};\n        vec2 uv = uvFromFlat(${s}TexShape[0], ${s}TexShape[1], index);\n        return sampleTexture(${s}, uv);\n      }\n    `:`\n  float ${o}(int row, int col) {\n    // Explicitly use integer operations as dot() only works on floats.\n    int index = row * ${i[1]} + col + ${C};\n    vec2 uv = uvFromFlat(${L}, ${M}, index);\n    return sampleTexture(${s}, uv);\n  }\n`}function pM(t,e){const i=t.shapeInfo.logicalShape,s=t.name,o="get"+s.charAt(0).toUpperCase()+s.slice(1),r=t.shapeInfo.texShape,u=[Math.ceil(r[0]/2),Math.ceil(r[1]/2)];if(1===i[0]){const s=[1,2],r=["b","row","col"];return`\n        ${XL(OM(t,i.slice(1)),e)}\n        vec4 ${o}(int b, int row, int col) {\n          return ${o}(${zM(r,s)});\n        }\n      `}const a=BL();if(e)return`\n    vec4 ${o}(int b, int row, int col) {\n      ivec2 packedTexShape = ivec2(ceil(float(${s}TexShape[0]) / 2.0), ceil(float(${s}TexShape[1]) / 2.0));\n      int valuesPerRow = int(ceil(float(${s}Shape[2]) / 2.0));\n      int texelsInBatch = valuesPerRow * int(ceil(float(${s}Shape[1]) / 2.0));\n      vec2 uv = packedUVfrom3D(\n        packedTexShape[0], packedTexShape[1], texelsInBatch, valuesPerRow, b, row, col);\n      return ${a.texture2D}(${s}, uv);\n    }\n  `;const n=u[0],L=u[1],M=Math.ceil(i[2]/2);return`\n    vec4 ${o}(int b, int row, int col) {\n      vec2 uv = packedUVfrom3D(\n        ${n}, ${L}, ${M*Math.ceil(i[1]/2)}, ${M}, b, row, col);\n      return ${a.texture2D}(${s}, uv);\n    }\n  `}function jM(t,e){const i=t.shapeInfo.logicalShape,s=t.name,o="get"+s.charAt(0).toUpperCase()+s.slice(1),r=i[1]*i[2],u=i[2],{newShape:a,keptDims:n}=Nt(i),L=a;if(L.length<i.length){const i=["row","col","depth"];return`\n        ${ZL(OM(t,L),e)}\n        float ${o}(int row, int col, int depth) {\n          return ${o}(${zM(i,n)});\n        }\n      `}if(t.shapeInfo.isUniform)return`\n      float ${o}(int row, int col, int depth) {\n        int index = round(dot(vec3(row, col, depth),\n                          vec3(${r}, ${u}, 1)));\n        ${getUniformSampler(t)}\n      }\n    `;const M=t.shapeInfo.texShape,C=M[0],w=M[1],y=t.shapeInfo.flatOffset;if(w===r&&null==y)return e?`\n      float ${o}(int row, int col, int depth) {\n        int stride1 = ${s}Shape[2];\n        float texR = float(row);\n        float texC = dot(vec2(col, depth), vec2(stride1, 1));\n        vec2 uv = (vec2(texC, texR) + halfCR) /\n                   vec2(${s}TexShape[1], ${s}TexShape[0]);\n        return sampleTexture(${s}, uv);\n      }\n    `:`\n        float ${o}(int row, int col, int depth) {\n          float texR = float(row);\n          float texC = dot(vec2(col, depth), vec2(${u}, 1));\n          vec2 uv = (vec2(texC, texR) + halfCR) /\n                     vec2(${w}.0, ${C}.0);\n          return sampleTexture(${s}, uv);\n        }\n      `;if(w===u&&null==y)return e?`\n      float ${o}(int row, int col, int depth) {\n        float texR = dot(vec2(row, col), vec2(${s}Shape[1], 1));\n        float texC = float(depth);\n        vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${s}TexShape[1], ${s}TexShape[0]);\n        return sampleTexture(${s}, uv);\n      }\n    `:`\n    float ${o}(int row, int col, int depth) {\n      float texR = dot(vec2(row, col), vec2(${i[1]}, 1));\n      float texC = float(depth);\n      vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${w}.0, ${C}.0);\n      return sampleTexture(${s}, uv);\n    }\n  `;const v=yM(s);return e?`\n    float ${o}(int row, int col, int depth) {\n      // Explicitly use integer operations as dot() only works on floats.\n      int stride0 = ${s}Shape[1] * ${s}Shape[2];\n      int stride1 = ${s}Shape[2];\n      int index = row * ${r} + col * ${u} + depth + ${v};\n      vec2 uv = uvFromFlat(${s}TexShape[0], ${s}TexShape[1], index);\n      return sampleTexture(${s}, uv);\n    }\n    `:`\n      float ${o}(int row, int col, int depth) {\n        // Explicitly use integer operations as dot() only works on floats.\n        int index = row * ${r} + col * ${u} + depth + ${v};\n        vec2 uv = uvFromFlat(${C}, ${w}, index);\n        return sampleTexture(${s}, uv);\n      }\n  `}function AM(t,e){const i=t.name,s="get"+i.charAt(0).toUpperCase()+i.slice(1),o=BL();if(e)return`\n    vec4 ${s}(int b2, int b, int row, int col) {\n      int valuesPerRow = int(ceil(float(${i}Shape[3]) / 2.0));\n      int texelsInBatch = valuesPerRow * int(ceil(float(${i}Shape[2]) / 2.0));\n      int index = b * texelsInBatch + (row / 2) * valuesPerRow + (col / 2);\n      texelsInBatch *= ${i}Shape[1];\n      index = b2 * texelsInBatch + index;\n      ivec2 packedTexShape = ivec2(ceil(float(${i}TexShape[0]) / 2.0), ceil(float(${i}TexShape[1]) / 2.0));\n      int texR = index / packedTexShape[1];\n      int texC = index - texR * packedTexShape[1];\n      vec2 uv = (vec2(texC, texR) + halfCR) / vec2(packedTexShape[1], packedTexShape[0]); return ${o.texture2D}(${i}, uv);\n    }\n  `;const r=t.shapeInfo.logicalShape,u=r.length,a=t.shapeInfo.texShape,n=[Math.ceil(a[0]/2),Math.ceil(a[1]/2)],L=n[0],M=n[1],C=Math.ceil(r[u-1]/2);let w=C*Math.ceil(r[u-2]/2),y="int b, int row, int col",v=`b * ${w} + (row / 2) * ${C} + (col / 2)`;for(let t=2;t<u-1;t++)y=`int b${t}, `+y,w*=r[u-t-1],v=`b${t} * ${w} + `+v;return`\n    vec4 ${s}(${y}) {\n      int index = ${v};\n      int texR = index / ${M};\n      int texC = index - texR * ${M};\n      vec2 uv = (vec2(texC, texR) + halfCR) / vec2(${M}, ${L});\n      return ${o.texture2D}(${i}, uv);\n    }\n  `}function cM(t,e){const i=t.name,s=i.charAt(0).toUpperCase()+i.slice(1),o="get"+s+"AtOutCoords",r=t.shapeInfo.logicalShape.length,u=e.logicalShape.length,a=HL(t.shapeInfo.logicalShape,e.logicalShape),n=mM(u),L=u-r;let M;const C=["x","y","z","w","u","v"];M=0===r?"":u<2&&a.length>=1?"coords = 0;":a.map((t=>`coords.${C[t+L]} = 0;`)).join("\n");let w="";w=u<2&&r>0?"coords":t.shapeInfo.logicalShape.map(((t,e)=>`coords.${C[e+L]}`)).join(", ");let y="return outputValue;";const v=1===bt(t.shapeInfo.logicalShape),D=1===bt(e.logicalShape);if(1!==r||v||D){if(v&&!D)y=1===u?"\n        return vec4(outputValue.x, outputValue.x, 0., 0.);\n      ":"\n        return vec4(outputValue.x);\n      ";else if(a.length){const t=r-2,e=r-1;a.indexOf(t)>-1&&a.indexOf(e)>-1?y="return vec4(outputValue.x);":a.indexOf(t)>-1?y="return vec4(outputValue.x, outputValue.y, outputValue.x, outputValue.y);":a.indexOf(e)>-1&&(y="return vec4(outputValue.xx, outputValue.zz);")}}else y="\n      return vec4(outputValue.xy, outputValue.xy);\n    ";return`\n    vec4 ${o}() {\n      ${n} coords = getOutputCoords();\n      ${M}\n      vec4 outputValue = get${s}(${w});\n      ${y}\n    }\n  `}function IM(t,e){const i=t.name,s=i.charAt(0).toUpperCase()+i.slice(1),o="get"+s+"AtOutCoords",r=e.texShape,u=t.shapeInfo.texShape,a=t.shapeInfo.logicalShape.length,n=e.logicalShape.length;if(!t.shapeInfo.isUniform&&a===n&&null==t.shapeInfo.flatOffset&&Et(u,r))return`\n      float ${o}() {\n        return sampleTexture(${i}, resultUV);\n      }\n    `;const L=mM(n),M=HL(t.shapeInfo.logicalShape,e.logicalShape),C=n-a;let w;const y=["x","y","z","w","u","v"];w=0===a?"":n<2&&M.length>=1?"coords = 0;":M.map((t=>`coords.${y[t+C]} = 0;`)).join("\n");let v="";return v=n<2&&a>0?"coords":t.shapeInfo.logicalShape.map(((t,e)=>`coords.${y[e+C]}`)).join(", "),`\n    float ${o}() {\n      ${L} coords = getOutputCoords();\n      ${w}\n      return get${s}(${v});\n    }\n  `}function mM(t){if(t<=1)return"int";if(2===t)return"ivec2";if(3===t)return"ivec3";if(4===t)return"ivec4";if(5===t)return"ivec5";if(6===t)return"ivec6";throw Error(`GPU for rank ${t} is not yet supported`)}function hM(t,e,i){const{newShape:s,keptDims:o}=Nt(e),r=e.length,u=t&&3===r&&1===e[0],a=u?e.slice(1):s,n=!t&&r>1&&!Et(e,i)&&s.length<r||u;return{useSqueezeShape:n,uniformShape:n?a:e,keptDims:o}}function OM(t,e){const i=JSON.parse(JSON.stringify(t));return i.shapeInfo.logicalShape=e,i}function zM(t,e){return e.map((e=>t[e])).join(", ")}function xM(t,e,i,s){const o=i.map(((t,i)=>{const s={logicalShape:t.shape,texShape:t.isUniform?null:t.texData.texShape,isUniform:t.isUniform,isPacked:!t.isUniform&&t.texData.isPacked,flatOffset:null};return null!=t.texData&&null!=t.texData.slice&&t.texData.slice.flatOffset>0&&(s.flatOffset=t.texData.slice.flatOffset),{name:e.variableNames[i],shapeInfo:s}})),r=o.map((t=>t.shapeInfo)),u={logicalShape:s.shape,texShape:s.texData.texShape,isUniform:!1,isPacked:s.texData.isPacked,flatOffset:null},a=VL(o,u,e),n=CL(t.gl,a),L=t.createProgram(n);return we().get("ENGINE_COMPILE_ONLY")?{program:e,fragmentShader:n,source:a,webGLProgram:L,inShapeInfos:r,outShapeInfo:u,uniformLocations:null,customUniformLocations:null,infLoc:null,nanLoc:null,inShapesLocations:null,inTexShapesLocations:null,outShapeLocation:null,outShapeStridesLocation:null,outTexShapeLocation:null}:Object.assign({program:e,fragmentShader:n,source:a,webGLProgram:L,inShapeInfos:r,outShapeInfo:u},dM(t,e,L))}function dM(t,e,i){const s={},o={},r={},u=[];let a,n,L,M=null,C=null;C=t.getUniformLocation(i,"NAN",!1),1===we().getNumber("WEBGL_VERSION")&&(M=t.getUniformLocation(i,"INFINITY",!1));const w=!1;for(let u=0;u<e.variableNames.length;u++){const a=e.variableNames[u];s[a]=t.getUniformLocation(i,a,w),s[`offset${a}`]=t.getUniformLocation(i,`offset${a}`,w),e.enableShapeUniforms&&(o[`${a}Shape`]=t.getUniformLocation(i,`${a}Shape`,w),r[`${a}TexShape`]=t.getUniformLocation(i,`${a}TexShape`,w))}return e.enableShapeUniforms&&(a=t.getUniformLocation(i,"outShape",w),L=t.getUniformLocation(i,"outShapeStrides",w),n=t.getUniformLocation(i,"outTexShape",w)),e.customUniforms&&e.customUniforms.forEach(((e,s)=>{u[s]=t.getUniformLocation(i,e.name,w)})),{uniformLocations:s,customUniformLocations:u,infLoc:M,nanLoc:C,inShapesLocations:o,inTexShapesLocations:r,outShapeLocation:a,outShapeStridesLocation:L,outTexShapeLocation:n}}function KM(t,e){if(t.length!==e.length)throw Error(`Binary was compiled with ${t.length} inputs, but was executed with ${e.length} inputs`);t.forEach(((t,i)=>{const s=t.logicalShape,o=e[i],r=o.shape;if(!Et(s,r))throw Error(`Binary was compiled with different shapes than the current args. Shapes ${s} and ${r} must match`);if(t.isUniform&&o.isUniform)return;const u=t.texShape,a=o.isUniform?null:o.texData.texShape;if(!Et(u,a))throw Error(`Binary was compiled with different texture shapes than the current args. Shape ${u} and ${a} must match`)}))}function PM(t,e,i,s,o){e.program.enableShapeUniforms||(KM(e.inShapeInfos,i),KM([e.outShapeInfo],[s]));const r=s.texData.texture,u=s.texData.texShape;s.texData.isPacked?t.setOutputPackedMatrixTexture(r.texture,u[0],u[1]):t.setOutputMatrixTexture(r.texture,u[0],u[1]),t.setProgram(e.webGLProgram),1===we().getNumber("WEBGL_VERSION")&&null!==e.infLoc&&t.gl.uniform1f(e.infLoc,1/0),null!==e.nanLoc&&t.gl.uniform1f(e.nanLoc,NaN),i.forEach(((i,s)=>{const o=e.program.variableNames[s],r=e.uniformLocations[o],u=e.uniformLocations[`offset${o}`],a=e.inShapesLocations[`${o}Shape`],n=e.inTexShapesLocations[`${o}TexShape`];if(a){const{uniformShape:s}=hM(e.program.packedInputs,i.shape,i.texData.texShape);switch(s.length){case 1:t.gl.uniform1iv(a,new Int32Array(s));break;case 2:t.gl.uniform2iv(a,new Int32Array(s));break;case 3:t.gl.uniform3iv(a,new Int32Array(s));break;case 4:t.gl.uniform4iv(a,new Int32Array(s))}}if(n&&t.gl.uniform2i(n,i.texData.texShape[0],i.texData.texShape[1]),null!=r)if(i.isUniform)if(bt(i.shape)<2)t.gl.uniform1f(r,i.uniformValues[0]);else{let e=i.uniformValues;e instanceof Float32Array||(e=new Float32Array(e)),t.gl.uniform1fv(r,e)}else null!=i.texData.slice&&null!=u&&t.gl.uniform1i(u,i.texData.slice.flatOffset),t.setInputMatrixTexture(i.texData.texture.texture,r,s)}));const a=e.outShapeLocation;if(a)switch(s.shape.length){case 1:t.gl.uniform1iv(a,new Int32Array(s.shape));break;case 2:t.gl.uniform2iv(a,new Int32Array(s.shape));break;case 3:t.gl.uniform3iv(a,new Int32Array(s.shape));break;case 4:t.gl.uniform4iv(a,new Int32Array(s.shape))}if(e.outShapeStridesLocation){const i=$t(s.shape);switch(s.shape.length){case 2:t.gl.uniform1iv(e.outShapeStridesLocation,new Int32Array(i));break;case 3:t.gl.uniform2iv(e.outShapeStridesLocation,new Int32Array(i));break;case 4:t.gl.uniform3iv(e.outShapeStridesLocation,new Int32Array(i))}}e.outTexShapeLocation&&t.gl.uniform2i(e.outTexShapeLocation,s.texData.texShape[0],s.texData.texShape[1]),e.program.customUniforms&&o&&e.program.customUniforms.forEach(((i,s)=>{const r=e.customUniformLocations[s],u=o[s];if("float"===i.type)t.gl.uniform1fv(r,u);else if("vec2"===i.type)t.gl.uniform2fv(r,u);else if("vec3"===i.type)t.gl.uniform3fv(r,u);else if("vec4"===i.type)t.gl.uniform4fv(r,u);else if("int"===i.type)t.gl.uniform1iv(r,u);else if("ivec2"===i.type)t.gl.uniform2iv(r,u);else if("ivec3"===i.type)t.gl.uniform3iv(r,u);else{if("ivec4"!==i.type)throw Error(`uniform type ${i.type} is not supported yet.`);t.gl.uniform4iv(r,u)}})),t.executeProgram()}function YM(t,e,i){let s="";e.concat(i).forEach((e=>{const o=null!=e.texData&&null!=e.texData.slice&&e.texData.slice.flatOffset>0;if(t.enableShapeUniforms&&!e.isUniform){const r=e.texData.texShape,{useSqueezeShape:u,uniformShape:a,keptDims:n}=hM(t.packedInputs,e.shape,r);let L="",M="",C="";if(1===a.length&&t.packedInputs){const t=[Math.ceil(r[0]/2),Math.ceil(r[1]/2)];L=`${t[0]>1}_${t[1]>1}`}else if(2!==a.length||t.packedInputs){if(a.length>2&&!t.packedInputs){const t=$t(a);C=`${t[0]===r[1]}_${t[t.length-1]===r[1]}`}}else M=`${a[0]>1}_${a[1]>1}`;const w=e.shape.length,y=2===a.length&&Et(e.shape,r),v=1===bt(e.shape),D=qo(e.shape,i.shape),l=!t.packedInputs&&w===i.shape.length&&Et(r,i.texData.texShape),g=t.packedInputs||a.length>2?"":`${r[0]>1}_${r[1]>1}`;s+=`${w}_${l}_${u?n:""}_${a.length}_${v}_${D}_${y}_${L}_${M}_${C}_${g}_${o}`}else{const t=e.isUniform?"uniform":e.texData.texShape;s+=`${e.shape}_${t}_${o}`}}));const o=t.userCode;let r=t.constructor.name;return r+="_"+s+"_"+o+`${we().getNumber("WEBGL_VERSION")}`,r}function QM(t){return we().getBool("WEBGL_USE_SHAPES_UNIFORMS")&&t<=4}class bM{constructor(t){this.variableNames=["A"],this.packedInputs=!1,this.packedOutput=!0,this.outPackingScheme=yt.DENSE,this.customUniforms=[{name:"texShape",type:"ivec2"}];const e=BL();this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length),this.userCode=`\n      ivec3 outCoordsFromFlatIndex(int index) {\n        ${this.enableShapeUniforms?JL(["r","c","d"],t):UL(["r","c","d"],t)}\n        return ivec3(r, c, d);\n      }\n\n      void main() {\n        ivec2 resTexRC = ivec2(resultUV.yx * vec2(texShape[0], texShape[1]));\n        int index = 4 * (resTexRC.x * texShape[1] + resTexRC.y);\n\n        vec4 result = vec4(0.);\n\n        for (int i=0; i<4; i++) {\n          int flatIndex = index + i;\n          ivec3 rc = outCoordsFromFlatIndex(flatIndex);\n          result[i] = getA(rc.x, rc.y, rc.z);\n        }\n\n        ${e.output} = result;\n      }\n    `}}class EM{constructor(t){this.variableNames=["A"],this.packedInputs=!0,this.packedOutput=!0,this.outPackingScheme=yt.DENSE,this.customUniforms=[{name:"texShape",type:"ivec2"}];const e=BL();this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length),this.userCode=`\n      ivec3 outCoordsFromFlatIndex(int index) {\n        ${this.enableShapeUniforms?JL(["r","c","d"],t):UL(["r","c","d"],t)}\n        return ivec3(r, c, d);\n      }\n\n      void main() {\n        ivec2 resTexRC = ivec2(resultUV.yx * vec2(texShape[0], texShape[1]));\n        int index = 4 * (resTexRC.x * texShape[1] + resTexRC.y);\n\n        vec4 result = vec4(0.);\n\n        for (int i=0; i<4; i++) {\n          int flatIndex = index + i;\n          ivec3 rc = outCoordsFromFlatIndex(flatIndex);\n          result[i] = getChannel(getA(rc.x, rc.y, rc.z), vec2(rc.y, rc.z));\n        }\n\n        ${e.output} = result;\n      }\n    `}}class TM{constructor(t){this.variableNames=["A"],this.outTexUsage=vt.DOWNLOAD;const e=BL();this.outputShape=t,this.userCode=`\n      ${RL}\n\n      void main() {\n        float x = getAAtOutCoords();\n        ${e.output} = encode_float(x);\n      }\n    `}}class SM{constructor(t){this.variableNames=["A"],this.packedInputs=!0,this.packedOutput=!1,this.outTexUsage=vt.DOWNLOAD;const e=BL();this.outputShape=t,this.userCode=`\n      ${RL}\n\n      void main() {\n        ivec3 coords = getOutputCoords();\n        float x = getChannel(getAAtOutCoords(), vec2(coords.y, coords.z));\n        ${e.output} = encode_float(x);\n      }\n    `}}class fM{constructor(t,e=!1){this.variableNames=["A"],this.customUniforms=[{name:"texShape",type:"ivec2"}];const i=BL();this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length);let s="result";e&&(s="floor(result * 255. + 0.5)"),this.userCode=`\n      ${this.enableShapeUniforms?"\n  int getFlatIndex(ivec3 coords) {\n    return coords.x * outShapeStrides[0] + coords.y * outShapeStrides[1] + coords.z;\n  }\n":getFlatIndexFrom3D(t)}\n\n      void main() {\n        ivec3 coords = getOutputCoords();\n\n        int flatIndex = getFlatIndex(coords);\n        int offset = imod(flatIndex, 4);\n\n        flatIndex = idiv(flatIndex, 4, 1.);\n\n        int r = flatIndex / texShape[1];\n        int c = imod(flatIndex, texShape[1]);\n        vec2 uv = (vec2(c, r) + halfCR) / vec2(texShape[1], texShape[0]);\n        vec4 values = ${i.texture2D}(A, uv);\n\n        float result;\n\n        if(offset == 0) {\n          result = values[0];\n        } else if(offset == 1) {\n          result = values[1];\n        } else if(offset == 2) {\n          result = values[2];\n        } else {\n          result = values[3];\n        }\n\n        ${i.output} = vec4(${s}, 0., 0., 0.);\n      }\n    `}}class qM{constructor(t,e=!1){this.variableNames=["A"],this.packedInputs=!1,this.packedOutput=!0,this.customUniforms=[{name:"texShape",type:"ivec2"}];const i=BL();this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length);let s="",o="result";e&&(o="floor(result * 255. + 0.5)");for(let e=0;e<=1;e++)for(let o=0;o<=1;o++){const r=2*e+o;s+=`\n          localCoords = coords;\n          if(localCoords[2] + ${o} < ${this.enableShapeUniforms?"outShape[2]":`${t[2]}`}) {\n          localCoords[2] += ${o};\n          if (localCoords[1] + ${e} < ${this.enableShapeUniforms?"outShape[1]":`${t[1]}`}) {\n            localCoords[1] += ${e};\n\n            flatIndex = getFlatIndex(localCoords);\n            offset = imod(flatIndex, 4);\n\n            flatIndex = idiv(flatIndex, 4, 1.);\n\n            int r = flatIndex / texShape[1];\n            int c = imod(flatIndex, texShape[1]);\n            vec2 uv = (vec2(c, r) + halfCR) / vec2(texShape[1], texShape[0]);\n            values = ${i.texture2D}(A, uv);\n\n            if (offset == 0) {\n              result[${r}] = values[0];\n            } else if (offset == 1) {\n              result[${r}] = values[1];\n            } else if (offset == 2) {\n              result[${r}] = values[2];\n            } else {\n              result[${r}] = values[3];\n            }\n          }\n        }\n        `}this.userCode=`\n        ${this.enableShapeUniforms?"\n  int getFlatIndex(ivec3 coords) {\n    return coords.x * outShapeStrides[0] + coords.y * outShapeStrides[1] + coords.z;\n  }\n":getFlatIndexFrom3D(t)}\n\n        void main() {\n          ivec3 coords = getOutputCoords();\n\n          vec4 result = vec4(0.);\n          int flatIndex, r, c, offset;\n          ivec3 localCoords;\n          vec2 uv;\n          vec4 values;\n\n          ${s}\n\n          ${i.output} = ${o};\n        }\n    `}}function kM(t){const e=BL();return ML(t,`${e.version}\n    precision highp float;\n    ${e.attribute} vec3 clipSpacePos;\n    ${e.attribute} vec2 uv;\n    ${e.varyingVs} vec2 resultUV;\n\n    void main() {\n      gl_Position = vec4(clipSpacePos, 1);\n      resultUV = uv;\n    }`)}function GM(t){return vL(t,new Float32Array([-1,1,0,0,1,-1,-1,0,0,0,1,1,0,1,1,1,-1,0,1,0]))}function NM(t){return DL(t,new Uint16Array([0,1,2,2,1,3]))}function BM(t,e,i,s,o,r){gL(e,i);const u=lL(t),a=t.TEXTURE_2D;return LL(t,(()=>t.bindTexture(a,u))),LL(t,(()=>t.texParameteri(a,t.TEXTURE_WRAP_S,t.CLAMP_TO_EDGE))),LL(t,(()=>t.texParameteri(a,t.TEXTURE_WRAP_T,t.CLAMP_TO_EDGE))),LL(t,(()=>t.texParameteri(a,t.TEXTURE_MIN_FILTER,t.NEAREST))),LL(t,(()=>t.texParameteri(a,t.TEXTURE_MAG_FILTER,t.NEAREST))),1===we().getNumber("WEBGL_VERSION")?LL(t,(()=>t.texImage2D(a,0,s,e,i,0,o,r,null))):LL(t,(()=>t.texStorage2D(a,1,s,e,i))),LL(t,(()=>t.bindTexture(t.TEXTURE_2D,null))),{texture:u,texShape:[i,e]}}function UM(t){return t.internalFormatFloat}function JM(t,e,i,s){const[o,r]=rL(e,i);return BM(t,o,r,UM(s),s.textureFormatFloat,t.FLOAT)}function WM(t){return t.internalFormatPackedFloat}function FM(t,e,i,s){const[o,r]=aL(e,i);return BM(t,o,r,WM(s),t.RGBA,t.FLOAT)}function RM(t,e,i){LL(t,(()=>t.bindBuffer(t.ARRAY_BUFFER,i)));return jL(t,e,"clipSpacePos",i,3,20,0)&&jL(t,e,"uv",i,2,20,12)}function HM(t,e,i,s,o,r){let u,a,n;LL(t,(()=>t.bindTexture(t.TEXTURE_2D,e))),o instanceof Uint8Array?(u=new Uint8Array(i*s*4),a=t.UNSIGNED_BYTE,n=t.RGBA):(u=new Float32Array(i*s*4),a=t.FLOAT,n=r.internalFormatPackedFloat),u.set(o),2===we().getNumber("WEBGL_VERSION")?LL(t,(()=>t.texSubImage2D(t.TEXTURE_2D,0,0,0,i,s,t.RGBA,a,u))):LL(t,(()=>t.texImage2D(t.TEXTURE_2D,0,n,i,s,0,t.RGBA,a,u))),LL(t,(()=>t.bindTexture(t.TEXTURE_2D,null)))}function VM(t,e,i,s){const o=t.createBuffer();LL(t,(()=>t.bindBuffer(t.PIXEL_PACK_BUFFER,o)));const r=16*e*i;return LL(t,(()=>t.bufferData(t.PIXEL_PACK_BUFFER,r,t.STREAM_READ))),LL(t,(()=>t.readPixels(0,0,i,e,t.RGBA,t.FLOAT,0))),LL(t,(()=>t.bindBuffer(t.PIXEL_PACK_BUFFER,null))),o}function ZM(t,e,i){const s=t,o=new Float32Array(i);return s.bindBuffer(s.PIXEL_PACK_BUFFER,e),s.getBufferSubData(s.PIXEL_PACK_BUFFER,0,o),s.bindBuffer(s.PIXEL_PACK_BUFFER,null),o}class XM{constructor(t){this.outputTexture=null,this.program=null,this.disposed=!1,this.vertexAttrsAreBound=!1,this.itemsToPoll=[];const e=we().getNumber("WEBGL_VERSION");null!=t?(this.gl=t,eL(e,t)):this.gl=iL(e);let i="WEBGL_color_buffer_float";const s="EXT_color_buffer_half_float";if(this.parallelCompilationExtension=this.gl.getExtension("KHR_parallel_shader_compile"),1===we().getNumber("WEBGL_VERSION")){const t="OES_texture_float",e="OES_texture_half_float";if(this.textureFloatExtension=getExtensionOrThrow(this.gl,t),SL(this.gl,e))this.textureHalfFloatExtension=getExtensionOrThrow(this.gl,e);else if(we().get("WEBGL_FORCE_F16_TEXTURES"))throw new Error("GL context does not support half float textures, yet the environment flag WEBGL_FORCE_F16_TEXTURES is set to true.");if(this.colorBufferFloatExtension=this.gl.getExtension(i),SL(this.gl,s))this.colorBufferHalfFloatExtension=getExtensionOrThrow(this.gl,s);else if(we().get("WEBGL_FORCE_F16_TEXTURES"))throw new Error("GL context does not support color renderable half floats, yet the environment flag WEBGL_FORCE_F16_TEXTURES is set to true.")}else if(i="EXT_color_buffer_float",SL(this.gl,i))this.colorBufferFloatExtension=this.gl.getExtension(i);else{if(!SL(this.gl,s))throw new Error("GL context does not support color renderable floats");this.colorBufferHalfFloatExtension=this.gl.getExtension(s)}this.vertexBuffer=GM(this.gl),this.indexBuffer=NM(this.gl),this.framebuffer=pL(this.gl),this.textureConfig=nL(this.gl,this.textureHalfFloatExtension)}get debug(){return we().getBool("DEBUG")}dispose(){if(this.disposed)return;null!=this.program&&console.warn("Disposing a GPGPUContext that still has a bound WebGLProgram. This is probably a resource leak, delete the program with GPGPUContext.deleteProgram before disposing."),null!=this.outputTexture&&console.warn("Disposing a GPGPUContext that still has a bound output matrix texture.  This is probably a resource leak, delete the output matrix texture with GPGPUContext.deleteMatrixTexture before disposing.");const t=this.gl;LL(t,(()=>t.finish())),LL(t,(()=>t.bindFramebuffer(t.FRAMEBUFFER,null))),LL(t,(()=>t.deleteFramebuffer(this.framebuffer))),LL(t,(()=>t.bindBuffer(t.ARRAY_BUFFER,null))),LL(t,(()=>t.bindBuffer(t.ELEMENT_ARRAY_BUFFER,null))),LL(t,(()=>t.deleteBuffer(this.indexBuffer))),this.disposed=!0}createFloat32MatrixTexture(t,e){return this.throwIfDisposed(),JM(this.gl,t,e,this.textureConfig)}createFloat16MatrixTexture(t,e){return this.throwIfDisposed(),createFloat16MatrixTexture(this.gl,t,e,this.textureConfig)}createUnsignedBytesMatrixTexture(t,e){return this.throwIfDisposed(),createUnsignedBytesMatrixTexture(this.gl,t,e,this.textureConfig)}uploadPixelDataToTexture(t,e){this.throwIfDisposed(),uploadPixelDataToTexture(this.gl,t,e)}uploadDenseMatrixToTexture(t,e,i,s){this.throwIfDisposed(),HM(this.gl,t,e,i,s,this.textureConfig)}createFloat16PackedMatrixTexture(t,e){return this.throwIfDisposed(),createFloat16PackedMatrixTexture(this.gl,t,e,this.textureConfig)}createPackedMatrixTexture(t,e){return this.throwIfDisposed(),FM(this.gl,t,e,this.textureConfig)}deleteMatrixTexture(t){this.throwIfDisposed(),this.outputTexture===t&&(unbindColorTextureFromFramebuffer(this.gl,this.framebuffer),this.outputTexture=null),LL(this.gl,(()=>this.gl.deleteTexture(t)))}downloadByteEncodedFloatMatrixFromOutputTexture(t,e,i){return this.downloadMatrixDriver(t,(()=>downloadByteEncodedFloatMatrixFromOutputTexture(this.gl,e,i,this.textureConfig)))}downloadPackedMatrixFromBuffer(t,e,i,s,o,r){return downloadPackedMatrixFromBuffer(this.gl,t,e,i,s,o,r,this.textureConfig)}downloadFloat32MatrixFromBuffer(t,e){return ZM(this.gl,t,e)}createBufferFromTexture(t,e,i){this.bindTextureToFrameBuffer(t);const s=VM(this.gl,e,i,this.textureConfig);return this.unbindTextureToFrameBuffer(),s}createAndWaitForFence(){const t=this.createFence(this.gl);return this.pollFence(t)}createFence(t){let e,i;if(we().getBool("WEBGL_FENCE_API_ENABLED")){const s=t,o=s.fenceSync(s.SYNC_GPU_COMMANDS_COMPLETE,0);t.flush(),i=()=>{const t=s.clientWaitSync(o,0,0);return t===s.ALREADY_SIGNALED||t===s.CONDITION_SATISFIED},e=o}else we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")>0?(e=this.beginQuery(),this.endQuery(),i=()=>this.isQueryAvailable(e,we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION"))):i=()=>!0;return{query:e,isFencePassed:i}}downloadMatrixFromPackedTexture(t,e,i){return this.downloadMatrixDriver(t,(()=>downloadMatrixFromPackedOutputTexture(this.gl,e,i)))}createProgram(t){this.throwIfDisposed();const e=this.gl;null==this.vertexShader&&(this.vertexShader=kM(e));const i=wL(e);return LL(e,(()=>e.attachShader(i,this.vertexShader))),LL(e,(()=>e.attachShader(i,t))),yL(e,i),this.debug&&validateProgram(e,i),this.vertexAttrsAreBound||(this.setProgram(i),this.vertexAttrsAreBound=RM(e,this.program,this.vertexBuffer)),i}deleteProgram(t){this.throwIfDisposed(),t===this.program&&(this.program=null),null!=t&&LL(this.gl,(()=>this.gl.deleteProgram(t)))}setProgram(t){this.throwIfDisposed(),this.program=t,null!=this.program&&this.debug&&validateProgram(this.gl,this.program),LL(this.gl,(()=>this.gl.useProgram(t)))}getUniformLocation(t,e,i=!0){return this.throwIfDisposed(),i?getProgramUniformLocationOrThrow(this.gl,t,e):cL(this.gl,t,e)}getAttributeLocation(t,e){return this.throwIfDisposed(),LL(this.gl,(()=>this.gl.getAttribLocation(t,e)))}getUniformLocationNoThrow(t,e){return this.throwIfDisposed(),this.gl.getUniformLocation(t,e)}setInputMatrixTexture(t,e,i){this.throwIfDisposed(),this.throwIfNoProgram(),IL(this.gl,t,e,i)}setOutputMatrixTexture(t,e,i){this.setOutputMatrixTextureDriver(t,i,e)}setOutputPackedMatrixTexture(t,e,i){this.throwIfDisposed();const[s,o]=aL(e,i);this.setOutputMatrixTextureDriver(t,s,o)}setOutputMatrixWriteRegion(t,e,i,s){this.setOutputMatrixWriteRegionDriver(i,t,s,e)}setOutputPackedMatrixWriteRegion(t,e,i,s){throw new Error("setOutputPackedMatrixWriteRegion not implemented.")}debugValidate(){null!=this.program&&validateProgram(this.gl,this.program),validateFramebuffer(this.gl)}executeProgram(){this.throwIfDisposed(),this.throwIfNoProgram();const t=this.gl;this.debug&&this.debugValidate(),LL(t,(()=>t.drawElements(t.TRIANGLES,6,t.UNSIGNED_SHORT,0)))}blockUntilAllProgramsCompleted(){this.throwIfDisposed(),LL(this.gl,(()=>this.gl.finish()))}getQueryTimerExtension(){return null==this.disjointQueryTimerExtension&&(this.disjointQueryTimerExtension=getExtensionOrThrow(this.gl,2===we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")?"EXT_disjoint_timer_query_webgl2":"EXT_disjoint_timer_query")),this.disjointQueryTimerExtension}getQueryTimerExtensionWebGL2(){return this.getQueryTimerExtension()}getQueryTimerExtensionWebGL1(){return this.getQueryTimerExtension()}beginQuery(){if(2===we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")){const t=this.gl,e=this.getQueryTimerExtensionWebGL2(),i=t.createQuery();return t.beginQuery(e.TIME_ELAPSED_EXT,i),i}const t=this.getQueryTimerExtensionWebGL1(),e=t.createQueryEXT();return t.beginQueryEXT(t.TIME_ELAPSED_EXT,e),e}endQuery(){if(2===we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")){const t=this.gl,e=this.getQueryTimerExtensionWebGL2();return void t.endQuery(e.TIME_ELAPSED_EXT)}const t=this.getQueryTimerExtensionWebGL1();t.endQueryEXT(t.TIME_ELAPSED_EXT)}async waitForQueryAndGetTime(t){return await qt((()=>this.disposed||this.isQueryAvailable(t,we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION")))),this.getQueryTime(t,we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_VERSION"))}getQueryTime(t,e){if(0===e)return null;if(2===e){const e=this.gl;return e.getQueryParameter(t,e.QUERY_RESULT)/1e6}{const e=this.getQueryTimerExtensionWebGL1();return e.getQueryObjectEXT(t,e.QUERY_RESULT_EXT)/1e6}}isQueryAvailable(t,e){if(0===e)return!0;if(2===e){const e=this.gl,i=this.getQueryTimerExtensionWebGL2(),s=e.getQueryParameter(t,e.QUERY_RESULT_AVAILABLE);return null==this.disjoint&&(this.disjoint=this.gl.getParameter(i.GPU_DISJOINT_EXT)),s&&!this.disjoint}{const e=this.getQueryTimerExtensionWebGL1(),i=e.getQueryObjectEXT(t,e.QUERY_RESULT_AVAILABLE_EXT);return null==this.disjoint&&(this.disjoint=this.gl.getParameter(e.GPU_DISJOINT_EXT)),i&&!this.disjoint}}pollFence(t){return new Promise((e=>{this.addItemToPoll((()=>t.isFencePassed()),(()=>e()))}))}pollItems(){const t=_M(this.itemsToPoll.map((t=>t.isDoneFn)));for(let e=0;e<=t;++e){const{resolveFn:t}=this.itemsToPoll[e];t()}this.itemsToPoll=this.itemsToPoll.slice(t+1)}addItemToPoll(t,e){this.itemsToPoll.push({isDoneFn:t,resolveFn:e}),this.itemsToPoll.length>1||qt((()=>(this.pollItems(),0===this.itemsToPoll.length)))}bindTextureToFrameBuffer(t){this.throwIfDisposed(),mL(this.gl,t,this.framebuffer),this.debug&&validateFramebuffer(this.gl)}unbindTextureToFrameBuffer(){null!=this.outputTexture?(mL(this.gl,this.outputTexture,this.framebuffer),this.debug&&validateFramebuffer(this.gl)):unbindColorTextureFromFramebuffer(this.gl,this.framebuffer)}downloadMatrixDriver(t,e){this.bindTextureToFrameBuffer(t);const i=e();return this.unbindTextureToFrameBuffer(),i}setOutputMatrixTextureDriver(t,e,i){this.throwIfDisposed();const s=this.gl;mL(s,t,this.framebuffer),this.debug&&validateFramebuffer(s),this.outputTexture=t,LL(s,(()=>s.viewport(0,0,e,i))),LL(s,(()=>s.scissor(0,0,e,i)))}setOutputMatrixWriteRegionDriver(t,e,i,s){this.throwIfDisposed(),LL(this.gl,(()=>this.gl.scissor(t,e,i,s)))}throwIfDisposed(){if(this.disposed)throw new Error("Attempted to use disposed GPGPUContext.")}throwIfNoProgram(){if(null==this.program)throw new Error("No GPU program is currently set.")}}function _M(t){let e=0;for(;e<t.length;++e){if(!t[e]())break}return e-1}function $M(t){return(e,i,s,o,r)=>{const u=Go(e,i),a=u.length,n=$t(u),L=Bt(r,bt(u)),M=e.length,C=i.length,w=$t(e),y=$t(i),v=qo(e,u),D=qo(i,u);if(v.length+D.length===0)for(let e=0;e<L.length;++e)L[e]=t(s[e%s.length],o[e%o.length]);else for(let e=0;e<L.length;++e){const i=ue(e,a,n),r=i.slice(-M);v.forEach((t=>r[t]=0));const u=re(r,M,w),l=i.slice(-C);D.forEach((t=>l[t]=0));const g=re(l,C,y);L[e]=t(s[u],o[g])}return[L,u]}}const tC=$M(((t,e)=>t+e));function eC(t,e,i,s,o){const r=bt(s),u=se(o,i);for(let i=0;i<t.length;i++){const s=t[i];if(s<0)throw new Error("Input x must be non-negative!");s>=o||(u[s]+=r>0?e[i]:1)}return u}function iC(t){return(e,i,s)=>{const o=Bt(i,e.length);for(let i=0;i<e.length;++i)o[i]=t(e[i],s);return o}}const sC=iC((t=>Math.ceil(t)));function oC(t,e,i,s){const o=Ut(i,bt(e));if(s&&"string"!==i){let e=0;t.forEach((t=>{const i=bt(t.shape);o.set(t.vals,e),e+=i}))}else{let s=0;t.forEach((t=>{const r="string"===i?fromUint8ToStringArray(t.vals):t.vals;let u=0;for(let i=0;i<t.shape[0];++i){const a=i*e[1]+s;for(let e=0;e<t.shape[1];++e)o[a+e]=r[u++]}s+=t.shape[1]}))}return o}const rC=$M(((t,e)=>t===e?1:0)),uC=iC((t=>Math.exp(t))),aC=iC((t=>Math.expm1(t))),nC=iC((t=>Math.floor(t)));function LC(t,e,i){const s=io(i,t.dtype);for(let i=0;i<s.size;++i){const o=s.indexToLoc(i).slice(),r=o[0],u=o[2],a=e.locToIndex([r,u]);o[2]=e.values[a];const n=t.locToIndex(o);0<=n&&n<t.values.length&&(s.values[i]=t.values[n])}return s}const MC=$M(((t,e)=>t>e?1:0)),CC=$M(((t,e)=>t>=e?1:0)),wC=$M(((t,e)=>t<e?1:0)),yC=$M(((t,e)=>t<=e?1:0)),vC=iC((t=>Math.log(t)));function DC(t,e,i,s){const o=Bt(s,bt(i));for(let i=0;i<o.length;++i){const s=i*e;let r=t[s];for(let i=0;i<e;++i){const e=t[s+i];(Number.isNaN(e)||e>r)&&(r=e)}o[i]=r}return o}const lC=$M(((t,e)=>Math.max(t,e))),gC=$M(((t,e)=>Math.min(t,e))),pC=$M(((t,e)=>t*e));function jC(t,e,i){const s=bi(-1,i);return pC([],e,s,t,i)}const AC=$M(((t,e)=>t!==e?1:0));function cC(t,e,i,s,o){const r=e.length,u=bt(e),a=$t(e),n=$t(o),L=Bt(i,bt(o));for(let e=0;e<u;++e){const i=ue(e,r,a),o=new Array(i.length);for(let t=0;t<o.length;t++)o[t]=i[s[t]];L[re(o,r,n)]=t[e]}return L}function IC(t,e,i,s){const[o,r]=Kr(t,s),u=Vi(e,"int32"),a=se(bt(o),u),n=bt(r);for(let t=0;t<a.length;++t){const e=t*n;let s=1;for(let t=0;t<n;++t)s*=i[e+t];a[t]=s}return{outVals:a,outShape:o,outDtype:u}}function mC(t,e,i,s){if(t===e||t<e&&i<0||e<t&&i>1)return se(0,s);const o=se(Math.abs(Math.ceil((e-t)/i)),s);e<t&&1===i&&(i=-1),o[0]=t;for(let t=1;t<o.length;t++)o[t]=o[t-1]+i;return o}const hC=iC((t=>1/Math.sqrt(t)));function OC(t,e,i,s,o,r,u,a,n,L){const M=[s/o,o],C=t.values,w=e.values;if(0===s)return io(i,e.dtype);const y=io(M,e.dtype);"string"==typeof n||"number"==typeof n?y.values.fill(n):"boolean"==typeof n&&y.values.fill(+n);for(let t=0;t<r;t++){const r=[];let n=0;for(let e=0;e<u;e++){const i=C[t*u+e];r.push(i),n+=i*a[e]}if(n<0||n>=s/o)throw new Error(`Invalid indices: ${r} does not index into ${i}`);for(let i=0;i<o;i++)L?y.values[n*o+i]+=w[t*o+i]:y.values[n*o+i]=0===e.rank?w[0]:w[t*o+i]}return y}const zC=iC((t=>1/(1+Math.exp(-t))));function xC(t,e,i,s,o){const r=Uo(s,e,i),u=bt(i),a=$t(s);if(r){const i=Jo(e,a);return"string"===o?t.slice(i,i+u):t.subarray(i,i+u)}const n=io(s,o,"string"===o?fromUint8ToStringArray(t):t),L=io(i,o);for(let t=0;t<L.size;++t){const i=L.indexToLoc(t),s=i.map(((t,i)=>t+e[i]));L.set(n.get(...s),...i)}return"string"===o?fromStringArrayToUint8(L.values):L.values}const dC=iC((t=>Math.sqrt(t))),KC=$M(((t,e)=>{const i=t-e;return i*i})),PC=$M(((t,e)=>t-e));var lt=Object.freeze({__proto__:null,simpleAbsImpl:()=>{},addImpl:tC,bincountImpl:eC,bincountReduceImpl:()=>{},ceilImpl:sC,concatImpl:oC,equalImpl:rC,expImpl:uC,expm1Impl:aC,floorImpl:nC,gatherNdImpl:()=>{},gatherV2Impl:LC,greaterImpl:MC,greaterEqualImpl:CC,lessImpl:wC,lessEqualImpl:yC,linSpaceImpl:()=>{},logImpl:vC,maxImpl:DC,maximumImpl:lC,minimumImpl:gC,multiplyImpl:pC,negImpl:jC,notEqualImpl:AC,prodImpl:IC,rangeImpl:mC,rsqrtImpl:hC,scatterImpl:OC,sigmoidImpl:zC,sliceImpl:xC,sparseFillEmptyRowsImpl:()=>{},sparseReshapeImpl:()=>{},sparseSegmentReductionImpl:()=>{},sqrtImpl:dC,squaredDifferenceImpl:KC,stridedSliceImpl:()=>{},stringNGramsImpl:()=>{},stringSplitImpl:()=>{},stringToHashBucketFastImpl:()=>{},subImpl:PC,tileImpl:()=>{},topKImpl:()=>{},transposeImpl:cC,uniqueImpl:()=>{}});const{addImpl:YC,bincountImpl:QC,bincountReduceImpl:bC,ceilImpl:EC,concatImpl:TC,equalImpl:SC,expImpl:fC,expm1Impl:qC,floorImpl:kC,gatherNdImpl:GC,gatherV2Impl:NC,greaterImpl:BC,greaterEqualImpl:UC,lessImpl:JC,lessEqualImpl:WC,linSpaceImpl:FC,logImpl:RC,maxImpl:HC,maximumImpl:VC,minimumImpl:ZC,multiplyImpl:XC,negImpl:_C,notEqualImpl:$C,prodImpl:tw,rangeImpl:ew,rsqrtImpl:iw,scatterImpl:sw,sigmoidImpl:ow,simpleAbsImpl:rw,sliceImpl:uw,sparseFillEmptyRowsImpl:aw,sparseReshapeImpl:nw,sparseSegmentReductionImpl:Lw,sqrtImpl:Mw,stridedSliceImpl:Cw,stringNGramsImpl:ww,stringSplitImpl:yw,stringToHashBucketFastImpl:vw,subImpl:Dw,tileImpl:lw,topKImpl:gw,transposeImpl:pw,uniqueImpl:jw}=lt;function Aw(t,e){return["x","y","z","w","u","v"].slice(0,e).map((e=>`${t}.${e}`))}function cw(t,e){return 1===e?[t]:Aw(t,e)}function Iw(t,e){if(1===t)return"rc";let i="";for(let s=0;s<t;s++)i+=e[s],s<t-1&&(i+=",");return i}class mw{constructor(t){if(this.variableNames=["A"],this.packedInputs=!1,this.packedOutput=!0,this.outputShape=t,this.rank=t.length,this.enableShapeUniforms=QM(this.outputShape.length),0===this.rank)this.userCode="\n        void main() {\n          setOutput(vec4(getA(), 0., 0., 0.));\n        }\n      ";else{const t=cw("rc",this.rank),e=mM(this.rank),i=this.getOutOfBoundsCondition(t),s=this.getSetup(t),o=this.getOutput(t);this.userCode=`\n        void main() {\n          ${e} rc = getOutputCoords();\n\n          if(${i}) {\n            setOutput(vec4(0));\n          } else {\n            ${s}\n\n            setOutput(vec4(${o}));\n          }\n        }\n      `}}getSourceCoordsArr(t){const e=[];for(let i=0;i<=1;i++)for(let s=0;s<=1;s++){let o=`${0===i?"r":"rp1"}, ${0===s?"c":"cp1"}`;for(let e=2;e<this.rank;e++)o=`${t[t.length-1-e]},`+o;e.push(o)}return e}getOutOfBoundsCondition(t){if(1===this.rank)return`rc > ${this.enableShapeUniforms?"outShape":this.outputShape[0]}`;let e="";for(let i=this.rank-2;i<this.rank;i++)e+=`${t[i]} >= ${this.enableShapeUniforms?`outShape[${i}]`:this.outputShape[i]}`,i<this.rank-1&&(e+="||");return e}getSetup(t){if(1===this.rank)return"";const e=t.slice(-2),i=this.enableShapeUniforms?`outShape[${this.rank} - 1]`:this.outputShape[this.rank-1],s=this.enableShapeUniforms?`outShape[${this.rank} - 2]`:this.outputShape[this.rank-2];return`\n      int r = ${e[0]};\n      int c = ${e[1]};\n      int rp1 = r + 1;\n      int cp1 = c + 1;\n\n      bool cEdge = cp1 >= ${i};\n      bool rEdge = rp1 >= ${s};\n    `}getOutput(t){const e=this.getSourceCoordsArr(t);if(1===this.rank){return`getA(rc), (rc + 1 >= ${this.enableShapeUniforms?"outShape":this.outputShape[0]} ? 0. : getA(rc + 1)), 0, 0`}return`getA(${e[0]}),\n            cEdge ? 0. : getA(${e[1]}),\n            rEdge ? 0. : getA(${e[2]}),\n            rEdge || cEdge ? 0. : getA(${e[3]})`}}class hw{constructor(t,e){this.variableNames=["A"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:"inputShape",type:"ivec3"}],this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length);let i="";for(let t=0;t<4;t++){let e="thisRC = rc;";t%2==1&&(e+="thisRC.z += 1;"),t>1&&(e+="thisRC.y += 1;"),i+=`\n        ${e}\n        ${t>0?"if(thisRC.y < rows && thisRC.z < cols){":""}\n          int flatIndex = getFlatIndex(thisRC);\n\n          ivec3 inputRC = inputCoordsFromReshapedOutCoords(flatIndex);\n          vec2 inputRCInnerDims = vec2(float(inputRC.y),float(inputRC.z));\n\n          result[${t}] =\n            getChannel(getA(inputRC.x, inputRC.y, inputRC.z), inputRCInnerDims);\n        ${t>0?"}":""}\n      `}this.userCode=`\n      ${Ow(e,this.enableShapeUniforms)}\n      ${this.enableShapeUniforms?"\n  int getFlatIndex(ivec3 coords) {\n    return coords.x * outShapeStrides[0] + coords.y * outShapeStrides[1] + coords.z;\n  }\n":getFlatIndexFrom3D(t)}\n\n      void main() {\n        ivec3 rc = getOutputCoords();\n\n        vec4 result = vec4(0.);\n\n        ivec3 thisRC;\n        int rows = ${this.enableShapeUniforms?"outShape[1]":t[1]};\n        int cols = ${this.enableShapeUniforms?"outShape[2]":t[2]};\n\n        ${i}\n\n        setOutput(result);\n      }\n    `}}function Ow(t,e){return`\n    ivec3 inputCoordsFromReshapedOutCoords(int index) {\n      ${e?FL(["r","c","d"],"inputShape"):UL(["r","c","d"],t)}\n      return ivec3(r, c, d);\n    }\n  `}class zw{constructor(t){this.gpgpu=t,this.numUsedTextures=0,this.numFreeTextures=0,this._numBytesAllocated=0,this._numBytesFree=0,this.freeTextures={},this.logEnabled=!1,this.usedTextures={}}acquireTexture(t,e,i){const s=Yw(e,i),o=Qw(t,s,i);o in this.freeTextures||(this.freeTextures[o]=[]),o in this.usedTextures||(this.usedTextures[o]=[]);const r=dw(t,s,this.gpgpu.gl,this.gpgpu.textureConfig,i);if(this.freeTextures[o].length>0){this.numFreeTextures--,this.numUsedTextures++,this._numBytesFree-=r,this.log();const t=this.freeTextures[o].shift();return this.usedTextures[o].push(t),t}let u;return s===Dt.PACKED_2X2_FLOAT32?u=this.gpgpu.createPackedMatrixTexture(t[0],t[1]):s===Dt.PACKED_2X2_FLOAT16?u=this.gpgpu.createFloat16PackedMatrixTexture(t[0],t[1]):s===Dt.UNPACKED_FLOAT32?u=this.gpgpu.createFloat32MatrixTexture(t[0],t[1]):s===Dt.UNPACKED_FLOAT16?u=this.gpgpu.createFloat16MatrixTexture(t[0],t[1]):s===Dt.PACKED_4X1_UNSIGNED_BYTE&&(u=this.gpgpu.createUnsignedBytesMatrixTexture(t[0],t[1])),this.usedTextures[o].push(u),this.numUsedTextures++,this._numBytesAllocated+=r,this.log(),u}releaseTexture(t,e,i,s){if(null==this.freeTextures)return;const o=Yw(i,s),r=Qw(e,o,s);r in this.freeTextures||(this.freeTextures[r]=[]);const u=dw(e,o,this.gpgpu.gl,this.gpgpu.textureConfig,s),a=we().get("WEBGL_DELETE_TEXTURE_THRESHOLD");-1!==a&&this._numBytesAllocated>a?(this.gpgpu.deleteMatrixTexture(t.texture),this._numBytesAllocated-=u):(this.freeTextures[r].push(t),this.numFreeTextures++,this._numBytesFree+=u),this.numUsedTextures--;const n=this.usedTextures[r],L=n.indexOf(t);if(L<0)throw new Error("Cannot release a texture that was never provided by this texture manager");n.splice(L,1),this.log()}log(){if(!this.logEnabled)return;const t=this.numFreeTextures+this.numUsedTextures;console.log("Free/Used",`${this.numFreeTextures} / ${this.numUsedTextures}`,`(${t})`);const e=this._numBytesFree/this._numBytesAllocated;console.log(`Bytes allocated: ${this._numBytesAllocated}`),console.log(`Bytes unused: ${this._numBytesFree} (${Math.round(100*e)}%)`)}get numBytesAllocated(){return this._numBytesAllocated}get numBytesFree(){return this._numBytesFree}getNumUsedTextures(){return this.numUsedTextures}getNumFreeTextures(){return this.numFreeTextures}dispose(){if(null!=this.freeTextures){for(const t in this.freeTextures)this.freeTextures[t].forEach((t=>{this.gpgpu.deleteMatrixTexture(t.texture)}));for(const t in this.usedTextures)this.usedTextures[t].forEach((t=>{this.gpgpu.deleteMatrixTexture(t.texture)}));this.freeTextures=null,this.usedTextures=null,this.numUsedTextures=0,this.numFreeTextures=0,this._numBytesAllocated=0,this._numBytesFree=0}}}function xw(t,e){const i=t;if(e===i.R32F)return 4;if(e===i.R16F)return 2;if(e===i.RGBA32F)return 16;if(e===t.RGBA)return 16;if(e===i.RGBA16F)return 8;if(e===i.RGBA8)return 4;throw new Error(`Unknown internal format ${e}`)}function dw(t,e,i,s,o){const r=Kw(e,s);let u;if(o){const[e,i]=aL(t[0],t[1]);u=e*i}else{const[e,i]=rL(t[0],t[1]);u=e*i}return u*xw(i,r)}function Kw(t,e){switch(t){case Dt.PACKED_2X2_FLOAT32:return WM(e);case Dt.PACKED_2X2_FLOAT16:return getInternalFormatForFloat16PackedMatrixTexture(e);case Dt.UNPACKED_FLOAT32:return UM(e);case Dt.UNPACKED_FLOAT16:return getInternalFormatForFloat16MatrixTexture(e);case Dt.PACKED_4X1_UNSIGNED_BYTE:return getInternalFormatForUnsignedBytesMatrixTexture(e);default:throw new Error(`Unknown physical texture type ${t}`)}}function Pw(t){return we().getBool("WEBGL_RENDER_FLOAT32_ENABLED")?t?Dt.PACKED_2X2_FLOAT32:Dt.UNPACKED_FLOAT32:t?Dt.PACKED_2X2_FLOAT16:Dt.UNPACKED_FLOAT16}function Yw(t,e){if(t===vt.UPLOAD)return Dt.PACKED_2X2_FLOAT32;if(t===vt.RENDER||null==t)return Pw(e);if(t===vt.DOWNLOAD||t===vt.PIXELS)return Dt.PACKED_4X1_UNSIGNED_BYTE;throw new Error(`Unknown logical texture type ${t}`)}function Qw(t,e,i){return`${t[0]}_${t[1]}_${e}_${i}`}class bw{constructor(t,e){this.variableNames=["A"],this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length),this.userCode=`\n      float unaryOperation(float x) {\n        ${e}\n      }\n\n      void main() {\n        float x = getAAtOutCoords();\n        float y = unaryOperation(x);\n\n        setOutput(y);\n      }\n    `}}const Ew="if (isnan(x)) return x;",Tw="return x;",Sw="return abs(x);",fw="return (x >= 0.0) ? x : (exp(x) - 1.0);",qw=Ew+"\n  return (x < 0.0) ? 0.0 : x;\n",kw=Ew+"\n  return (x < 0.0) ? 0.0 : min(6.0, x);\n",Gw="return x;",Nw="return 1.0 / (1.0 + exp(-1.0 * x));",Bw="return x;",Uw="\n  vec4 result;\n\n  result.r = (x.r >= 0.0) ? x.r : (exp(x.r) - 1.0);\n  result.g = (x.g >= 0.0) ? x.g : (exp(x.g) - 1.0);\n  result.b = (x.b >= 0.0) ? x.b : (exp(x.b) - 1.0);\n  result.a = (x.a >= 0.0) ? x.a : (exp(x.a) - 1.0);\n\n  return result;\n",Jw="\n  vec4 result = x * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n",Ww="\n  vec4 result = min(x, vec4(6.)) * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n",Fw="return 1.0 / (1.0 + exp(-1.0 * x));";class Rw{constructor(t,e){this.variableNames=["A"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length),this.userCode=`\n      vec4 unaryOperation(vec4 x) {\n        ${e}\n      }\n\n      void main() {\n        vec4 x = getAAtOutCoords();\n        vec4 y = unaryOperation(x);\n\n        setOutput(y);\n      }\n    `}}class Hw{constructor(t){this.variableNames=["A"],this.packedInputs=!0,this.packedOutput=!1,this.outputShape=t,this.enableShapeUniforms=QM(this.outputShape.length);const e=t.length,i=cw("rc",e),s=mM(e),o=Iw(e,i),r=i.slice(-2),u=e<=1?"rc":`vec2(${r.join(",")})`;this.userCode=`\n      void main() {\n        ${s} rc = getOutputCoords();\n        vec4 packedInput = getA(${o});\n\n        setOutput(getChannel(packedInput, ${u}));\n      }\n    `}}const Vw=1e-7,Zw=1e-4,Xw={};function _w(t){return t in Xw||(Xw[t]={}),Xw[t]}const $w=we().getNumber("CPU_HANDOFF_SIZE_THRESHOLD"),ty=600;class ey extends zt{constructor(t){if(super(),this.pendingRead=new WeakMap,this.pendingDisposal=new WeakSet,this.dataRefCount=new WeakMap,this.numBytesInGPU=0,this.uploadWaitMs=0,this.downloadWaitMs=0,this.lastGlFlushTime=0,this.warnedAboutMemory=!1,this.pendingDeletes=0,this.disposed=!1,!we().getBool("HAS_WEBGL"))throw new Error("WebGL is not supported on this device");let e;if(null!=t){if(t instanceof XM)e=t;else{const i=iL(we().getNumber("WEBGL_VERSION"),t);e=new XM(i)}this.binaryCache={},this.gpgpuCreatedLocally=!1}else{const t=iL(we().getNumber("WEBGL_VERSION"));e=new XM(t),this.binaryCache=_w(we().getNumber("WEBGL_VERSION")),this.gpgpuCreatedLocally=!0}this.gpgpu=e,this.canvas=this.gpgpu.gl.canvas,this.textureManager=new zw(this.gpgpu),this.numMBBeforeWarning=null==we().global.screen?1024:we().global.screen.height*we().global.screen.width*window.devicePixelRatio*ty/1024/1024,this.texData=new Ot(this,Ko())}nextDataId(){return ey.nextDataId++}numDataIds(){return this.texData.numDataIds()-this.pendingDeletes}write(t,e,i){if((we().getBool("WEBGL_CHECK_NUMERICAL_PROBLEMS")||we().getBool("DEBUG"))&&this.checkNumericalProblems(t),"complex64"===i&&null!=t)throw new Error("Cannot write to a complex64 dtype. Please use tf.complex(real, imag).");const s={id:this.nextDataId()};return this.texData.set(s,{shape:e,dtype:i,values:t,usage:vt.UPLOAD,refCount:1}),s}refCount(t){if(this.texData.has(t)){return this.texData.get(t).refCount}return 0}incRef(t){this.texData.get(t).refCount++}decRef(t){if(this.texData.has(t)){this.texData.get(t).refCount--}}move(t,e,i,s,o){if(we().getBool("DEBUG")&&this.checkNumericalProblems(e),"complex64"===s)throw new Error("Cannot write to a complex64 dtype. Please use tf.complex(real, imag).");this.texData.set(t,{shape:i,dtype:s,values:e,usage:vt.UPLOAD,refCount:o})}disposeIntermediateTensorInfo(t){this.disposeData(t.dataId)}readSync(t){const e=this.texData.get(t),{values:i,dtype:s,complexTensorInfos:o,slice:r,shape:u,isPacked:a}=e;if(null!=r){let e;e=a?new Rw(u,Gw):new bw(u,Gw);const i=this.runWebGLProgram(e,[{dataId:t,shape:u,dtype:s}],s),o=this.readSync(i.dataId);return this.disposeIntermediateTensorInfo(i),o}if(null!=i)return this.convertAndCacheOnCPU(t);if("string"===s)return i;const n=null!=this.activeTimers;let L,M;if(n&&(L=Si()),"complex64"===s){const t=this.readSync(o.real.dataId),e=this.readSync(o.imag.dataId);M=mergeRealAndImagArrays(t,e)}else M=this.getValuesFromTexture(t);return n&&(this.downloadWaitMs+=Si()-L),this.convertAndCacheOnCPU(t,M)}async read(t){if(this.pendingRead.has(t)){const e=this.pendingRead.get(t);return new Promise((t=>e.push(t)))}const e=this.texData.get(t),{values:i,shape:s,slice:o,dtype:r,complexTensorInfos:u,isPacked:a}=e;if(null!=o){let e;e=a?new Rw(s,Gw):new bw(s,Gw);const i=this.runWebGLProgram(e,[{dataId:t,shape:s,dtype:r}],r),o=this.read(i.dataId);return this.disposeIntermediateTensorInfo(i),o}if(null!=i)return this.convertAndCacheOnCPU(t);if(we().getBool("DEBUG")&&!we().getBool("WEBGL_DOWNLOAD_FLOAT_ENABLED")&&2===we().getNumber("WEBGL_VERSION"))throw new Error("tensor.data() with WEBGL_DOWNLOAD_FLOAT_ENABLED=false and WEBGL_VERSION=2 not yet supported.");let n,L,M=null;if("complex64"!==r&&we().get("WEBGL_BUFFER_SUPPORTED")){n=this.decode(t);const e=this.texData.get(n.dataId);M=this.gpgpu.createBufferFromTexture(e.texture.texture,...uL(s))}if(this.pendingRead.set(t,[]),"complex64"!==r&&await this.gpgpu.createAndWaitForFence(),"complex64"===r){const t=await Promise.all([this.read(u.real.dataId),this.read(u.imag.dataId)]),e=t[0],i=t[1];L=mergeRealAndImagArrays(e,i)}else if(null==M)L=this.getValuesFromTexture(t);else{const t=bt(s);L=this.gpgpu.downloadFloat32MatrixFromBuffer(M,t)}if(null!=n&&this.disposeIntermediateTensorInfo(n),null!=M){const t=this.gpgpu.gl;LL(t,(()=>t.deleteBuffer(M)))}const C=this.convertAndCacheOnCPU(t,L),w=this.pendingRead.get(t);return this.pendingRead.delete(t),w.forEach((t=>t(C))),this.pendingDisposal.has(t)&&(this.pendingDisposal.delete(t),this.disposeData(t)&&Ko().removeDataId(t,this),this.pendingDeletes--),C}readToGPU(t,e={}){const i=this.texData.get(t),{values:s,shape:o,slice:r,dtype:u,isPacked:a,texture:n}=i;if("complex64"===u)throw new Error("Does not support reading texture for complex64 dtype.");if(null!=r){let i;i=a?new Rw(o,Gw):new bw(o,Gw);const s=this.runWebGLProgram(i,[{dataId:t,shape:o,dtype:u}],u),r=this.readToGPU(s,e);return this.disposeIntermediateTensorInfo(s),r}if(null==n)throw null!=s?new Error("Data is not on GPU but on CPU."):new Error("There is no data on GPU or CPU.");const L=this.decode(t,e.customTexShape),M=Ko().makeTensorFromTensorInfo(L),C=this.texData.get(L.dataId);return Object.assign({tensorRef:M},C.texture)}bufferSync(t){const e=this.readSync(t.dataId);if("string"===t.dtype)try{const i=e.map((t=>decodeString(t)));return io(t.shape,t.dtype,i)}catch(t){throw new Error("Failed to decode encoded string bytes into utf-8")}return io(t.shape,t.dtype,e)}checkNumericalProblems(t){if(null!=t)for(let e=0;e<t.length;e++){const i=t[e];if(!canBeRepresented(i)){if(we().getBool("WEBGL_RENDER_FLOAT32_CAPABLE"))throw Error(`The value ${i} cannot be represented with your current settings. Consider enabling float32 rendering: 'tf.env().set('WEBGL_RENDER_FLOAT32_ENABLED', true);'`);throw Error(`The value ${i} cannot be represented on this device.`)}}}getValuesFromTexture(t){const{shape:e,dtype:i,isPacked:s}=this.texData.get(t),o=bt(e);if(we().getBool("WEBGL_DOWNLOAD_FLOAT_ENABLED")){const i=this.decode(t),s=this.texData.get(i.dataId),r=this.gpgpu.downloadMatrixFromPackedTexture(s.texture.texture,...uL(e)).subarray(0,o);return this.disposeIntermediateTensorInfo(i),r}const r=we().getBool("WEBGL_PACK")&&!0===s,u=r?dL(e):e,a=r?new SM(u):new TM(u),n=this.runWebGLProgram(a,[{shape:u,dtype:i,dataId:t}],"float32"),L=this.texData.get(n.dataId),M=this.gpgpu.downloadByteEncodedFloatMatrixFromOutputTexture(L.texture.texture,L.texShape[0],L.texShape[1]).subarray(0,o);return this.disposeIntermediateTensorInfo(n),M}timerAvailable(){return we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE")>0}time(t){const e=this.activeTimers,i=[];let s=!1;null==this.programTimersStack?(this.programTimersStack=i,s=!0):this.activeTimers.push(i),this.activeTimers=i,t();const o=Qt(this.activeTimers.map((t=>t.query))).filter((t=>null!=t)),r=Qt(this.activeTimers.map((t=>t.name))).filter((t=>null!=t));this.activeTimers=e,s&&(this.programTimersStack=null);const u={uploadWaitMs:this.uploadWaitMs,downloadWaitMs:this.downloadWaitMs,kernelMs:null,wallMs:null};return(async()=>{if(we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE")>0){const t=await Promise.all(o);u.kernelMs=dt(t),u.getExtraProfileInfo=()=>t.map(((t,e)=>({name:r[e],ms:t}))).map((t=>`${t.name}: ${t.ms}`)).join(", ")}else u.kernelMs={error:"WebGL query timers are not supported in this environment."};return this.uploadWaitMs=0,this.downloadWaitMs=0,u})()}memory(){return{unreliable:!1,numBytesInGPU:this.numBytesInGPU,numBytesInGPUAllocated:this.textureManager.numBytesAllocated,numBytesInGPUFree:this.textureManager.numBytesFree}}startTimer(){return we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE")>0?this.gpgpu.beginQuery():{startMs:Si(),endMs:null}}endTimer(t){return we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE")>0?(this.gpgpu.endQuery(),t):(t.endMs=Si(),t)}async getQueryTime(t){if(we().getNumber("WEBGL_DISJOINT_QUERY_TIMER_EXTENSION_RELIABLE")>0)return this.gpgpu.waitForQueryAndGetTime(t);const e=t;return e.endMs-e.startMs}disposeData(t,e=!1){if(this.pendingDisposal.has(t))return!1;if(!this.texData.has(t))return!0;if(e?this.texData.get(t).refCount=0:this.texData.get(t).refCount--,!e&&this.texData.get(t).refCount>0)return!1;if(this.pendingRead.has(t))return this.pendingDisposal.add(t),this.pendingDeletes++,!1;this.releaseGPUData(t);const{complexTensorInfos:i}=this.texData.get(t);return null!=i&&(this.disposeData(i.real.dataId,e),this.disposeData(i.imag.dataId,e)),this.texData.delete(t),!0}releaseGPUData(t){const{texture:e,dtype:i,texShape:s,usage:o,isPacked:r,slice:u}=this.texData.get(t),a=u&&u.origDataId||t,n=this.dataRefCount.get(a);n>1?this.dataRefCount.set(a,n-1):(this.dataRefCount.delete(a),null!=e&&(this.numBytesInGPU-=this.computeBytes(s,i),this.textureManager.releaseTexture(e,s,o,r)));const L=this.texData.get(t);L.texture=null,L.texShape=null,L.isPacked=!1,L.slice=null}getTexture(t){return this.uploadToGPU(t),this.texData.get(t).texture.texture}getDataInfo(t){return this.texData.get(t)}shouldExecuteOnCPU(t,e=$w){return we().getBool("WEBGL_CPU_FORWARD")&&t.every((t=>null==this.texData.get(t.dataId).texture&&bt(t.shape)<e))}getGPGPUContext(){return this.gpgpu}where(t){warn("tf.where() in webgl locks the UI thread. Call tf.whereAsync() instead");const e=t.dataSync();return whereImpl(t.shape,e)}packedUnaryOp(t,e,i){const s=new Rw(t.shape,e),o=this.compileAndRun(s,[t],i);return Ko().makeTensorFromTensorInfo(o)}abs(t){if(this.shouldExecuteOnCPU([t])&&"complex64"!==t.dtype){const e=rw(this.texData.get(t.dataId).values);return this.makeOutput(t.shape,t.dtype,e)}if(we().getBool("WEBGL_PACK_UNARY_OPERATIONS"))return this.packedUnaryOp(t,Sw,t.dtype);const e=new bw(t.shape,Sw),i=this.compileAndRun(e,[t]);return Ko().makeTensorFromTensorInfo(i)}makeTensorInfo(t,e,i){let s;if("string"===e&&null!=i&&i.length>0&&isString(i[0])){const o=i.map((t=>encodeString(t)));s=this.write(o,t,e)}else s=this.write(i,t,e);return this.texData.get(s).usage=null,{dataId:s,shape:t,dtype:e}}makeOutput(t,e,i){return Ko().makeTensorFromTensorInfo(this.makeTensorInfo(t,e,i),this)}unpackTensor(t){const e=new Hw(t.shape);return this.runWebGLProgram(e,[t],t.dtype)}packTensor(t){const e=new mw(t.shape);return this.runWebGLProgram(e,[t],t.dtype,null,!0)}packedReshape(t,e){const i=[zL(t.shape),...xL(t.shape)],s={dtype:t.dtype,shape:i,dataId:t.dataId},o=[zL(e),...xL(e)],r=new hw(o,i),u=[i],a=this.runWebGLProgram(r,[s],t.dtype,u,!0);return{dataId:a.dataId,shape:e,dtype:a.dtype}}decode(t,e){const i=this.texData.get(t),{isPacked:s,shape:o,dtype:r}=i;if(null!=e){Kt(bt(o)<=e[0]*e[1]*4,(()=>"customTexShape is too small. Row * Column * 4 should be equal or larger than the size of the tensor data."))}const u=dL(o);let a;a=s?new EM(u):new bM(u);const n=[null!=e?e:uL(u)];return{dtype:r,shape:o,dataId:this.runWebGLProgram(a,[{shape:u,dtype:r,dataId:t}],r,n,!0,e).dataId}}runWebGLProgram(t,e,i,s,o=!1,r){const u=this.makeTensorInfo(t.outputShape,i),a=this.texData.get(u.dataId);if(t.packedOutput&&(a.isPacked=!0),t.outPackingScheme===yt.DENSE){const e=null!=r?r:uL(t.outputShape);a.texShape=e.map((t=>2*t))}if(null!=t.outTexUsage&&(a.usage=t.outTexUsage),0===bt(u.shape))return a.values=Bt(u.dtype,0),u;const n=[],L=e.map((e=>{if("complex64"===e.dtype)throw new Error("GPGPUProgram does not support complex64 input. For complex64 dtypes, please separate the program into real and imaginary parts.");let i=this.texData.get(e.dataId);if(null==i.texture){if(!t.packedInputs&&bt(e.shape)<=we().getNumber("WEBGL_SIZE_UPLOAD_UNIFORM"))return{shape:e.shape,texData:null,isUniform:!0,uniformValues:i.values};t.packedInputs&&(i.isPacked=!0,i.shape=e.shape)}if(this.uploadToGPU(e.dataId),!!i.isPacked!=!!t.packedInputs)e=i.isPacked?this.unpackTensor(e):this.packTensor(e),n.push(e),i=this.texData.get(e.dataId);else if(i.isPacked&&!YL(i.shape,e.shape)){const t=e,s=e.shape;e.shape=i.shape,e=this.packedReshape(e,s),n.push(e),i=this.texData.get(e.dataId),t.shape=s}return{shape:e.shape,texData:i,isUniform:!1}}));this.uploadToGPU(u.dataId);const M={shape:u.shape,texData:a,isUniform:!1},C=YM(t,L,M),w=this.getAndSaveBinary(C,(()=>xM(this.gpgpu,t,L,M))),y=null!=this.activeTimers;let v;y&&(v=this.startTimer()),we().get("ENGINE_COMPILE_ONLY")||PM(this.gpgpu,w,L,M,s),n.forEach((t=>this.disposeIntermediateTensorInfo(t))),y&&(v=this.endTimer(v),this.activeTimers.push({name:t.constructor.name,query:this.getQueryTime(v)}));const D=we().get("WEBGL_FLUSH_THRESHOLD");if(D>0){const t=Si();t-this.lastGlFlushTime>D&&(this.gpgpu.gl.flush(),this.lastGlFlushTime=t)}if(!we().getBool("WEBGL_LAZILY_UNPACK")&&a.isPacked&&!1===o){const t=this.unpackTensor(u);return this.disposeIntermediateTensorInfo(u),t}return u}compileAndRun(t,e,i,s,o=!1){i=i||e[0].dtype;return this.runWebGLProgram(t,e,i,s,o)}getAndSaveBinary(t,e){return t in this.binaryCache||(this.binaryCache[t]=e()),this.binaryCache[t]}getTextureManager(){return this.textureManager}dispose(){if(!this.disposed){if(!we().getBool("IS_TEST")){Object.keys(this.binaryCache).forEach((t=>{this.gpgpu.deleteProgram(this.binaryCache[t].webGLProgram),delete this.binaryCache[t]}))}this.textureManager.dispose(),null!=this.canvas&&"undefined"!=typeof HTMLCanvasElement&&this.canvas instanceof HTMLCanvasElement?this.canvas.remove():this.canvas=null,this.gpgpuCreatedLocally&&(this.gpgpu.program=null,this.gpgpu.dispose()),this.disposed=!0}}floatPrecision(){return null==this.floatPrecisionValue&&(this.floatPrecisionValue=Po((()=>{if(!we().get("WEBGL_RENDER_FLOAT32_ENABLED")){const t=we().getBool("DEBUG");we().set("DEBUG",!1);const e=this.abs(Sr(1e-8)).dataSync()[0];if(we().set("DEBUG",t),e>0)return 32}return 16}))),this.floatPrecisionValue}epsilon(){return 32===this.floatPrecision()?Vw:Zw}uploadToGPU(t){const e=this.texData.get(t),{shape:i,dtype:s,values:o,texture:r,usage:u,isPacked:a}=e;if(null!=r)return;const n=null!=this.activeTimers;let L;n&&(L=Si());let M=e.texShape;if(null==M&&(M=KL(i,a),e.texShape=M),null!=o){const t=dL(i);let r,u=M[1],C=M[0];const w=o instanceof Uint8Array||o instanceof Uint8ClampedArray;!a&&w||([u,C]=aL(M[0],M[1])),r=a?new qM(t,w):new fM(t,w);const y=w?[C,u]:M,v=this.makeTensorInfo(y,s),D=this.texData.get(v.dataId);D.usage=w?vt.PIXELS:vt.UPLOAD,D.texShape=y,this.gpgpu.uploadDenseMatrixToTexture(this.getTexture(v.dataId),u,C,o);const l=[[C,u]],g=!0,p=this.runWebGLProgram(r,[v],s,l,g),j=this.texData.get(p.dataId);e.texShape=j.texShape,e.isPacked=j.isPacked,e.usage=j.usage,we().get("ENGINE_COMPILE_ONLY")?this.disposeData(p.dataId):(e.texture=j.texture,e.values=null,this.texData.delete(p.dataId)),this.disposeIntermediateTensorInfo(v),n&&(this.uploadWaitMs+=Si()-L)}else{const t=this.acquireTexture(M,u,s,a);e.texture=t}}convertAndCacheOnCPU(t,e){const i=this.texData.get(t),{dtype:s}=i;return this.releaseGPUData(t),null!=e&&(i.values=iy(e,s)),i.values}acquireTexture(t,e,i,s){if(this.numBytesInGPU+=this.computeBytes(t,i),!this.warnedAboutMemory&&this.numBytesInGPU>1024*this.numMBBeforeWarning*1024){const t=(this.numBytesInGPU/1024/1024).toFixed(2);this.warnedAboutMemory=!0,console.warn(`High memory usage in GPU: ${t} MB, most likely due to a memory leak`)}return this.textureManager.acquireTexture(t,e,s)}computeBytes(t,e){return t[0]*t[1]*Rt(e)}checkCompileCompletion(){for(const[,t]of Object.entries(this.binaryCache))this.checkCompletion_(t)}async checkCompileCompletionAsync(){const t=[];if(this.gpgpu.parallelCompilationExtension){for(const[,e]of Object.entries(this.binaryCache))t.push(this.checkCompletionAsync_(e));return Promise.all(t)}for(const[,e]of Object.entries(this.binaryCache)){const i=new Promise((t=>{try{this.checkCompletion_(e),t(!0)}catch(t){throw t}}));t.push(i)}return Promise.all(t)}async checkCompletionAsync_(t){return this.gpgpu.gl.getProgramParameter(t.webGLProgram,this.gpgpu.parallelCompilationExtension.COMPLETION_STATUS_KHR)?this.checkCompletion_(t):(await nextFrame(),this.checkCompletionAsync_(t))}checkCompletion_(t){if(!1===this.gpgpu.gl.getProgramParameter(t.webGLProgram,this.gpgpu.gl.LINK_STATUS)){if(console.log(this.gpgpu.gl.getProgramInfoLog(t.webGLProgram)),!1===this.gpgpu.gl.getShaderParameter(t.fragmentShader,this.gpgpu.gl.COMPILE_STATUS))throw logShaderSourceAndInfoLog(t.source,this.gpgpu.gl.getShaderInfoLog(t.fragmentShader)),new Error("Failed to compile fragment shader.");throw new Error("Failed to link vertex and fragment shaders.")}return!0}getUniformLocations(){for(const[,t]of Object.entries(this.binaryCache)){const{uniformLocations:e,customUniformLocations:i,infLoc:s,nanLoc:o,inShapesLocations:r,inTexShapesLocations:u,outShapeLocation:a,outShapeStridesLocation:n,outTexShapeLocation:L}=dM(this.gpgpu,t.program,t.webGLProgram);t.uniformLocations=e,t.customUniformLocations=i,t.infLoc=s,t.nanLoc=o,t.inShapesLocations=r,t.inTexShapesLocations=u,t.outShapeLocation=a,t.outShapeStridesLocation=n,t.outTexShapeLocation=L}}}function iy(t,e){if("float32"===e||"complex64"===e)return t;if("int32"===e||"bool"===e){const i="int32"===e?new Int32Array(t.length):new Uint8Array(t.length);for(let e=0;e<i.length;++e)i[e]=Math.round(t[e]);return i}throw new Error(`Unknown dtype ${e}`)}ey.nextDataId=0,Ls()&&bo("webgl",(()=>new ey),2);class sy{constructor(t,e,i){this.variableNames=["A","B"],this.outputShape=Go(e,i),this.enableShapeUniforms=QM(this.outputShape.length),this.userCode=`\n      float binaryOperation(float a, float b) {\n        ${t}\n      }\n\n      void main() {\n        float a = getAAtOutCoords();\n        float b = getBAtOutCoords();\n        setOutput(binaryOperation(a, b));\n      }\n    `}}const oy="\n  result.r = isNaN.r > 0. ? NAN : result.r;\n  result.g = isNaN.g > 0. ? NAN : result.g;\n  result.b = isNaN.b > 0. ? NAN : result.b;\n  result.a = isNaN.a > 0. ? NAN : result.a;\n";class ry{constructor(t,e,i,s=!1){this.variableNames=["A","B"],this.supportsBroadcasting=!0,this.packedInputs=!0,this.packedOutput=!0,this.outputShape=Go(e,i);const o=this.outputShape.length;this.enableShapeUniforms=QM(o);let r="";if(s)if(0===o||1===bt(this.outputShape))r="\n          result.y = 0.;\n          result.z = 0.;\n          result.w = 0.;\n        ";else{if(r=`\n          ${mM(o)} coords = getOutputCoords();\n        `,1===o)this.enableShapeUniforms?r+="\n            result.y = (coords + 1) >= outShape ? 0. : result.y;\n            result.z = 0.;\n            result.w = 0.;\n          ":r+=`\n            result.y = (coords + 1) >= ${this.outputShape[0]} ? 0. : result.y;\n            result.z = 0.;\n            result.w = 0.;\n          `;else{const t=cw("coords",o);this.enableShapeUniforms?r+=`\n            bool nextRowOutOfBounds =\n              (${t[o-2]} + 1) >= outShape[${o} - 2];\n            bool nextColOutOfBounds =\n              (${t[o-1]} + 1) >= outShape[${o} - 1];\n            result.y = nextColOutOfBounds ? 0. : result.y;\n            result.z = nextRowOutOfBounds ? 0. : result.z;\n            result.w = nextColOutOfBounds || nextRowOutOfBounds ? 0. : result.w;\n          `:r+=`\n            bool nextRowOutOfBounds =\n              (${t[o-2]} + 1) >= ${this.outputShape[o-2]};\n            bool nextColOutOfBounds =\n              (${t[o-1]} + 1) >= ${this.outputShape[o-1]};\n            result.y = nextColOutOfBounds ? 0. : result.y;\n            result.z = nextRowOutOfBounds ? 0. : result.z;\n            result.w = nextColOutOfBounds || nextRowOutOfBounds ? 0. : result.w;\n          `}}this.userCode=`\n      vec4 binaryOperation(vec4 a, vec4 b) {\n        ${t}\n      }\n\n      void main() {\n        vec4 a = getAAtOutCoords();\n        vec4 b = getBAtOutCoords();\n\n        vec4 result = binaryOperation(a, b);\n        ${r}\n\n        setOutput(result);\n      }\n    `}}function uy(t){const{inputs:e,backend:i}=t,{x:s}=e;return i.incRef(s.dataId),{dataId:s.dataId,shape:s.shape,dtype:s.dtype}}const ay={kernelName:qe,backendName:"webgl",kernelFunc:uy};function ny(t){const{inputs:e,backend:i}=t,{real:s,imag:o}=e,r=i.makeTensorInfo(s.shape,"complex64"),u=i.texData.get(r.dataId),a=uy({inputs:{x:s},backend:i}),n=uy({inputs:{x:o},backend:i});return u.complexTensorInfos={real:a,imag:n},r}const Ly="return (a < 0.) ? b * a : a;",My="\n  vec4 aLessThanZero = vec4(lessThan(a, vec4(0.)));\n  return (aLessThanZero * (b * a)) + ((vec4(1.0) - aLessThanZero) * a);\n",Cy="return (a < 0.) ? b * a : a;",wy="\n  vec4 aLessThanZero = vec4(lessThan(a, vec4(0.)));\n  return (aLessThanZero * (b * a)) + ((vec4(1.0) - aLessThanZero) * a);\n",yy="if (isnan(x)) return x;";function vy({opSnippet:t,packedOpSnippet:e,cpuKernelImpl:i,dtype:s}){return({inputs:o,backend:r})=>{const{x:u}=o,a=r,n=s||u.dtype;if(a.shouldExecuteOnCPU([u])&&null!=i){const t=a.texData.get(u.dataId),e=i(t.values,n);return a.makeTensorInfo(u.shape,n,e)}let L;return L=we().getBool("WEBGL_PACK_UNARY_OPERATIONS")&&null!=e?new Rw(u.shape,e):new bw(u.shape,t),a.runWebGLProgram(L,[u],n)}}function Dy({opSnippet:t,packedOpSnippet:e,checkOutOfBounds:i=!1,supportsComplex:s=!1,cpuKernelImpl:o,dtype:r}){return({inputs:u,backend:a})=>{const{a:n,b:L}=u,M=a;if(s&&"complex64"===n.dtype){const e=M.texData.get(n.dataId),i=M.texData.get(L.dataId),[s,o]=[[e.complexTensorInfos.real,i.complexTensorInfos.real],[e.complexTensorInfos.imag,i.complexTensorInfos.imag]].map((e=>{const[i,s]=e,o={dataId:i.dataId,dtype:i.dtype,shape:n.shape},r={dataId:s.dataId,dtype:s.dtype,shape:L.shape},u=new sy(t,n.shape,L.shape);return M.runWebGLProgram(u,[o,r],Vi(i.dtype,s.dtype))})),r=ny({inputs:{real:s,imag:o},backend:M});return M.disposeIntermediateTensorInfo(s),M.disposeIntermediateTensorInfo(o),r}const C=r||Vi(n.dtype,L.dtype);if(("string"===n.dtype||"string"===L.dtype||M.shouldExecuteOnCPU([n,L]))&&null!=o){const t=M.texData.get(n.dataId).values,e=M.texData.get(L.dataId).values,i="string"===n.dtype?fromUint8ToStringArray(t):t,s="string"===n.dtype?fromUint8ToStringArray(e):e,[r,u]=o(n.shape,L.shape,i,s,C),a=M.makeTensorInfo(u,C);return M.texData.get(a.dataId).values=r,a}let w;return w=we().getBool("WEBGL_PACK_BINARY_OPERATIONS")&&null!=e?new ry(e,n.shape,L.shape,i):new sy(t,n.shape,L.shape),M.runWebGLProgram(w,[n,L],C)}}function ly(t,e=!1){if("linear"===t)return e?Bw:Tw;if("relu"===t)return e?Jw:qw;if("elu"===t)return e?Uw:fw;if("relu6"===t)return e?Ww:kw;if("prelu"===t)return e?wy:Cy;if("leakyrelu"===t)return e?My:Ly;if("sigmoid"===t)return e?Fw:Nw;throw new Error(`Activation ${t} has not been implemented for the WebGL backend.`)}const gy="return a + b;",py=Dy({opSnippet:gy,packedOpSnippet:gy,supportsComplex:!0,cpuKernelImpl:YC}),jy={kernelName:Ae,backendName:"webgl",kernelFunc:py};class Ay{constructor(t,e){this.variableNames=["x"];const{windowSize:i,batchSize:s,inSize:o,outSize:r}=t;this.outputShape=[s,r];const u=4*Math.floor(i/4),a=i%4;let n="sumValue += dot(values, ones);";if(null!=e){const t=1/e;n=`sumValue += dot(values * ${Tt(t)?t.toPrecision(2):t}, ones);`}let L="";o%i>0&&(L=`\n        if (inIdx < 0 || inIdx >= ${o}) {\n          return 0.0;\n        }\n      `),this.userCode=`\n      const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n      float getValue(int batch, int inIdx) {\n        ${L}\n        return getX(batch, inIdx);\n      }\n\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n        int outIdx = coords[1];\n        int inOffset = outIdx * ${i};\n\n        float sumValue = 0.0;\n\n        for (int i = 0; i < ${u}; i += 4) {\n          int inIdx = inOffset + i;\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            getValue(batch, inIdx + 3)\n          );\n\n          ${n}\n        }\n\n        int inIdx = inOffset + ${u};\n        if (${1===a}) {\n          vec4 values = vec4(getValue(batch, inIdx), 0.0, 0.0, 0.0);\n\n          ${n}\n        } else if (${2===a}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1), 0.0, 0.0);\n\n          ${n}\n        } else if (${3===a}) {\n          vec4 values = vec4(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2), 0.0);\n\n          ${n}\n        }\n        setOutput(sumValue);\n      }\n    `}}class cy{constructor(t,e){this.variableNames=["x"];const{windowSize:i,batchSize:s,inSize:o,outSize:r}=t;this.outputShape=[s,r];let u="0.0",a="";"prod"===e?u="1.0":"min"===e?(u="1.0 / 1e-20",a="min"):"max"===e&&(u="-1.0 / 1e-20",a="max");let n=`${e}(${e}(${e}(minMaxValue[0], minMaxValue[1]), minMaxValue[2]), minMaxValue[3])`;"sum"===e?n="sumValue":"prod"===e?n="prodValue":"all"===e?n="allValue":"any"===e&&(n="anyValue");const L=4*Math.floor(i/4),M=i%4;let C=`\n      if (${"sum"===e}) {\n        sumValue += dot(values, ones);\n      } else if (${"prod"===e}) {\n        vec2 tmp = vec2(values[0], values[1]) * vec2(values[2], values[3]);\n        prodValue *= tmp[0] * tmp[1];\n      } else {\n        minMaxValue = ${a}(values, minMaxValue);\n        if (${"min"===e} || ${"max"===e}) {\n          minMaxValue = ${a}(values, minMaxValue);\n          bvec4 isNaN = isnan(values);\n          if (isNaN.r || isNaN.g || isNaN.b || isNaN.a) {\n            minMaxValue = vec4(NAN);\n          }\n        }\n      }\n    `,w="vec4";"all"===e?(u="1.0",C="\n        bool reducedAllValue = all(values);\n        float floatedReducedAllValue = float(reducedAllValue);\n        allValue = float(allValue >= 1.0 && floatedReducedAllValue >= 1.0);\n      ",w="bvec4"):"any"===e&&(u="0.0",C="\n        bool reducedAnyValue = any(values);\n        float floatedReducedAnyValue = float(reducedAnyValue);\n        anyValue = float(anyValue >= 1.0 || floatedReducedAnyValue >= 1.0);\n      ",w="bvec4");let y="";o%i>0&&(y=`\n        if (inIdx < 0 || inIdx >= ${o}) {\n          return initializationValue;\n        }\n      `),this.userCode=`\n      const float initializationValue = ${u};\n      const vec4 ones = vec4(1.0, 1.0, 1.0, 1.0);\n\n      float getValue(int batch, int inIdx) {\n        ${y}\n        return getX(batch, inIdx);\n      }\n\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int batch = coords[0];\n        int outIdx = coords[1];\n        int inOffset = outIdx * ${i};\n\n        vec4 minMaxValue = vec4(${u});\n        float prodValue = 1.0;\n        float sumValue = 0.0;\n        float allValue = 1.0;\n        float anyValue = 0.0;\n\n        for (int i = 0; i < ${L}; i += 4) {\n          int inIdx = inOffset + i;\n          ${w} values = ${w}(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            getValue(batch, inIdx + 3)\n          );\n\n          ${C}\n        }\n\n        int inIdx = inOffset + ${L};\n        if (${1===M}) {\n          ${w} values = ${w}(\n            getValue(batch, inIdx),\n            initializationValue,\n            initializationValue,\n            initializationValue\n          );\n\n          ${C}\n        } else if (${2===M}) {\n          ${w} values = ${w}(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            initializationValue,\n            initializationValue\n          );\n\n          ${C}\n        } else if (${3===M}) {\n          ${w} values = ${w}(\n            getValue(batch, inIdx),\n            getValue(batch, inIdx + 1),\n            getValue(batch, inIdx + 2),\n            initializationValue\n          );\n\n          ${C}\n        }\n        setOutput(${n});\n      }\n    `}}function Iy(t){const e=[];for(;0===e.length||1!==e[e.length-1].outSize;){const i=e.length?e[e.length-1].outSize:t[1],s=va(i);e.push({inSize:i,windowSize:s,outSize:Math.ceil(i/s)})}return e}function my(t,e,i,s){const o=Iy(t.shape);let r=t;for(let u=0;u<o.length;u++){const{inSize:a,windowSize:n,outSize:L}=o[u];let M,C;M="mean"===i?0===u?new Ay({windowSize:n,inSize:a,batchSize:t.shape[0],outSize:L},a):new Ay({windowSize:n,inSize:a,batchSize:t.shape[0],outSize:L}):new cy({windowSize:n,inSize:a,batchSize:t.shape[0],outSize:L},i),C=r,r=s.runWebGLProgram(M,[r],e),C.dataId!==t.dataId&&s.disposeIntermediateTensorInfo(C)}return r}function hy(t,e,i){const s=[zL(t.shape),...xL(t.shape)],o={dtype:t.dtype,shape:s,dataId:t.dataId},r=[zL(e),...xL(e)],u=new hw(r,s),a=[s],n=i.runWebGLProgram(u,[o],t.dtype,a,!0);return{dataId:n.dataId,shape:e,dtype:n.dtype}}function Oy(t){const{inputs:e,backend:i,attrs:s}=t,{x:o}=e,{shape:r}=s,u=i,a=bt(o.shape),n=kt(r,a),L=bt(n);Kt(a===L,(()=>`The new shape (${n}) has ${L} elements and the old shape (${o.shape}) has ${a} elements. The new shape and old shape must have the same number of elements.`));const M=u.texData.get(o.dataId);return!M.isPacked||YL(o.shape,n)||null!==M.texture&&YL(M.shape,n)?(u.incRef(o.dataId),{dataId:o.dataId,shape:n,dtype:o.dtype}):hy(o,n,u)}const zy={kernelName:oi,backendName:"webgl",kernelFunc:Oy};class xy{constructor(t,e){this.variableNames=["A"];const i=new Array(t.length);for(let s=0;s<i.length;s++)i[s]=t[e[s]];this.outputShape=i,this.rank=i.length;const s=mM(this.rank),o=dy(e);this.userCode=`\n    void main() {\n      ${s} resRC = getOutputCoords();\n      setOutput(getA(${o}));\n    }\n    `}}function dy(t){const e=t.length;if(e>6)throw Error(`Transpose for rank ${e} is not yet supported`);const i=["resRC.x","resRC.y","resRC.z","resRC.w","resRC.u","resRC.v"],s=new Array(e);for(let e=0;e<t.length;e++)s[t[e]]=i[e];return s.join()}class Ky{constructor(t,e){this.variableNames=["A"],this.packedInputs=!0,this.packedOutput=!0;const i=new Array(t.length);for(let s=0;s<i.length;s++)i[s]=t[e[s]];if(this.outputShape=i,this.rank=i.length,this.rank>6)throw Error(`Packed transpose for rank ${this.rank} is not yet supported.`);const s=mM(this.rank),o=Aw("rc",this.rank),r=new Array(this.rank);for(let t=0;t<e.length;t++)r[e[t]]=o[t];const u=`vec2(${r.slice(-2).join()})`,a=`++${o[this.rank-1]} < ${i[this.rank-1]}`,n=`getChannel(getA(${r.join()}), ${u})`;this.userCode=`\n    void main() {\n      ${s} rc = getOutputCoords();\n      vec4 result = vec4(0.);\n      result[0] = ${n};\n      if(${a}) {\n        result[1] = ${n};\n      }\n      --${o[this.rank-1]};\n      if(++${o[this.rank-2]} < ${i[this.rank-2]}) {\n        result[2] = ${n};\n        if(${a}) {\n          result[3] = ${n};\n        }\n      }\n      setOutput(result);\n    }\n    `}}function Py(t,e,i){const s=we().getBool("WEBGL_PACK_ARRAY_OPERATIONS")?new Ky(t.shape,e):new xy(t.shape,e);return i.runWebGLProgram(s,[t],t.dtype)}function Yy(t,e,i,s){const o=e,r=t.shape.length,u=Gt(o,t.shape);let a=u;const n=Qr(a,r),L=null!=n;let M=t;L&&(M=Py(t,n,s),a=br(a.length,r)),Yr("sum",a,r);const[C,w]=Kr(M.shape,a);let y=C;i&&(y=Pr(C,u));const v=bt(w),D=Oy({inputs:{x:M},attrs:{shape:[bt(t.shape)/v,v]},backend:s}),l=my(D,Zi(t.dtype),"sum",s),g=Oy({inputs:{x:l},attrs:{shape:y},backend:s});return s.disposeIntermediateTensorInfo(D),s.disposeIntermediateTensorInfo(l),L&&s.disposeIntermediateTensorInfo(M),g}function Qy(t){const{inputs:e,backend:i,attrs:s}=t,{x:o}=e,{axis:r,keepDims:u}=s;return Yy(o,r,u,i)}const by={kernelName:Li,backendName:"webgl",kernelFunc:Qy},Ey={kernelName:$e,backendName:"webgl",kernelFunc:Dy({opSnippet:"\n  if(a < 0.0 && floor(b) < b){\n    return NAN;\n  }\n  if (b == 0.0) {\n    return 1.0;\n  }\n  return (round(mod(b, 2.0)) != 1) ?\n      pow(abs(a), b) : sign(a) * pow(abs(a), b);\n",packedOpSnippet:"\n  // isModRound1 has 1 for components with round(mod(b, 2.0)) == 1, 0 otherwise.\n  vec4 isModRound1 = vec4(equal(round(mod(b, 2.0)), ivec4(1)));\n  vec4 multiplier = sign(a) * isModRound1 + (vec4(1.0) - isModRound1);\n  vec4 result = multiplier * pow(abs(a), b);\n\n  // Ensure that a^0 = 1, including 0^0 = 1 as this correspond to TF and JS\n  bvec4 isExpZero = equal(b, vec4(0.0));\n  result.r = isExpZero.r ? 1.0 : result.r;\n  result.g = isExpZero.g ? 1.0 : result.g;\n  result.b = isExpZero.b ? 1.0 : result.b;\n  result.a = isExpZero.a ? 1.0 : result.a;\n\n  vec4 isNaN = vec4(lessThan(a, vec4(0.0))) * vec4(lessThan(floor(b), b));\n  "+oy+"\n  return result;\n"})};class Ty{constructor(t){this.outputShape=[],this.outputShape=wa(t,1),this.variableNames=t.map(((t,e)=>`T${e}`));const e=new Array(t.length-1);e[0]=t[0][1];for(let i=1;i<e.length;i++)e[i]=e[i-1]+t[i][1];const i=[`if (yC < ${e[0]}) setOutput(getT0(yR, yC));`];for(let t=1;t<e.length;t++){const s=e[t-1];i.push(`else if (yC < ${e[t]}) setOutput(getT${t}(yR, yC-${s}));`)}const s=e.length,o=e[e.length-1];i.push(`else setOutput(getT${s}(yR, yC-${o}));`),this.userCode=`\n      void main() {\n        ivec2 coords = getOutputCoords();\n        int yR = coords.x;\n        int yC = coords.y;\n\n        ${i.join("\n        ")}\n      }\n    `}}class Sy{constructor(t,e){this.packedInputs=!0,this.packedOutput=!0,this.outputShape=[],this.outputShape=wa(t,e);const i=this.outputShape,s=i.length,o=mM(s),r=cw("coords",s),u=["x","y","z","w","u","v"].slice(0,s);this.variableNames=t.map(((t,e)=>`T${e}`));const a=new Array(t.length-1);a[0]=t[0][e];for(let i=1;i<a.length;i++)a[i]=a[i-1]+t[i][e];const n=u[e],L=u.slice(-2),M=u.join();let C=`if (${n} < ${a[0]}) {\n        return getChannel(\n            getT0(${M}), vec2(${L.join()}));\n        }`;for(let t=1;t<a.length;t++){const e=a[t-1];C+=`\n        if (${n} < ${a[t]}  && ${n} >= ${a[t-1]}) {\n          return getChannel(\n            getT${t}(${fy(u,n,e)}),\n            vec2(${fy(L,n,e)}));\n        }`}const w=a.length,y=a[a.length-1];C+=`\n        return getChannel(\n          getT${w}(${fy(u,n,y)}),\n          vec2(${fy(L,n,y)}));`,this.userCode=`\n      float getValue(${u.map((t=>"int "+t))}) {\n        ${C}\n      }\n\n      void main() {\n        ${o} coords = getOutputCoords();\n        vec4 result = vec4(getValue(${r}), 0., 0., 0.);\n\n        ${r[s-1]} = ${r[s-1]} + 1;\n        if (${r[s-1]} < ${i[s-1]}) {\n          result.g = getValue(${r});\n        }\n\n        ${r[s-2]} = ${r[s-2]} + 1;\n        if (${r[s-2]} < ${i[s-2]}) {\n          result.a = getValue(${r});\n        }\n\n        ${r[s-1]} = ${r[s-1]} - 1;\n        if (${r[s-2]} < ${i[s-2]} &&\n            ${r[s-1]} < ${i[s-1]}) {\n          result.b = getValue(${r});\n        }\n        setOutput(result);\n      }\n    `}}function fy(t,e,i){const s=t.indexOf(e),o=t.map(((t,e)=>e===s?`${t} - ${i}`:t));return o.join()}function qy(t){const{inputs:e,backend:i}=t,{input:s}=e;return uy({inputs:{x:i.texData.get(s.dataId).complexTensorInfos.real},backend:i})}function ky(t,e,i){const s=t[0].dtype;if("complex64"===s){const s=t.map((t=>qy({inputs:{input:t},backend:i}))),o=t.map((t=>imag({inputs:{input:t},backend:i}))),r=ky(s,e,i),u=ky(o,e,i),a=ny({inputs:{real:r,imag:u},backend:i});return s.forEach((t=>i.disposeIntermediateTensorInfo(t))),o.forEach((t=>i.disposeIntermediateTensorInfo(t))),i.disposeIntermediateTensorInfo(r),i.disposeIntermediateTensorInfo(u),a}let o=i.shouldExecuteOnCPU(t);if("string"===s&&(o=!0),o){const o=t.map((t=>{const s=bt(t.shape.slice(e));return Oy({inputs:{x:t},backend:i,attrs:{shape:[-1,s]}})})),r=o.map((t=>({vals:i.readSync(t.dataId),shape:t.shape}))),u=wa(o.map((t=>t.shape)),1),a=1===o[0].shape[0],n=TC(r,u,s,a),L=wa(t.map((t=>t.shape)),e),M=i.makeTensorInfo(L,s,n);return o.forEach((t=>i.disposeIntermediateTensorInfo(t))),M}const r=we().getNumber("WEBGL_MAX_TEXTURES_IN_SHADER");if(t.length>r){const s=[];for(let o=0;o<t.length;o+=r){const u=t.slice(o,o+r);s.push(ky(u,e,i))}const o=ky(s,e,i);for(const t of s)i.disposeIntermediateTensorInfo(t);return o}if(we().getBool("WEBGL_PACK_ARRAY_OPERATIONS")&&t[0].shape.length>1){const o=new Sy(t.map((t=>t.shape)),e);return i.runWebGLProgram(o,t,s)}const{tensors2D:u,outShape:a}=computeTensors2D(t,e,i),n=new Ty(u.map((t=>t.shape))),L=i.runWebGLProgram(n,u,s);u.forEach((t=>i.disposeIntermediateTensorInfo(t)));const M=Oy({inputs:{x:L},attrs:{shape:a},backend:i});return i.disposeIntermediateTensorInfo(L),M}function Gy(t){const{inputs:e,backend:i,attrs:s}=t,{axis:o}=s,r=Gt(o,e[0].shape)[0],u=wa(e.map((t=>t.shape)),r);if(0===bt(u))return i.makeTensorInfo(u,e[0].dtype,[]);const a=e.filter((t=>bt(t.shape)>0));if(1===a.length)return uy({inputs:{x:a[0]},backend:i});const n=a.map((t=>t.shape));return Ca(n,r),ky(a,r,i)}const Ny={kernelName:ze,backendName:"webgl",kernelFunc:Gy};function By(t){const{inputs:e,attrs:i,backend:s}=t,{dim:o}=i,{input:r}=e,u=r.shape.length,a=r.shape.slice();let n=o;return o<0&&(Kt(-(u+1)<=o,(()=>`Axis must be in the interval [${-(u+1)}, ${u}]`)),n=u+o+1),a.splice(n,0,1),Oy({inputs:{x:r},backend:s,attrs:{shape:a}})}function Uy(t){const{inputs:e,backend:i,attrs:s}=t,{axis:o}=s;if(1===e.length)return By({inputs:{input:e[0]},backend:i,attrs:{dim:o}});const r=e[0].shape,u=e[0].dtype;e.forEach((t=>{Pt(r,t.shape,"All tensors passed to stack must have matching shapes"),Kt(u===t.dtype,(()=>"All tensors passed to stack must have matching dtypes"))}));const a=[],n=e.map((t=>{const e=By({inputs:{input:t},backend:i,attrs:{dim:o}});return a.push(e),e})),L=Gy({inputs:n,backend:i,attrs:{axis:o}});return a.forEach((t=>i.disposeIntermediateTensorInfo(t))),L}const Jy={kernelName:Xe,backendName:"webgl",kernelFunc:Uy},Wy=Dy({opSnippet:"return float(a != b);",cpuKernelImpl:$C,dtype:"bool"});function Fy(t){const{inputs:e,backend:i,attrs:s}=t,{x:o}=e,{dtype:r}=s;if("complex64"===r){if("complex64"===o.dtype)return uy({inputs:{x:o},backend:i});const t=yu(o.shape),e=Fy({inputs:{x:o},backend:i,attrs:{dtype:"float32"}}),s=ny({inputs:{real:e,imag:t},backend:i});return t.dispose(),i.disposeIntermediateTensorInfo(e),s}if("complex64"===o.dtype){const t=qy({inputs:{input:o},backend:i}),e=Fy({inputs:{x:t},backend:i,attrs:{dtype:r}});return i.disposeIntermediateTensorInfo(t),e}if(!Wt(o.dtype,r)){const t=uy({inputs:{x:o},backend:i});return{dataId:t.dataId,shape:t.shape,dtype:r}}if("int32"===r)return int(o,i);if("bool"===r){const t=i.makeTensorInfo([],"bool",Bt("bool",1)),e=Wy({inputs:{a:o,b:t},backend:i});return i.disposeIntermediateTensorInfo(t),e}throw new Error(`Error in Cast: failed to cast ${o.dtype} to ${r}`)}const Ry={kernelName:me,backendName:"webgl",kernelFunc:Fy},Hy=vy({opSnippet:Ew+"\n  return (x < 0.0) ? 0.0 : x;\n",packedOpSnippet:"\n  vec4 result = x * vec4(greaterThanEqual(x, vec4(0.0)));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n"}),Vy={kernelName:si,backendName:"webgl",kernelFunc:Hy};function Zy(t,e,i,s){const o=bt(e),r=Oy({inputs:{x:t},attrs:{shape:[bt(t.shape)/o,o]},backend:s}),u=my(r,"float32","mean",s),a=Oy({inputs:{x:u},attrs:{shape:i},backend:s});return s.disposeIntermediateTensorInfo(r),s.disposeIntermediateTensorInfo(u),a}const Xy={kernelName:We,backendName:"webgl",kernelFunc:({inputs:t,attrs:e,backend:i})=>{const{x:s}=t,{keepDims:o,axis:r}=e,u=i,a=s.shape.length,n=Gt(r,s.shape);let L=n;const M=Qr(L,a),C=null!=M,w=u.shouldExecuteOnCPU([s]),y=[];let v=s;if(C){if(w){const t=u.texData.get(v.dataId).values,e=new Array(a);for(let t=0;t<e.length;t++)e[t]=s.shape[M[t]];const i=pw(t,s.shape,s.dtype,M,e);v=u.makeTensorInfo(e,s.dtype);u.texData.get(v.dataId).values=i}else v=Py(s,M,u);y.push(v),L=br(L.length,a)}Yr("sum",L,a);const[D,l]=Kr(v.shape,L);let g=D;o&&(g=Pr(D,n));const p=Zy(v,l,g,u);for(const t of y)u.disposeIntermediateTensorInfo(t);return p}};function _y(t){const{inputs:e,backend:i,attrs:s}=t,{x:o}=e,{axis:r,keepDims:u}=s,a=o.shape.length,n=[],L=Gt(r,o.shape);let M=L;const C=Qr(M,a);let w,y=o;if(null!=C&&(y=transpose({inputs:{x:o},backend:i,attrs:{perm:C}}),M=br(M.length,a),n.push(y)),Yr("prod",M,a),i.shouldExecuteOnCPU([y])){const t=i.texData.get(y.dataId).values,{outVals:e,outShape:s,outDtype:o}=tw(y.shape,y.dtype,t,M);w=i.makeTensorInfo(s,o,e)}else{const[t,e]=Kr(y.shape,M),s=bt(e),r=Oy({inputs:{x:y},backend:i,attrs:{shape:[-1,s]}}),u=my(r,Zi(o.dtype),"prod",i);w=Oy({inputs:{x:u},backend:i,attrs:{shape:t}}),n.push(r),n.push(u)}if(u){n.push(w);const t=Pr(w.shape,L);w=Oy({inputs:{x:w},backend:i,attrs:{shape:t}})}return n.forEach((t=>i.disposeIntermediateTensorInfo(t))),w}const $y={kernelName:ti,backendName:"webgl",kernelFunc:_y};class tv{constructor(t,e,i){this.variableNames=["x"],this.customUniforms=[{name:"value",type:"float"}],this.outputShape=e.map(((e,i)=>e[0]+t[i]+e[1]));const s=t.length,o=mM(s),r=e.map((t=>t[0])).join(","),u=e.map(((e,i)=>e[0]+t[i])).join(","),a=["coords[0]","coords[1]","coords[2]","coords[3]"].slice(0,s);this.userCode=1!==s?`\n      ${o} start = ${o}(${r});\n      ${o} end = ${o}(${u});\n\n      void main() {\n        ${o} outC = getOutputCoords();\n        if (any(lessThan(outC, start)) || any(greaterThanEqual(outC, end))) {\n          setOutput(value);\n        } else {\n          ${o} coords = outC - start;\n          setOutput(getX(${a}));\n        }\n      }\n    `:`\n        int start = ${r};\n        int end = ${u};\n\n        void main() {\n          int outC = getOutputCoords();\n          if (outC < start || outC >= end) {\n            setOutput(value);\n          } else {\n            setOutput(getX(outC - start));\n          }\n        }\n      `}}class ev{constructor(t,e,i){this.variableNames=["x"],this.packedInputs=!0,this.packedOutput=!0,this.customUniforms=[{name:"value",type:"float"}],this.outputShape=e.map(((e,i)=>e[0]+t[i]+e[1]));const s=t.length,o=mM(s),r=e.map((t=>t[0])).join(","),u=e.map(((e,i)=>e[0]+t[i])).join(","),a=cw("rc",s),n=cw("source",s),L=`${a[s-1]} < ${this.outputShape[s-1]}`,M=1===s?"source":`vec2(${n.slice(-2).join()})`,C=[`${o} rc = outputLoc;`,`${a[s-1]} += 1;\n       if(${L}) {\n      `,1===s?"":`}\n       rc = outputLoc;\n       ${a[s-2]} += 1;\n       if(${a[s-2]} < ${this.outputShape[s-2]}) {`,1===s?"":`  ${a[s-1]} += 1;\n         if(${L}) {`],w=1===s?"rc < start || rc >= end":"any(lessThan(rc, start)) || any(greaterThanEqual(rc, end))";let y="";for(let t=0,e=1===s?2:4;t<e;t++)y+=`\n        ${C[t]}\n        if (${w}) {\n          result[${t}] = float(value);\n        } else {\n          ${o} source = rc - start;\n          result[${t}] = getChannel(getX(${n.join()}), ${M});\n        }\n      `;y+=1===s?"} ":"}}",this.userCode=`\n      const ${o} start = ${o}(${r});\n      const ${o} end = ${o}(${u});\n\n      void main() {\n        ${o} outputLoc = getOutputCoords();\n        vec4 result = vec4(0.);\n        ${y}\n        setOutput(result);\n      }\n    `}}const iv=t=>{const{inputs:e,backend:i,attrs:s}=t,{x:o}=e,{paddings:r,constantValue:u}=s;if(0===bt(o.shape)){const t=r.map(((t,e)=>t[0]+o.shape[e]+t[1]));return fill({backend:i,attrs:{shape:t,value:u,dtype:o.dtype}})}const a=we().getBool("WEBGL_PACK_ARRAY_OPERATIONS")?new ev(o.shape,r,u):new tv(o.shape,r,u),n=[[u]];return i.runWebGLProgram(a,[o],o.dtype,n)},sv={kernelName:_e,backendName:"webgl",kernelFunc:iv};class ov{constructor(t){this.variableNames=["source"],this.outputShape=t,this.rank=t.length;const e=mM(this.rank);this.customUniforms=[{name:"start",arrayIndex:this.rank,type:"int"}];const i=uv(this.rank);let s;const o=t.map(((t,e)=>`sourceLoc.${rv[e]} = start[${e}] + coords.${rv[e]};`));s=`\n        ${e} sourceLoc;\n        ${e} coords = getOutputCoords();\n        ${o.join("\n")}\n      `,this.userCode=`\n      void main() {\n        ${s}\n        setOutput(getSource(${i}));\n      }\n    `}}const rv=["x","y","z","w","u","v"];function uv(t){if(1===t)return"sourceLoc";if(t<=6)return rv.slice(0,t).map((t=>"sourceLoc."+t)).join(",");throw Error(`Slicing for rank ${t} is not yet supported`)}class av{constructor(t){this.variableNames=["source"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=t,this.rank=t.length,this.customUniforms=[{name:"start",arrayIndex:this.rank,type:"int"}];const e=mM(this.rank),i=cw("coords",this.rank),s=cw("sourceLoc",this.rank),o=1===this.rank?"sourceLoc":`vec2(${s.slice(-2).join()})`,r=`getChannel(getSource(${s.join()}), ${o})`,u=`\n      result.x = ${r};\n      if (++${i[this.rank-1]} < ${t[this.rank-1]}) {\n        ++${s[this.rank-1]};\n        result.y = ${r};\n        --${s[this.rank-1]};\n      }\n    `,a=1===this.rank?"":`\n      --${i[this.rank-1]};\n      if (++${i[this.rank-2]} < ${t[this.rank-2]}) {\n        ++${s[this.rank-2]};\n        result.z = ${r};\n        if (++${i[this.rank-1]} < ${t[this.rank-1]}) {\n          ++${s[this.rank-1]};\n          result.w = ${r};\n        }\n      }\n    `,n=this.rank<=4?`sourceLoc = coords +\n            ${e}(${t.map(((t,e)=>`start[${e}]`)).join()});`:t.map(((t,e)=>`${s[e]} = ${i[e]} + start[${e}];`)).join("\n");this.userCode=`\n      void main() {\n        ${e} coords = getOutputCoords();\n        ${e} sourceLoc;\n        ${n}\n        vec4 result = vec4(0.);\n        ${u}\n        ${a}\n        setOutput(result);\n      }\n    `}}function nv(t){const{inputs:e,backend:i,attrs:s}=t,{x:o}=e,{begin:r,size:u}=s,[a,n]=Wo(o,r,u);if(Bo(o,a,n),0===bt(n))return i.makeTensorInfo(n,o.dtype,[]);if(i.shouldExecuteOnCPU([o])||"string"===o.dtype){const t=i.texData.get(o.dataId),e=uw(t.values,a,n,o.shape,o.dtype);return i.makeTensorInfo(n,o.dtype,e)}const{isPacked:L}=i.texData.get(o.dataId),M=Uo(o.shape,a,n);if(L||!M){const t=we().getBool("WEBGL_PACK_ARRAY_OPERATIONS")?new av(n):new ov(n),e=[a];return i.runWebGLProgram(t,[o],o.dtype,e)}return i.uploadToGPU(o.dataId),shallowSlice(o,a,n,i)}function Lv(t){const{inputs:e,backend:i,attrs:s}=t,{value:o}=e;let{axis:r}=s;r<0&&(r+=o.shape.length);const u=o,a=u.shape.length,n=o.shape[r],L=new Array(a-1);let M=0;for(let t=0;t<a;t++)t!==r&&(L[M++]=u.shape[t]);const C=[],w=new Array(a).fill(0),y=u.shape.slice();y[r]=1;const v=new Array(n);for(let t=0;t<v.length;t++){w[r]=t;const e=nv({inputs:{x:u},backend:i,attrs:{begin:w,size:y}}),s=Oy({inputs:{x:e},backend:i,attrs:{shape:L}});v[t]=s,C.push(e)}return C.forEach((t=>i.disposeIntermediateTensorInfo(t))),v}const Mv={kernelName:yi,backendName:"webgl",kernelFunc:Lv},Cv={kernelName:ke,backendName:"webgl",kernelFunc:vy({opSnippet:"return float(!isnan(x) && !isinf(x));",dtype:"bool"})};class wv{constructor(t,e,i){let s,o;if(this.variableNames=["c","a","b"],this.outputShape=e,i>4)throw Error(`Where for rank ${i} is not yet supported`);if(1===i)o="resRC",s="resRC";else{const i=["resRC.x","resRC.y","resRC.z","resRC.w"],r=[],u=[];for(let s=0;s<e.length;s++)u.push(`${i[s]}`),s<t&&r.push(`${i[s]}`);s=r.join(),o=u.join()}const r=mM(i);this.userCode=`\n      void main() {\n        ${r} resRC = getOutputCoords();\n        float cVal = getC(${s});\n        if (cVal >= 1.0) {\n          setOutput(getA(${o}));\n        } else {\n          setOutput(getB(${o}));\n        }\n      }\n    `}}function yv(t){const{inputs:e,backend:i}=t,{condition:s,t:o,e:r}=e,u=new wv(s.shape.length,o.shape,o.shape.length);return i.runWebGLProgram(u,[s,o,r],Vi(o.dtype,r.dtype))}const vv={kernelName:ui,backendName:"webgl",kernelFunc:yv},Dv={REAL:"return areal * breal - aimag * bimag;",IMAG:"return areal * bimag + aimag * breal;"};class lv{constructor(t,e,i){this.variableNames=["AReal","AImag","BReal","BImag"],this.outputShape=Go(e,i),this.userCode=`\n      float binaryOpComplex(\n          float areal, float aimag, float breal, float bimag) {\n        ${t}\n      }\n\n      void main() {\n        float areal = getARealAtOutCoords();\n        float aimag = getAImagAtOutCoords();\n        float breal = getBRealAtOutCoords();\n        float bimag = getBImagAtOutCoords();\n        setOutput(binaryOpComplex(areal, aimag, breal, bimag));\n      }\n    `}}const gv="return a * b;";function pv(t){const{inputs:e,backend:i}=t,{a:s,b:o}=e,r=Vi(s.dtype,o.dtype);if("complex64"===s.dtype){const t=i.texData.get(s.dataId),e=i.texData.get(o.dataId),r=new lv(Dv.REAL,s.shape,o.shape),u=new lv(Dv.IMAG,s.shape,o.shape),a=[{dataId:t.complexTensorInfos.real.dataId,dtype:t.complexTensorInfos.real.dtype,shape:s.shape},{dataId:t.complexTensorInfos.imag.dataId,dtype:t.complexTensorInfos.imag.dtype,shape:s.shape},{dataId:e.complexTensorInfos.real.dataId,dtype:e.complexTensorInfos.real.dtype,shape:o.shape},{dataId:e.complexTensorInfos.imag.dataId,dtype:e.complexTensorInfos.imag.dtype,shape:o.shape}],n=i.runWebGLProgram(r,a,"float32"),L=i.runWebGLProgram(u,a,"float32"),M=ny({inputs:{real:n,imag:L},backend:i});return i.disposeIntermediateTensorInfo(n),i.disposeIntermediateTensorInfo(L),M}if(i.shouldExecuteOnCPU([s,o])){const t=i.texData.get(s.dataId),e=i.texData.get(o.dataId),[u,a]=XC(s.shape,o.shape,t.values,e.values,r),n=i.makeTensorInfo(a,r);return i.texData.get(n.dataId).values=u,n}let u;return u=we().getBool("WEBGL_PACK_BINARY_OPERATIONS")?new ry(gv,s.shape,o.shape):new sy(gv,s.shape,o.shape),i.runWebGLProgram(u,[s,o],r)}const jv={kernelName:Re,backendName:"webgl",kernelFunc:pv};class Av{constructor(t,e,i,s=!1,o=!1,r=!1,u=null,a=!1,n=!1){this.variableNames=["matrixA","matrixB"],this.packedInputs=!0,this.packedOutput=!0,this.outputShape=i,this.enableShapeUniforms=QM(this.outputShape.length);const L=s?t[1]:t[2],M=Math.ceil(L/2),C=s?"i * 2, rc.y":"rc.y, i * 2",w=o?"rc.z, i * 2":"i * 2, rc.z",y=s?["a.xxyy","a.zzww"]:["a.xxzz","a.yyww"],v=o?["b.xzxz","b.ywyw"]:["b.xyxy","b.zwzw"];let D="",l="";u&&(D=a?`vec4 activation(vec4 a) {\n          vec4 b = getPreluActivationWeightsAtOutCoords();\n          ${u}\n        }`:n?`vec4 activation(vec4 a) {\n          vec4 b = getLeakyreluAlphaAtOutCoords();\n          ${u}\n        }`:`vec4 activation(vec4 x) {\n          ${u}\n        }`,l="result = activation(result);");const g=r?"result += getBiasAtOutCoords();":"";r&&this.variableNames.push("bias"),a&&this.variableNames.push("preluActivationWeights"),n&&this.variableNames.push("leakyreluAlpha");let p="rc.x",j="rc.x";t[0]<e[0]?p=`int(min(float(rc.x), ${t[0]-1}.))`:e[0]<t[0]&&(j=`int(min(float(rc.x), ${e[0]-1}.))`),this.userCode=`\n      ${D}\n      // Don't use uniform for sharedDimensionPacked for performance.\n      const float sharedDimension = ${M}.0;\n\n      vec4 dot2x2ARowBCol(ivec3 rc) {\n        vec4 result = vec4(0);\n        for (int i = 0; i < ${M}; i++) {\n          int batchA = ${p};\n          int batchB = ${j};\n          vec4 a = getMatrixA(batchA, ${C});\n          vec4 b = getMatrixB(batchB, ${w});\n\n          // These swizzled products need to be separately added.\n          // See: https://github.com/tensorflow/tfjs/issues/1735\n          result += (${y[0]} * ${v[0]});\n          result += (${y[1]} * ${v[1]});\n        }\n        return result;\n      }\n\n      void main() {\n        ivec3 rc = getOutputCoords();\n        vec4 result = dot2x2ARowBCol(rc);\n\n        ${g}\n\n        ${l}\n\n        setOutput(result);\n      }\n    `}}const cv=1e3;function Iv({a:t,b:e,transposeA:i,transposeB:s,backend:o,bias:r=null,preluActivationWeights:u=null,leakyreluAlpha:a=0,activation:n=null}){const L=t.shape.length,M=e.shape.length,C=i?t.shape[L-2]:t.shape[L-1],w=s?e.shape[M-1]:e.shape[M-2],y=i?t.shape[L-1]:t.shape[L-2],v=s?e.shape[M-2]:e.shape[M-1],D=t.shape.slice(0,-2),l=e.shape.slice(0,-2),g=bt(D),p=bt(l),j=Go(t.shape.slice(0,-2),e.shape.slice(0,-2)).concat([y,v]);Kt(C===w,(()=>`Error in matMul: inner shapes (${C}) and (${w}) of Tensors with shapes ${t.shape} and ${e.shape} and transposeA=${i} and transposeB=${s} must match.`));const A=i?[g,C,y]:[g,y,C],c=s?[p,v,w]:[p,w,v],I=Oy({inputs:{x:t},backend:o,attrs:{shape:A}}),m=Oy({inputs:{x:e},backend:o,attrs:{shape:c}}),h=[I,m],O=Math.max(g,p),z=i?I.shape[1]:I.shape[2],x=null!=r,d=null!=u,K="leakyrelu"===n,P=null!=n?ly(n,!0):null;let Y;if((1===y||1===v)&&z>cv&&!1===(x||d||K||null!=P)){let t=I,e=m;i&&(t=transpose({inputs:{x:I},backend:o,attrs:{perm:[0,2,1]}}),h.push(t)),s&&(e=transpose({inputs:{x:m},backend:o,attrs:{perm:[0,2,1]}}),h.push(e));const r=1===v;let u=t;1!==v&&(u=Oy({inputs:{x:t},backend:o,attrs:{shape:[O,z,1]}}),h.push(u));const a=1===v?2:1;let n=e;r&&(n=Oy({inputs:{x:e},backend:o,attrs:{shape:[O,1,z]}}),h.push(n));const L=pv({inputs:{a:u,b:n},backend:o});Y=Qy({inputs:{x:L},backend:o,attrs:{axis:a,keepDims:!0}}),h.push(L)}else{const n=Vi(t.dtype,e.dtype),L=new Av(A,c,[O,y,v],i,s,x,P,d,K),M=[I,m];if(null!=r&&M.push(r),d&&M.push(u),K){const t=o.makeTensorInfo([],"float32",bi(a,"float32"));M.push(t),h.push(t)}Y=o.runWebGLProgram(L,M,n)}const Q=Oy({inputs:{x:Y},backend:o,attrs:{shape:j}});h.push(Y);for(const t of h)o.disposeIntermediateTensorInfo(t);return Q}function mv(t){const{inputs:e,backend:i,attrs:s}=t,{a:o,b:r}=e,{transposeA:u,transposeB:a}=s;return Iv({a:o,b:r,transposeA:u,transposeB:a,backend:i})}const hv={kernelName:ce,backendName:"webgl",kernelFunc:mv};class Ov{constructor(t,e){this.variableNames=["A","indices"],this.outputShape=e,this.rank=e.length;const i=mM(this.rank),s=zv(t);this.userCode=`\n      void main() {\n        ${i} resRC = getOutputCoords();\n        int index = int(getIndices(resRC.x, resRC.z));\n        float inBounds = (index >= 0) && (index < ${t[2]}) ? 1.0 : 0.0;\n        setOutput(inBounds * getA(${s}));\n      }\n    `}}function zv(t,e){const i=["resRC.x","resRC.y","resRC.z","resRC.w"],s=[];for(let e=0;e<t.length;e++)2===e?s.push("index"):s.push(`${i[e]}`);return s.join()}function xv(t){const{inputs:e,backend:i,attrs:s}=t,{x:o,indices:r}=e,{axis:u,batchDims:a}=s,n=Gt(u,o.shape)[0];if(we().get("DEBUG")){const t=i.readSync(r.dataId),e=o.shape[n];for(let i=0;i<t.length;++i){const s=t[i];Kt(s<=e-1&&s>=0,(()=>`GatherV2: the index value ${s} is not in [0, ${e-1}]`))}}const L=ma(o,r,n,a),M=bt(r.shape),C=[],w=Oy({inputs:{x:o},backend:i,attrs:{shape:[L.batchSize,L.outerSize,L.dimSize,L.sliceSize]}}),y=Oy({inputs:{x:r},backend:i,attrs:{shape:[L.batchSize,M/L.batchSize]}});C.push(w),C.push(y);const v=[L.batchSize,L.outerSize,M/L.batchSize,L.sliceSize];if(i.shouldExecuteOnCPU([o,r])||"string"===o.dtype){const t=i.bufferSync(y),e=i.bufferSync(w),s=NC(e,t,v);return C.forEach((t=>i.disposeIntermediateTensorInfo(t))),i.makeTensorInfo(L.outputShape,s.dtype,s.values)}const D=new Ov(w.shape,v),l=i.runWebGLProgram(D,[w,y],w.dtype);C.push(l);const g=Oy({inputs:{x:l},backend:i,attrs:{shape:L.outputShape}});return C.forEach((t=>i.disposeIntermediateTensorInfo(t))),g}const dv={kernelName:Se,backendName:"webgl",kernelFunc:xv},Kv=vy({opSnippet:yy+"\n  return 1.0 / (1.0 + exp(-1.0 * x));\n",packedOpSnippet:"\n  vec4 result = 1.0 / (1.0 + exp(-1.0 * x));\n  bvec4 isNaN = isnan(x);\n\n  result.r = isNaN.r ? x.r : result.r;\n  result.g = isNaN.g ? x.g : result.g;\n  result.b = isNaN.b ? x.b : result.b;\n  result.a = isNaN.a ? x.a : result.a;\n\n  return result;\n",cpuKernelImpl:ow}),Pv={kernelName:ni,backendName:"webgl",kernelFunc:Kv};function Yv(t){const{inputs:e,backend:i,attrs:s}=t,{a:o,b:r,bias:u,preluActivationWeights:a}=e,{transposeA:n,transposeB:L,activation:M,leakyreluAlpha:C}=s;return Iv({a:o,b:r,transposeA:n,transposeB:L,backend:i,bias:u,preluActivationWeights:a,leakyreluAlpha:C,activation:M})}const Qv={kernelName:Di,backendName:"webgl",kernelFunc:Yv};for(let TD of[jy,by,Ey,Jy,Ry,Vy,Xy,$y,sv,Mv,zy,Cv,ay,vv,jv,hv,dv,Ny,Pv,Qv])Ii(TD);var gt=Object.freeze({__proto__:null,cast:oo,enableProdMode:xo,env:we,loadGraphModel:_n,oneHot:zo,stack:Tu,sum:Gr,tensor:As,tidy:Po,unstack:ku,zeros:yu}),pt={format:"graph-model",generatedBy:"2.7.0",convertedBy:"TensorFlow.js Converter v3.7.0",signature:{inputs:{adjacency:{name:"adjacency:0",dtype:"DT_FLOAT",tensorShape:{dim:[{size:"-1"},{size:"200"},{size:"200"}]}},features:{name:"features:0",dtype:"DT_FLOAT",tensorShape:{dim:[{size:"-1"},{size:"200"},{size:"562"}]}}},outputs:{prediction:{name:"Identity:0",dtype:"DT_FLOAT",tensorShape:{dim:[{size:"-1"},{size:"2"}]}}}},modelTopology:{node:[{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/axes",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2_1/axis",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const_1",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/ReadVariableOp",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/free",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2/axis",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const_2",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/concat_1/axis",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/BiasAdd/ReadVariableOp",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/axes",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2_1/axis",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const_1",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/ReadVariableOp",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape/shape",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_1",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape/1",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape/2",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_3/shape",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_4",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape/1",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape/2",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/BiasAdd/ReadVariableOp",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_6/shape",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_7",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape/1",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape/2",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_9/shape",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_10",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape/shape",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_1",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"562"},{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_2/shape/1",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_2/shape/2",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_3/shape",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_4",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"562"},{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_5/shape/1",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_5/shape/2",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv/BiasAdd/ReadVariableOp",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_6/shape",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_7",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"562"},{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_8/shape/1",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_8/shape/2",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_9/shape",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_10",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"562"},{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_11/shape/1",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_11/shape/2",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/BiasAdd_1/ReadVariableOp",op:"Const",attr:{dtype:{type:"DT_FLOAT"},value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"}]}}}}},{name:"StatefulPartitionedCall/model/arma_conv/Mean/reduction_indices",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape/1",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape/2",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/BiasAdd_1/ReadVariableOp",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Mean/reduction_indices",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/free",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"2"}]}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2/axis",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const_2",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{dim:[{size:"1"}]}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/concat_1/axis",op:"Const",attr:{dtype:{type:"DT_INT32"},value:{tensor:{dtype:"DT_INT32",tensorShape:{}}}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/BiasAdd/ReadVariableOp",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/Sum/reduction_indices",op:"Const",attr:{value:{tensor:{dtype:"DT_INT32",tensorShape:{}}},dtype:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/prediction/MatMul/ReadVariableOp",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"64"},{size:"2"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/prediction/BiasAdd/ReadVariableOp",op:"Const",attr:{value:{tensor:{dtype:"DT_FLOAT",tensorShape:{dim:[{size:"2"}]}}},dtype:{type:"DT_FLOAT"}}},{name:"adjacency",op:"Placeholder",attr:{dtype:{type:"DT_FLOAT"},shape:{shape:{dim:[{size:"-1"},{size:"200"},{size:"200"}]}}}},{name:"features",op:"Placeholder",attr:{dtype:{type:"DT_FLOAT"},shape:{shape:{dim:[{size:"-1"},{size:"200"},{size:"562"}]}}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape",op:"Reshape",input:["features","StatefulPartitionedCall/model/arma_conv/Reshape/shape"],attr:{Tshape:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Shape",op:"Shape",input:["features"],attr:{T:{type:"DT_FLOAT"},out_type:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_3",op:"Reshape",input:["features","StatefulPartitionedCall/model/arma_conv/Reshape_3/shape"],attr:{Tshape:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Shape_2",op:"Shape",input:["features"],attr:{T:{type:"DT_FLOAT"},out_type:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_6",op:"Reshape",input:["features","StatefulPartitionedCall/model/arma_conv/Reshape_6/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Shape_4",op:"Shape",input:["features"],attr:{out_type:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_9",op:"Reshape",input:["features","StatefulPartitionedCall/model/arma_conv/Reshape_9/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Shape_6",op:"Shape",input:["features"],attr:{out_type:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/MatMul",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv/Reshape","StatefulPartitionedCall/model/arma_conv/Reshape_1"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_b:{b:!1},transpose_a:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/unstack",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv/Shape"],attr:{axis:{i:"0"},num:{i:"3"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/MatMul_2",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv/Reshape_3","StatefulPartitionedCall/model/arma_conv/Reshape_4"],device:"/device:CPU:0",attr:{transpose_b:{b:!1},T:{type:"DT_FLOAT"},transpose_a:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/unstack_2",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv/Shape_2"],attr:{num:{i:"3"},axis:{i:"0"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/MatMul_3",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv/Reshape_6","StatefulPartitionedCall/model/arma_conv/Reshape_7"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_a:{b:!1},transpose_b:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/unstack_4",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv/Shape_4"],attr:{T:{type:"DT_INT32"},num:{i:"3"},axis:{i:"0"}}},{name:"StatefulPartitionedCall/model/arma_conv/MatMul_5",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv/Reshape_9","StatefulPartitionedCall/model/arma_conv/Reshape_10"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_b:{b:!1},transpose_a:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/unstack_6",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv/Shape_6"],attr:{T:{type:"DT_INT32"},axis:{i:"0"},num:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_2/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv/unstack","StatefulPartitionedCall/model/arma_conv/Reshape_2/shape/1","StatefulPartitionedCall/model/arma_conv/Reshape_2/shape/2"],attr:{axis:{i:"0"},T:{type:"DT_INT32"},N:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_5/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv/unstack_2","StatefulPartitionedCall/model/arma_conv/Reshape_5/shape/1","StatefulPartitionedCall/model/arma_conv/Reshape_5/shape/2"],attr:{axis:{i:"0"},T:{type:"DT_INT32"},N:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_8/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv/unstack_4","StatefulPartitionedCall/model/arma_conv/Reshape_8/shape/1","StatefulPartitionedCall/model/arma_conv/Reshape_8/shape/2"],attr:{T:{type:"DT_INT32"},N:{i:"3"},axis:{i:"0"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_11/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv/unstack_6","StatefulPartitionedCall/model/arma_conv/Reshape_11/shape/1","StatefulPartitionedCall/model/arma_conv/Reshape_11/shape/2"],attr:{N:{i:"3"},T:{type:"DT_INT32"},axis:{i:"0"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_2",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/MatMul","StatefulPartitionedCall/model/arma_conv/Reshape_2/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_5",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/MatMul_2","StatefulPartitionedCall/model/arma_conv/Reshape_5/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_8",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/MatMul_3","StatefulPartitionedCall/model/arma_conv/Reshape_8/shape"],attr:{Tshape:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_11",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/MatMul_5","StatefulPartitionedCall/model/arma_conv/Reshape_11/shape"],attr:{Tshape:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/MatMul_1",op:"BatchMatMulV2",input:["adjacency","StatefulPartitionedCall/model/arma_conv/Reshape_2"],attr:{T:{type:"DT_FLOAT"},adj_y:{b:!1},adj_x:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/MatMul_4",op:"BatchMatMulV2",input:["adjacency","StatefulPartitionedCall/model/arma_conv/Reshape_8"],attr:{T:{type:"DT_FLOAT"},adj_x:{b:!1},adj_y:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/add",op:"AddV2",input:["StatefulPartitionedCall/model/arma_conv/MatMul_1","StatefulPartitionedCall/model/arma_conv/Reshape_5"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/add_1",op:"AddV2",input:["StatefulPartitionedCall/model/arma_conv/MatMul_4","StatefulPartitionedCall/model/arma_conv/Reshape_11"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/BiasAdd",op:"BiasAdd",input:["StatefulPartitionedCall/model/arma_conv/add","StatefulPartitionedCall/model/arma_conv/BiasAdd/ReadVariableOp"],attr:{data_format:{s:"TkhXQw=="},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/BiasAdd_1",op:"BiasAdd",input:["StatefulPartitionedCall/model/arma_conv/add_1","StatefulPartitionedCall/model/arma_conv/BiasAdd_1/ReadVariableOp"],attr:{data_format:{s:"TkhXQw=="},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Relu",op:"Relu",input:["StatefulPartitionedCall/model/arma_conv/BiasAdd"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/Relu_1",op:"Relu",input:["StatefulPartitionedCall/model/arma_conv/BiasAdd_1"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv/stack",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv/Relu","StatefulPartitionedCall/model/arma_conv/Relu_1"],attr:{T:{type:"DT_FLOAT"},N:{i:"2"},axis:{i:"-1"}}},{name:"StatefulPartitionedCall/model/arma_conv/Mean",op:"Mean",input:["StatefulPartitionedCall/model/arma_conv/stack","StatefulPartitionedCall/model/arma_conv/Mean/reduction_indices"],attr:{T:{type:"DT_FLOAT"},Tidx:{type:"DT_INT32"},keep_dims:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv/Relu_2",op:"Relu",input:["StatefulPartitionedCall/model/arma_conv/Mean"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2","StatefulPartitionedCall/model/arma_conv_1/Reshape/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Shape",op:"Shape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2"],attr:{T:{type:"DT_FLOAT"},out_type:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_3",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2","StatefulPartitionedCall/model/arma_conv_1/Reshape_3/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Shape_2",op:"Shape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2"],attr:{out_type:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_6",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2","StatefulPartitionedCall/model/arma_conv_1/Reshape_6/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Shape_4",op:"Shape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2"],attr:{out_type:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_9",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2","StatefulPartitionedCall/model/arma_conv_1/Reshape_9/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Shape_6",op:"Shape",input:["StatefulPartitionedCall/model/arma_conv/Relu_2"],attr:{T:{type:"DT_FLOAT"},out_type:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/MatMul",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv_1/Reshape","StatefulPartitionedCall/model/arma_conv_1/Reshape_1"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_b:{b:!1},transpose_a:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv_1/unstack",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv_1/Shape"],attr:{T:{type:"DT_INT32"},axis:{i:"0"},num:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/MatMul_2",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv_1/Reshape_3","StatefulPartitionedCall/model/arma_conv_1/Reshape_4"],device:"/device:CPU:0",attr:{transpose_a:{b:!1},T:{type:"DT_FLOAT"},transpose_b:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv_1/unstack_2",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv_1/Shape_2"],attr:{num:{i:"3"},axis:{i:"0"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/MatMul_3",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv_1/Reshape_6","StatefulPartitionedCall/model/arma_conv_1/Reshape_7"],device:"/device:CPU:0",attr:{transpose_b:{b:!1},transpose_a:{b:!1},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/unstack_4",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv_1/Shape_4"],attr:{num:{i:"3"},axis:{i:"0"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/MatMul_5",op:"MatMul",input:["StatefulPartitionedCall/model/arma_conv_1/Reshape_9","StatefulPartitionedCall/model/arma_conv_1/Reshape_10"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_a:{b:!1},transpose_b:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv_1/unstack_6",op:"Unpack",input:["StatefulPartitionedCall/model/arma_conv_1/Shape_6"],attr:{num:{i:"3"},axis:{i:"0"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv_1/unstack","StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape/1","StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape/2"],attr:{axis:{i:"0"},T:{type:"DT_INT32"},N:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv_1/unstack_2","StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape/1","StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape/2"],attr:{axis:{i:"0"},T:{type:"DT_INT32"},N:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv_1/unstack_4","StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape/1","StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape/2"],attr:{axis:{i:"0"},T:{type:"DT_INT32"},N:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv_1/unstack_6","StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape/1","StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape/2"],attr:{axis:{i:"0"},T:{type:"DT_INT32"},N:{i:"3"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_2",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv_1/MatMul","StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_5",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv_1/MatMul_2","StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape"],attr:{Tshape:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_8",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv_1/MatMul_3","StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_11",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv_1/MatMul_5","StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/MatMul_1",op:"BatchMatMulV2",input:["adjacency","StatefulPartitionedCall/model/arma_conv_1/Reshape_2"],attr:{adj_x:{b:!1},T:{type:"DT_FLOAT"},adj_y:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv_1/MatMul_4",op:"BatchMatMulV2",input:["adjacency","StatefulPartitionedCall/model/arma_conv_1/Reshape_8"],attr:{T:{type:"DT_FLOAT"},adj_x:{b:!1},adj_y:{b:!1}}},{name:"StatefulPartitionedCall/model/arma_conv_1/add",op:"AddV2",input:["StatefulPartitionedCall/model/arma_conv_1/MatMul_1","StatefulPartitionedCall/model/arma_conv_1/Reshape_5"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/add_1",op:"AddV2",input:["StatefulPartitionedCall/model/arma_conv_1/MatMul_4","StatefulPartitionedCall/model/arma_conv_1/Reshape_11"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/BiasAdd",op:"BiasAdd",input:["StatefulPartitionedCall/model/arma_conv_1/add","StatefulPartitionedCall/model/arma_conv_1/BiasAdd/ReadVariableOp"],attr:{data_format:{s:"TkhXQw=="},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/BiasAdd_1",op:"BiasAdd",input:["StatefulPartitionedCall/model/arma_conv_1/add_1","StatefulPartitionedCall/model/arma_conv_1/BiasAdd_1/ReadVariableOp"],attr:{data_format:{s:"TkhXQw=="},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Relu",op:"Relu",input:["StatefulPartitionedCall/model/arma_conv_1/BiasAdd"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Relu_1",op:"Relu",input:["StatefulPartitionedCall/model/arma_conv_1/BiasAdd_1"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/stack",op:"Pack",input:["StatefulPartitionedCall/model/arma_conv_1/Relu","StatefulPartitionedCall/model/arma_conv_1/Relu_1"],attr:{N:{i:"2"},axis:{i:"-1"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Mean",op:"Mean",input:["StatefulPartitionedCall/model/arma_conv_1/stack","StatefulPartitionedCall/model/arma_conv_1/Mean/reduction_indices"],attr:{Tidx:{type:"DT_INT32"},keep_dims:{b:!1},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/arma_conv_1/Relu_2",op:"Relu",input:["StatefulPartitionedCall/model/arma_conv_1/Mean"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Shape",op:"Shape",input:["StatefulPartitionedCall/model/arma_conv_1/Relu_2"],attr:{out_type:{type:"DT_INT32"},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Shape",op:"Shape",input:["StatefulPartitionedCall/model/arma_conv_1/Relu_2"],attr:{T:{type:"DT_FLOAT"},out_type:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2_1",op:"GatherV2",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Shape","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/axes","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2_1/axis"],attr:{Taxis:{type:"DT_INT32"},Tparams:{type:"DT_INT32"},Tindices:{type:"DT_INT32"},batch_dims:{i:"0"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2",op:"GatherV2",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Shape","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/free","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2/axis"],attr:{Tparams:{type:"DT_INT32"},Taxis:{type:"DT_INT32"},batch_dims:{i:"0"},Tindices:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2_1",op:"GatherV2",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Shape","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/axes","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2_1/axis"],attr:{Tindices:{type:"DT_INT32"},Taxis:{type:"DT_INT32"},batch_dims:{i:"0"},Tparams:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2",op:"GatherV2",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Shape","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/free","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2/axis"],attr:{batch_dims:{i:"0"},Taxis:{type:"DT_INT32"},Tparams:{type:"DT_INT32"},Tindices:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Prod_1",op:"Prod",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2_1","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const_1"],attr:{T:{type:"DT_INT32"},Tidx:{type:"DT_INT32"},keep_dims:{b:!1}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Prod",op:"Prod",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const"],attr:{T:{type:"DT_INT32"},Tidx:{type:"DT_INT32"},keep_dims:{b:!1}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/concat_1",op:"ConcatV2",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const_2","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/concat_1/axis"],attr:{N:{i:"2"},T:{type:"DT_INT32"},Tidx:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Prod_1",op:"Prod",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2_1","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const_1"],attr:{T:{type:"DT_INT32"},Tidx:{type:"DT_INT32"},keep_dims:{b:!1}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Prod",op:"Prod",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const"],attr:{T:{type:"DT_INT32"},Tidx:{type:"DT_INT32"},keep_dims:{b:!1}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/concat_1",op:"ConcatV2",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const_2","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/concat_1/axis"],attr:{Tidx:{type:"DT_INT32"},N:{i:"2"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/stack",op:"Pack",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Prod","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Prod_1"],attr:{T:{type:"DT_INT32"},N:{i:"2"},axis:{i:"0"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/stack",op:"Pack",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Prod","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Prod_1"],attr:{N:{i:"2"},axis:{i:"0"},T:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Reshape",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv_1/Relu_2","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/stack"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Reshape",op:"Reshape",input:["StatefulPartitionedCall/model/arma_conv_1/Relu_2","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/stack"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/MatMul",op:"MatMul",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Reshape","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/ReadVariableOp"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_a:{b:!1},transpose_b:{b:!1}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/MatMul",op:"MatMul",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Reshape","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/ReadVariableOp"],device:"/device:CPU:0",attr:{T:{type:"DT_FLOAT"},transpose_a:{b:!1},transpose_b:{b:!1}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot",op:"Reshape",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/MatMul","StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/concat_1"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot",op:"Reshape",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/MatMul","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/concat_1"],attr:{T:{type:"DT_FLOAT"},Tshape:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/BiasAdd",op:"BiasAdd",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot","StatefulPartitionedCall/model/global_attention_pool/features_layer/BiasAdd/ReadVariableOp"],attr:{data_format:{s:"TkhXQw=="},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/BiasAdd",op:"BiasAdd",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot","StatefulPartitionedCall/model/global_attention_pool/attn_layer/BiasAdd/ReadVariableOp"],attr:{data_format:{s:"TkhXQw=="},T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Sigmoid",op:"Sigmoid",input:["StatefulPartitionedCall/model/global_attention_pool/attn_layer/BiasAdd"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/mul",op:"Mul",input:["StatefulPartitionedCall/model/global_attention_pool/features_layer/BiasAdd","StatefulPartitionedCall/model/global_attention_pool/attn_layer/Sigmoid"],attr:{T:{type:"DT_FLOAT"}}},{name:"StatefulPartitionedCall/model/global_attention_pool/Sum",op:"Sum",input:["StatefulPartitionedCall/model/global_attention_pool/mul","StatefulPartitionedCall/model/global_attention_pool/Sum/reduction_indices"],attr:{keep_dims:{b:!1},T:{type:"DT_FLOAT"},Tidx:{type:"DT_INT32"}}},{name:"StatefulPartitionedCall/model/prediction/BiasAdd",op:"_FusedMatMul",input:["StatefulPartitionedCall/model/global_attention_pool/Sum","StatefulPartitionedCall/model/prediction/MatMul/ReadVariableOp","StatefulPartitionedCall/model/prediction/BiasAdd/ReadVariableOp"],device:"/device:CPU:0",attr:{num_args:{i:"1"},transpose_b:{b:!1},T:{type:"DT_FLOAT"},transpose_a:{b:!1},epsilon:{f:0},fused_ops:{list:{s:["Qmlhc0FkZA=="]}}}},{name:"StatefulPartitionedCall/model/prediction/Sigmoid",op:"Sigmoid",input:["StatefulPartitionedCall/model/prediction/BiasAdd"],attr:{T:{type:"DT_FLOAT"}}},{name:"Identity",op:"Identity",input:["StatefulPartitionedCall/model/prediction/Sigmoid"],attr:{T:{type:"DT_FLOAT"}}}],library:{},versions:{producer:898}},weightsManifest:[{paths:["hideIfGraphMatches-shard1of1.dat"],weights:[{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/axes",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2_1/axis",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const_1",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/ReadVariableOp",shape:[64,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/free",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/GatherV2/axis",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/Const_2",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/Tensordot/concat_1/axis",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/features_layer/BiasAdd/ReadVariableOp",shape:[64],dtype:"float32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/axes",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2_1/axis",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const_1",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/ReadVariableOp",shape:[64,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_1",shape:[64,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_2/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_3/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_4",shape:[64,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_5/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/BiasAdd/ReadVariableOp",shape:[64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_6/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_7",shape:[64,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_8/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_9/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_10",shape:[64,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_1",shape:[562,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_2/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_2/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_3/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_4",shape:[562,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_5/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_5/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/BiasAdd/ReadVariableOp",shape:[64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_6/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_7",shape:[562,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_8/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_8/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_9/shape",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_10",shape:[562,64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_11/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/Reshape_11/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv/BiasAdd_1/ReadVariableOp",shape:[64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv/Mean/reduction_indices",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape/1",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Reshape_11/shape/2",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/arma_conv_1/BiasAdd_1/ReadVariableOp",shape:[64],dtype:"float32"},{name:"StatefulPartitionedCall/model/arma_conv_1/Mean/reduction_indices",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/free",shape:[2],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/GatherV2/axis",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/Const_2",shape:[1],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/Tensordot/concat_1/axis",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/global_attention_pool/attn_layer/BiasAdd/ReadVariableOp",shape:[64],dtype:"float32"},{name:"StatefulPartitionedCall/model/global_attention_pool/Sum/reduction_indices",shape:[],dtype:"int32"},{name:"StatefulPartitionedCall/model/prediction/MatMul/ReadVariableOp",shape:[64,2],dtype:"float32"},{name:"StatefulPartitionedCall/model/prediction/BiasAdd/ReadVariableOp",shape:[2],dtype:"float32"}]}],graphml:{learning_rate:1e-5,epochs:768,armaconv_dropout:.1,nodes:200,features:562,features_dropout:.1,model_version:"1.0.0"}},jt={config:{graph:[],node:[["top_level",{path:"",features:[{node_id:{dim:1,normalizers:["float"]}},{parent_id:{dim:1,normalizers:["float"]}},{siblings:{dim:1,normalizers:["float"]}},{tag:{dim:8,normalizers:["lower",{sequence:{max_len:8}}]}},{level:{dim:1,normalizers:["float"]}},{children:{dim:1,normalizers:["children_len"]}}]}],["attributes",{path:"attributes",features:[{url:{dim:256,names:["src^xlink:href"],normalizers:["strip_whitespace","lower",{url_parts:{max_len:256}},{sequence:{max_len:256}}]}},{meta_url:{dim:9,names:["src^xlink:href"],normalizers:["meta_url"]}},{url_level:{dim:1,names:["src_level","href_level"],normalizers:["float"]}},{id:{dim:16,normalizers:["lower","replace_punctuation","strip_and_collapse_whitespace",{sequence:{max_len:16}}]}},{class:{dim:8,normalizers:["css_class","strip_and_collapse_whitespace",{sequence:{max_len:8}}]}},{meta_class:{dim:2,names:["class"],normalizers:["strip_and_collapse_whitespace","meta_content"]}},{text_attrs:{dim:8,names:["aria-hidden","aria-describedby","aria-labelledby","aria-expanded","aria-haspopup","referrerpolicy","type","fill","mask","dir","role","target","d","rel","transform","preserveAspectRatio","title","viewBox","data-visualcompletion","data-ad-comet-preview","data-ad-preview","fill-rule"],normalizers:["replace_punctuation","strip_and_collapse_whitespace",{sequence:{max_len:8}}]}},{num_attrs:{dim:1,names:["height","width","x","y","rx","ry","cy","aria-posinset","tabindex"],normalizers:["strip_whitespace",{replace_str:{pairs:[["px",""],["%",""],["em",""]]}},"float"]}}]}],["style",{path:"attributes/style",features:[{num_attrs:{dim:1,names:["height","width","top","bottom","left","right","marginRight"],normalizers:["strip_whitespace",{replace_str:{pairs:[["px",""],["%",""],["em",""]]}},"float"]}},{text_attrs:{dim:4,names:["inset","borderBottomLeftRadius","borderBottomRightRadius","borderRadius","borderTopLeftRadius","borderTopRightRadius","webkitBorderBottomLeftRadius","webkitBorderBottomRightRadius","webkitBorderRadius","webkitBorderTopLeftRadius","webkitBorderTopRightRadius","overflow","overflowX","overflowY","webkitBoxOrient","webkitLineClamp"],normalizers:["strip_and_collapse_whitespace","replace_punctuation",{sequence:{max_len:4}}]}}]}]]}},At=Object.freeze({__proto__:null,hideIfGraphMatchesModel:pt,hideIfGraphMatchesWeights:" ",hideIfGraphMatchesConfig:jt});const bv=/\s+/g,Ev=/[\xA0!"\\'()*,-./:;?&[\]^_`{|}~“”]/g,Tv=/rgb\((\d+), (\d+), (\d+)\)/,Sv=/rgba\((\d+), (\d+), (\d+), (\d+)\)/,fv=/(\d*?\.?\d*)px (\d*?\.?\d*)px/,qv=/(\d*?\.?\d*)px/,kv=/\./g,Gv=/^\[|\]$/g,Nv=/\//g,Bv=Object.fromEntries([..." abcdefghijklmnopqrstuvwxyz1234567890:;/?!=+.,()[]-`*_|~"].map(((t,e)=>[t,e+1])));class Uv{constructor(t){this.normalizers=[],t.forEach((t=>{if(Array.isArray(t)){let[e,i]=t;this.normalizers.push(new e(i))}else this.normalizers.push(new t)}))}normalize(t,e){return this.normalizers.forEach((i=>{t=i.normalize(t,e)})),t}}class Jv{normalize(t){throw new Error("Not implemented.")}}class Wv extends Jv{normalize(t){return t.toLowerCase()}}class Fv extends Jv{normalize(t){return t.trim()}}class Rv extends Jv{normalize(t){return t.replace(bv," ")}}class Hv extends Jv{normalize(t){return t.replace(bv," ").trim()}}class Vv extends Jv{normalize(t){return t.replace(Ev,"")}}class Zv extends Jv{normalize(t){return t.replace(Ev," ")}}class Xv extends Jv{constructor(t){super(),this.pairs=t}normalize(t){return t&&this.pairs.forEach((e=>{t=t.replaceAll(e[0],e[1])})),t}}class _v extends Jv{normalize(t){return t.split(" ").pop()}}class $v{normalize(t){throw new Error("Not implemented.")}}class tD extends $v{normalize(t){return[parseFloat(t)||0]}}class eD extends $v{constructor(t){super(),this.maxLen=t}normalize(t){let e=[...t.toLowerCase()].slice(-this.maxLen).map((t=>t in Bv?Bv[t]:1));return e.length>=this.maxLen?e:e.concat(new Array(this.maxLen-e.length).fill(0))}}class iD extends $v{constructor(t){super();const e=t.length;this.empty=new Array(e).fill(0);let i=0;this.categoryMap=t.reduce(((t,e)=>{let s=[...this.empty];return s[i++]=1,t[e]=s,t}),{})}normalize(t){return this.categoryMap[t]||this.empty}}class sD extends $v{normalize(t){return[parseFloat(t)||0]}}class oD extends $v{constructor(t){super(),this.maxLen=t}normalize(t){let e=[0,0,0,0];const i=t.match(Tv);if(i)i.shift(),e=i.map((t=>parseFloat(t)||0)),e.push(0);else{const i=t.match(Sv);i&&(i.shift(),e=i.map((t=>parseFloat(t)||0)))}return e.slice(0,this.maxLen)}}class rD extends $v{normalize(t){const e=t.match(qv);return e?[parseFloat(e[1])||0]:[0]}}class uD extends $v{normalize(t){const e=t.match(fv);return e?(e.shift(),e.map((t=>parseFloat(t)||0))):[0,0]}}class aD{normalize(t){return Array.isArray(t)?[t.length]:[0]}}const nD=["http","data","blob","ftp:"];class LD{normalize(t,e){if(!t)return[0,0,0,0,0,0,0,0,0];const i=nD.includes(t.slice(0,4).toLowerCase())?1:0;if(!i)return[1,i,0,0,t.length,0,0,0,0];let s;try{s=new URL(t)}catch(e){return[1,i,0,0,t.length,0,0,0,0]}const o=s.hostname.includes(e.domain)?0:1,r=s.username+s.password+s.hostname+(s.port?s.port:""),u="/"===s.pathname?"":s.pathname,a=Array.from(s.searchParams);return[1,i,o,r.length,u.length,a.flat().join("").length,r?s.hostname.split(".").length:0,u.split("/").filter(Boolean).length,a.length]}}class MD{constructor(t){this.maxLen=t,this.maxPartsLen=this.maxLen/3,this.replacePunctuation=new Zv}normalize(t,e){let i;if(!(nD.includes(t.slice(0,4).toLowerCase())?1:0))return t.substring(0,this.maxLen).trim();try{i=new URL(t)}catch(e){return t.substring(0,this.maxLen).trim()}const s=i.hostname.replace(Gv,""),o=[i.username,i.password,s.replace(kv," "),i.port].filter(Boolean).join(" ").slice(0,this.maxPartsLen).trim(),r=i.pathname.replace(Nv," ").slice(0,2*this.maxPartsLen-o.length).trim(),u=i.search.substring(1).split("&").map((t=>t.split("=")[0].trim())).join(" ").slice(0,3*this.maxPartsLen-o.length-r.length).trim();return[[o,r].join(" ").trim(),u].join(" ").trim()}}class CD{normalize(t,e){let i=0,s=0;return t&&(i=t.length,s=t.split(" ").length),[i,s]}}class wD{constructor(t){this.preprocesors=[];for(let e of t)this.preprocesors.push(new e)}process(t,e){return this.preprocesors.forEach((e=>t=e.process(t))),t}}class yD{process(t,e){return t||new Map}}class vD{process(t,e){return t&&("string"==typeof t||t instanceof String)?t.split(";").reduce(((t,e)=>{const[i,s]=e.split(":");return i&&s&&!(i in t)&&(t[i.trim()]=s.trim()),t}),{}):new Map}}function DD(t){let e=[];for(const i of t.graph)e.push(new AD(i[0],i[1]));let i=[];for(const e of t.node)i.push(new AD(e[0],e[1]));return[i,e]}const lD={empty:yD,css_selector:vD},gD={lower:Wv,strip_whitespace:Fv,collapse_whitespace:Rv,strip_and_collapse_whitespace:Hv,remove_punctuation:Vv,replace_punctuation:Zv,sequence:eD,one_hot_vector:iD,font_size:sD,color:oD,pixel:rD,origin:uD,children_len:aD,replace_str:Xv,meta_url:LD,url_parts:MD,meta_content:CD,css_class:_v,float:tD},pD=(t,e)=>{const i=t.split(e);return""===i[0]&&1===i.length?[]:i};class jD{constructor(t,e){this.name=t,this.dim=e.dim,this.altNames=pD(t,"^"),this.path=[],e.path&&(this.path=pD(e.path,"^"));let i=[];if(Object.hasOwn(e,"normalizers"))for(const t in e.normalizers){const s=e.normalizers[t];if("string"==typeof s||s instanceof String)i.push(gD[s]);else if("object"==typeof s&&null!==s){const t=Object.keys(s)[0];i.push([gD[t],Object.values(s[t])[0]])}}else i.push(gD.empty);this.normalizer=new Uv(i)}getName(t){if(this.altNames&&Object.keys(t).length>0)for(let e of this.altNames)if(e in t)return e;return this.name}extractValues(t,e){let i=t;this.path.forEach((t=>{t in i&&(i=i[t])}));const s=this.getName(i),o=s in i?i[s]:"",r=this.normalizer.normalize(o||"",e);if(r.length!==this.dim)throw new Error("Feature dimensionality mismatch");return r}}class AD{constructor(t,e){this.name=t,this.path=pD(e.path,"/"),this.prep=this.initPreprocessing(e),this.features=this.initFeatures(e.features)}initPreprocessing(t){let e=[];if(Object.hasOwn(t,"prep"))for(let i of t.prep)e.push(lD[i]);else e.push(lD.empty);return new wD(e)}initFeatures(t){let e=[];for(const i of t){const t=Object.keys(i)[0],s=i[t];if(Object.hasOwn(s,"names"))for(const t of s.names)e.push(new jD(t,s));else e.push(new jD(t,s))}return e}extractValues(t,e){let i=t;if(this.path.forEach((t=>{t in i&&(i=i[t])})),i=this.prep.process(i,e),"object"!=typeof i||Array.isArray(i)||null===i)throw new Error(`path ${this.path}, value ${i}, expected ${typeof{}}, got ${i}`);let s=[];return this.features.forEach((t=>s.push(...t.extractValues(i,e)))),s}}const cD=["src","href","xlink:href"],ID=(t,e,i=0)=>Array.from(new Array(e),(e=>Array(t).fill(i))),mD=(t,e,i)=>e in t?t[e]:i;class hD{constructor(t){this.numNodes=0,this.root=t.obj.graph,this.domain=t.obj.domain,this.graphAttributes={domain:t.obj.domain},this.featureGroups=t.nodeFeatureGroups,this.graphFeatureGroups=t.graphFeatureGroups,this.cutoff=t.cutoff}getData(){this.setNodeAttributes();let t=ID(this.numNodes,this.numNodes),e=[],i=[],s=[[this.root,{}]],o=this.cutoff;for(;s.length&&--o>=0;){let i,[o,r]=s.pop();this._updateFeatures(o,this.featureGroups,e),r&&Object.keys(r).length>0&&this._updateEdges(o,r,t),[r,i]=[o,o.children];for(let t=i.length-1;t>=0;t--)s.push([i[t],r])}return this._updateFeatures(this.graphAttributes,this.graphFeatureGroups,i),this._formatData(t,e,i)}setNodeAttributes(){let t=[[this.root,{}]],e=this.cutoff;for(;t.length&&--e>=0;){let e,[i,s]=t.pop();this._setNodeAttributes(i,s),[s,e]=[i,i.children];for(let i=e.length-1;i>=0;i--)t.push([e[i],s])}}_setNodeAttributes(t,e){t.node_id=this.numNodes++,t.dom=this.domain,t.parent_id=mD(e,"node_id",0),t.siblings=mD(e,"children",[]).length,t.level=mD(e,"level",-1)+1;let i=mD(t,"attributes",{}),s=mD(e,"attributes",{});cD.forEach((o=>{let r=`${o}_level`;this._hasAttribute(o,i)?t.attributes[r]=0:this._hasAttribute(o,s)&&(t.attributes[o]=s[o],t.attributes[r]=s[r]+1,"requestType"in e&&(t.requestType=e.requestType))}))}_hasAttribute(t,e){return t in e&&e[t]}_updateFeatures(t,e,i){let s=[];e.forEach((e=>s.push(...e.extractValues(t,{domain:this.domain}).map((t=>Math.round(100*t)/100||0))))),i.push(s)}_updateEdges(t,e,i){i[e.node_id][t.node_id]=1,i[t.node_id][e.node_id]=1}_formatData(t,e,i){return t.length>e.length&&this._cutEdges(t,e.length),this.graphFeatureGroups.length>0?[t,e,i]:[t,e]}_cutEdges(t,e){(t=t.slice(0,e)).forEach(((t,i,s)=>{s[i]=t.slice(0,e)}))}}class OD{constructor(t){this.tfjs=t,this._preprocessingFunctions=new Map([["cast",t.cast],["stack",t.stack],["unstack",t.unstack],["localPooling",this._localPoolingMap.bind(this)],["padAdjacency",this._padTensorAdjacency.bind(this)],["padFeatures",this._padTensorFeatures.bind(this)]])}_padTensorAdjacency(t,e){return t.pad([[0,0],[0,e-t.shape[1]],[0,e-t.shape[2]]])}_localPoolingMap(t){return t.map((t=>this._localPooling(t)))}_localPooling(t){let e=t.add(this.tfjs.eye(t.shape[0])),i=this.tfjs.pow(this.tfjs.sum(e,1),-.5);i=i.where(this.tfjs.isFinite(i),this.tfjs.zeros(i.shape));let s=i.mul(this.tfjs.eye(e.shape[0]));return s.dot(e).dot(s)}_padTensorFeatures(t,e){return t.pad([[0,0],[0,e-t.shape[1]],[0,0]])}createTensors(t,e){const[i,s]=t,o=[{data:[i],preprocess:[{funcName:"padAdjacency",args:e}]},{data:[s],preprocess:[{funcName:"padFeatures",args:e}]}];return this.tfjs.tidy((()=>o.map((t=>{let e=this.tfjs.tensor(t.data);if(t.preprocess)for(let i of t.preprocess)e=this._preprocessingFunctions.get(i.funcName)(e,i.args);return e}))))}}const zD=500;async function xD(t,e,i,s,o="."){return dD(i,s).then((t=>KD(i,t,o))).then((s=>PD(t,e,i,s))).then((t=>YD(t)))}async function dD(t,e){return new Promise(((i,s)=>{t&&t.node||s();let o=t.cutoff||zD,r=(t,e,i,s)=>{"attributes"===i&&void 0!==t.attributes[s]?e.attributes[s]=t.attributes[s].value:"style"===i&&t.style[s]?e.attributes.style[s]=t.style[s]:"css"===i&&(e.cssSelectors=getComputedStyle(t).cssText||"")},u=e=>{if(o-=1,o<0)return;let i={tag:e.tagName,width:e.clientWidth,height:e.clientHeight,attributes:{style:{}},children:[]};for(let s of t.node)for(let t of s[1].features)for(let[o,u]of Object.entries(t))if("names"in u)for(let t of u.names)for(let o of t.split("^"))r(e,i,s[0],o);else r(e,i,s[0],o);if(e.children)for(let t of e.children){let e=u(t);e&&i.children.push(e)}return i};i(u(e))}))}async function KD(t,e,i="."){return new Promise(((s,o)=>{t&&t.node||o();let r=t.cutoff||zD,[u,a]=DD(t);s(new hD({nodeFeatureGroups:u,graphFeatureGroups:a,obj:{domain:i,graph:e},cutoff:r}).getData())}))}async function PD(t,e,i,s){return new Promise(((o,r)=>{i&&t&&e&&s||r();const u=i.cutoff||zD;const a=new OD(t).createTensors(s,u);let n=e.execute(a);n.data().then((t=>{o(t)})).catch((t=>{r(t)})).finally((()=>{n.dispose();for(let t of a)t.dispose()}))}))}async function YD(t){return new Promise(((e,i)=>{(t=Array.from(t))&&Array.isArray(t)&&t.some((t=>t>0))&&!(t.length<2)||i();let s=t.reduce(((t,e)=>t+e),0);e((t=t.map((t=>t/s)))[1]>t[0])}))}async function QD(t,e,i){if(!e||!i)throw new Error("Model format not recognized.");return Array.isArray(i)||(i=[i]),t.loadGraphModel({load(){let t={modelTopology:e.modelTopology||{},signature:e.signature||{},weightsManifest:e.weightsManifest||[],weightSpecs:e.weightsManifest.map((t=>t.weights))[0]||[],weightData:ED(i.map((t=>Uint8Array.from(atob(t),(t=>t.charCodeAt(0))))))||[]};return t}})}async function bD(t,e){return t.loadGraphModel(e)}function ED(t){let e=0;t.forEach((t=>{e+=t.byteLength}));let i=new Uint8Array(e),s=0;return t.forEach((t=>{i.set(new Uint8Array(t),s),s+=t.byteLength})),i.buffer}var ct=Object.freeze({__proto__:null,inference:xD,domToGraph:dD,preprocessGraph:KD,predict:PD,digestPrediction:YD,loadRawModel:QD,loadModel:bD});globalThis.ml={tfjs:gt,data:At,util:ct},globalThis.ml.data.hideIfGraphMatchesConfig.config.cutoff=globalThis.ml.data.hideIfGraphMatchesModel.graphml.nodes,globalThis.ml.model=await globalThis.ml.util.loadRawModel(globalThis.ml.tfjs,globalThis.ml.data.hideIfGraphMatchesModel,globalThis.ml.data.hideIfGraphMatchesWeights),globalThis.ml.tfjs.enableProdMode(),globalThis.ml.tfjs.env().set("WEBGL_USE_SHAPES_UNIFORMS",!0)}
/**  
        *   @eyeo/mlbrowserutils - v0.1.7
        *   ML utility package for ABP's snippet library
        *   Made by eyeo GmbH
        *   Under GPL-3.0-only License
        *   
        *   The following npm packages may be included in this product:
        *
        *   - tfjs
        *   - tfjs-backend-cpu
        *   - tfjs-backend-webgl
        *   - tfjs-converter
        *   - tfjs-core
        *   - tfjs-data
        *   - tfjs-layers
        *
        *    These packages contain the following information about the license:
        * 
        *  * @license
        *  * Copyright 2018-2022 Google LLC. All Rights Reserved.
        *  * Licensed under the Apache License, Version 2.0 (the "License");
        *  * you may not use this file except in compliance with the License.
        *  * You may obtain a copy of the License at
        *  *
        *  * http://www.apache.org/licenses/LICENSE-2.0
        *  *
        *  * Unless required by applicable law or agreed to in writing, software
        *  * distributed under the License is distributed on an "AS IS" BASIS,
        *  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        *  * See the License for the specific language governing permissions and
        *  * limitations under the License.
        *  * =============================================================================
        */
var It}]]);
callback.get = snippet => graph.get(snippet);
callback.has = snippet => graph.has(snippet);
/* harmony default export */ const ml = (callback);
;// CONCATENATED MODULE: ./node_modules/@eyeo/snippets/webext/main.mjs
/*!
 * This file is part of eyeo's Anti-Circumvention Snippets module (@eyeo/snippets),
 * Copyright (C) 2006-present eyeo GmbH
 * 
 * @eyeo/snippets is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 * 
 * @eyeo/snippets is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with @eyeo/snippets.  If not, see <http://www.gnu.org/licenses/>.
 */

const main_callback = (environment, ...filters) => {
const e=Proxy,{apply:t,bind:r,call:n}=Function,o=n.bind(t),i=n.bind(r),s=n.bind(n),a={get:(e,t)=>i(n,e[t])},l=t=>new e(t,a),c=(t,r)=>new e(t,{apply:(e,t,n)=>o(r,t,n)}),u={get:(e,t)=>i(e[t],e)},f=t=>new e(t,u),{assign:p,defineProperties:d,freeze:h,getOwnPropertyDescriptor:w,getOwnPropertyDescriptors:g,getPrototypeOf:y}=f(Object),{hasOwnProperty:m}=l({}),{species:b}=Symbol,v={get(e,t){const r=e[t];class n extends r{}const o=g(r.prototype);delete o.constructor,h(d(n.prototype,o));const i=g(r);return delete i.length,delete i.prototype,i[b]={value:n},h(d(n,i))}},E=t=>new e(t,v),S="undefined"!=typeof environment?environment:{};"undefined"==typeof globalThis&&(window.globalThis=window);const{apply:M,ownKeys:T}=f(Reflect),x="world"in S,O=x&&"ISOLATED"===S.world,P=x&&"MAIN"===S.world,j="object"==typeof chrome&&!!chrome.runtime,N="object"==typeof browser&&!!browser.runtime,L=!P&&(O||j||N),k=e=>L?e:C(e,H(e)),{create:C,defineProperties:A,defineProperty:W,freeze:$,getOwnPropertyDescriptor:D,getOwnPropertyDescriptors:H}=f(Object),z=f(globalThis),R=L?globalThis:E(globalThis),{Map:F,RegExp:I,Set:J,WeakMap:V,WeakSet:B}=R,U=(e,t,r=null)=>{const n=T(t);for(const o of T(e)){if(n.includes(o))continue;const i=D(e,o);if(r&&"value"in i){const{value:e}=i;"function"==typeof e&&(i.value=r(e))}W(t,o,i)}},_=e=>{const t=R[e];class r extends t{}const{toString:n,valueOf:o}=t.prototype;A(r.prototype,{toString:{value:n},valueOf:{value:o}});const i=e.toLowerCase(),s=e=>function(){const t=M(e,this,arguments);return typeof t===i?new r(t):t};return U(t,r,s),U(t.prototype,r.prototype,s),r},X=$({frozen:new V,hidden:new B,iframePropertiesToAbort:{read:new J,write:new J},abortedIframes:new V}),q=new I("^[A-Z]");var G=new Proxy(new F([["chrome",L&&(j&&chrome||N&&browser)||void 0],["isExtensionContext",L],["variables",X],["console",k(console)],["document",globalThis.document],["performance",k(performance)],["JSON",k(JSON)],["Map",F],["Math",k(Math)],["Number",L?Number:_("Number")],["RegExp",I],["Set",J],["String",L?String:_("String")],["WeakMap",V],["WeakSet",B],["MouseEvent",MouseEvent]]),{get(e,t){if(e.has(t))return e.get(t);let r=globalThis[t];return"function"==typeof r&&(r=(q.test(t)?R:z)[t]),e.set(t,r),r},has:(e,t)=>e.has(t)});const K={WeakSet:WeakSet,WeakMap:WeakMap,WeakValue:class{has(){return!1}set(){}}},{apply:Y}=Reflect;const{Map:Z,WeakMap:Q,WeakSet:ee,setTimeout:te}=G;let re=!0,ne=e=>{e.clear(),re=!re};var oe=function(e){const{WeakSet:t,WeakMap:r,WeakValue:n}=this||K,o=new t,i=new r,s=new n;return function(t){if(o.has(t))return t;if(i.has(t))return i.get(t);if(s.has(t))return s.get(t);const r=Y(e,this,arguments);return o.add(r),r!==t&&("object"==typeof t&&t?i:s).set(t,r),r}}.bind({WeakMap:Q,WeakSet:ee,WeakValue:class extends Z{set(e,t){return re&&(re=!re,te(ne,0,this)),super.set(e,t)}}});const{concat:ie,includes:se,join:ae,reduce:le,unshift:ce}=l([]),ue=E(globalThis),{Map:fe,WeakMap:pe}=ue,de=new fe,he=t=>{const r=(e=>{const t=[];let r=e;for(;r;){if(de.has(r))ce(t,de.get(r));else{const e=g(r);de.set(r,e),ce(t,e)}r=y(r)}return ce(t,{}),o(p,null,t)})("function"==typeof t?t.prototype:t),n={get(e,t){if(t in r){const{value:n,get:o}=r[t];if(o)return s(o,e);if("function"==typeof n)return i(n,e)}return e[t]},set(e,t,n){if(t in r){const{set:o}=r[t];if(o)return s(o,e,n),!0}return e[t]=n,!0}};return t=>new e(t,n)},{isExtensionContext:we,Array:ge,Number:ye,String:me,Object:be}=G,{isArray:ve}=ge,{getOwnPropertyDescriptor:Ee,setPrototypeOf:Se}=be,{toString:Me}=be.prototype,{slice:Te}=me.prototype,{get:xe}=Ee(Node.prototype,"nodeType"),Oe=we?{}:{Attr:he(Attr),CanvasRenderingContext2D:he(CanvasRenderingContext2D),CSSStyleDeclaration:he(CSSStyleDeclaration),Document:he(Document),Element:he(Element),HTMLCanvasElement:he(HTMLCanvasElement),HTMLElement:he(HTMLElement),HTMLImageElement:he(HTMLImageElement),HTMLScriptElement:he(HTMLScriptElement),MutationRecord:he(MutationRecord),Node:he(Node),ShadowRoot:he(ShadowRoot),get CSS2Properties(){return Oe.CSSStyleDeclaration}},Pe=(e,t)=>{if("Element"!==t&&t in Oe)return Oe[t](e);if(ve(e))return Se(e,ge.prototype);const r=(e=>s(Te,s(Me,e),8,-1))(e);if(r in Oe)return Oe[r](e);if(r in G)return Se(e,G[r].prototype);if("nodeType"in e)switch(s(xe,e)){case 1:if(!(t in Oe))throw new Error("unknown hint "+t);return Oe[t](e);case 2:return Oe.Attr(e);case 3:return Oe.Node(e);case 9:return Oe.Document(e)}throw new Error("unknown brand "+r)};var je=we?e=>e===window||e===globalThis?G:e:oe(((e,t="Element")=>{if(e===window||e===globalThis)return G;switch(typeof e){case"object":return e&&Pe(e,t);case"string":return new me(e);case"number":return new ye(e);default:throw new Error("unsupported value")}}));const Ne={get(e,t){const r=e;for(;!m(e,t);)e=y(e);const{get:n,set:i}=w(e,t);return function(){return arguments.length?o(i,r,arguments):s(n,r)}}},Le=t=>new e(t,Ne);let ke=!1;function Ce(){return ke}const{console:Ae}=je(window),We=()=>{};function $e(...e){Ce()&&je(e).unshift("%c DEBUG","font-weight: bold"),Ae.log(...e)}function De(e){return i(Ce()?$e:We,null,e)}let{Math:He,RegExp:ze}=je(window);function Re(e){let{length:t}=e;if(t>1&&"/"===e[0]){let r="/"===e[t-1];if(r||t>2&&je(e).endsWith("/i")){let t=[je(e).slice(1,r?-1:-2)];return r||t.push("i"),new ze(...t)}}return new ze(je(e).replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))}function Fe(){return je(He.floor(2116316160*He.random()+60466176)).toString(36)}let{parseFloat:Ie,variables:Je,Array:Ve,Error:Be,Map:Ue,Object:_e,ReferenceError:Xe,Set:qe,WeakMap:Ge}=je(window),{onerror:Ke}=Le(window),Ye=Node.prototype,Ze=Element.prototype,Qe=null;function et(e,t,r,n=!0){let o=je(t),i=o.indexOf(".");if(-1==i){let o=_e.getOwnPropertyDescriptor(e,t);if(o&&!o.configurable)return;let i=_e.assign({},r,{configurable:n});if(!o&&!i.get&&i.set){let r=e[t];i.get=()=>r}return void _e.defineProperty(e,t,i)}let s=o.slice(0,i).toString();t=o.slice(i+1).toString();let a=e[s];!a||"object"!=typeof a&&"function"!=typeof a||et(a,t,r);let l=_e.getOwnPropertyDescriptor(e,s);if(l&&!l.configurable)return;Qe||(Qe=new Ge),Qe.has(e)||Qe.set(e,new Ue);let c=Qe.get(e);if(c.has(s))return void c.get(s).set(t,r);let u=new Ue([[t,r]]);c.set(s,u),_e.defineProperty(e,s,{get:()=>a,set(e){if(a=e,a&&("object"==typeof a||"function"==typeof a))for(let[e,t]of u)et(a,e,t)},configurable:n})}function tt(e){let t=Ke();Ke(((...r)=>{let n=r.length&&r[0];return!("string"!=typeof n||!je(n).includes(e))||("function"==typeof t?o(t,this,r):void 0)}))}function rt(e,t,r,n=!0){let o=De(e);if(!r)return void o("no property to abort on read");let i=Fe();o(`aborting on ${r} access`),et(t,r,{get:function(){throw o(`${r} access aborted`),new Xe(i)},set(){}},n),tt(i)}function nt(e,t,r,n=!0){let o=De(e);if(!r)return void o("no property to abort on write");let i=Fe();o(`aborting when setting ${r}`),et(t,r,{set:function(){throw o(`setting ${r} aborted`),new Xe(i)}},n),tt(i)}function ot(e,t=!1,r=!1){let n=Je.abortedIframes,i=Je.iframePropertiesToAbort;for(let o of Ve.from(window.frames))if(n.has(o))for(let i of e)t&&n.get(o).read.add(i),r&&n.get(o).write.add(i);for(let n of e)t&&i.read.add(n),r&&i.write.add(n);function a(){for(let e of Ve.from(window.frames)){n.has(e)||n.set(e,{read:new qe(i.read),write:new qe(i.write)});let t=n.get(e).read;if(t.size>0){let r=Ve.from(t);t.clear();for(let t of r)rt("abort-on-iframe-property-read",e,t)}let r=n.get(e).write;if(r.size>0){let t=Ve.from(r);r.clear();for(let r of t)nt("abort-on-iframe-property-write",e,r)}}}a(),n.has(document)||(n.set(document,!0),function(e){let t;function r(e,t){for(let r of t){et(e,r,n(e,r))}}function n(t,r){let n=t[r];return{get:()=>function(...t){let r;return r=o(n,this,t),e&&e(),r}}}function i(t,r){let n=_e.getOwnPropertyDescriptor(t,r),{set:o}=n||{};return{set(t){let r;return r=s(o,this,t),e&&e(),r}}}r(Ye,["appendChild","insertBefore","replaceChild"]),r(Ze,["append","prepend","replaceWith","after","before","insertAdjacentElement","insertAdjacentHTML"]),t=i(Ze,"innerHTML"),et(Ze,"innerHTML",t),t=i(Ze,"outerHTML"),et(Ze,"outerHTML",t)}(a))}let{Object:it}=window;function st(e,t){if(!(e instanceof it))return;let r=e,n=je(t).split(".");if(0===n.length)return;for(let e=0;e<n.length-1;e++){let t=n[e];if(!m(r,t))return;if(r=r[t],!(r instanceof it))return}let o=n[n.length-1];return m(r,o)?[r,o]:void 0}const at=je(/^\d+$/);function lt(e){switch(e){case"false":return!1;case"true":return!0;case"null":return null;case"noopFunc":return()=>{};case"trueFunc":return()=>!0;case"falseFunc":return()=>!1;case"emptyArray":return[];case"emptyObj":return{};case"undefined":return;case"":return e;default:if(at.test(e))return Ie(e);throw new Be(`[override-property-read snippet]: Value "${e}" is not valid.`)}}let{HTMLScriptElement:ct,Object:ut,ReferenceError:ft}=je(window),pt=ut.getPrototypeOf(ct);let{Error:dt}=je(window),{cookie:ht}=Le(document);let{document:wt,getComputedStyle:gt,isExtensionContext:yt,variables:mt,Array:bt,MutationObserver:vt,Object:Et,XPathEvaluator:St,XPathExpression:Mt,XPathResult:Tt}=je(window),{querySelectorAll:xt}=wt,Ot=xt&&i(xt,wt);const{assign:Pt,setPrototypeOf:jt}=Et;class Nt extends Mt{evaluate(...e){return jt(o(super.evaluate,this,e),Tt.prototype)}}class Lt extends St{createExpression(...e){return jt(o(super.createExpression,this,e),Nt.prototype)}}function kt(e){if(mt.hidden.has(e))return;!function(e){yt&&"function"==typeof checkElement&&checkElement(e)}(e),mt.hidden.add(e);let{style:t}=je(e),r=je(t,"CSSStyleDeclaration"),n=je([]),{debugCSSProperties:o}=S;for(let[e,t]of o||[["display","none"]])r.setProperty(e,t,"important"),n.push([e,r.getPropertyValue(e)]);new vt((()=>{for(let[e,t]of n){let n=r.getPropertyValue(e),o=r.getPropertyPriority(e);n==t&&"important"==o||r.setProperty(e,t,"important")}})).observe(e,{attributes:!0,attributeFilter:["style"]})}function Ct(e){let t=e;if(t.startsWith("xpath(")&&t.endsWith(")")){let t=function(e){let t=e;if(t.startsWith("xpath(")&&t.endsWith(")")){let e=t.slice(6,-1),r=(new Lt).createExpression(e,null),n=Tt.ORDERED_NODE_SNAPSHOT_TYPE;return e=>{if(!e)return;let t=r.evaluate(wt,n,null),{snapshotLength:o}=t;for(let r=0;r<o;r++)e(t.snapshotItem(r))}}return t=>Ot(e).forEach(t)}(e);return()=>{let e=je([]);return t((t=>e.push(t))),e}}return()=>bt.from(Ot(e))}let{ELEMENT_NODE:At,TEXT_NODE:Wt,prototype:$t}=Node,{prototype:Dt}=Element,{prototype:Ht}=HTMLElement,{console:zt,variables:Rt,DOMParser:Ft,Error:It,MutationObserver:Jt,Object:Vt,ReferenceError:Bt}=je(window),{getOwnPropertyDescriptor:Ut}=Vt;function _t(e,t){return We}je(window);const{Map:Xt,MutationObserver:qt,Object:Gt,Set:Kt,WeakSet:Yt}=je(window);let Zt=Element.prototype,{attachShadow:Qt}=Zt,er=new Yt,tr=new Xt,rr=null;const{Error:nr,JSON:or,Map:ir,Object:sr}=je(window);let ar=null;let{Error:lr,JSON:cr,Map:ur,Object:fr}=je(window),pr=null;let{Error:dr}=je(window);let{Error:hr,Map:wr,Object:gr,console:yr}=je(window),{toString:mr}=Function.prototype,br=EventTarget.prototype,{addEventListener:vr}=br,Er=null;let Sr,{URL:Mr,fetch:Tr}=je(window),{delete:xr,has:Or}=l(URLSearchParams.prototype);const Pr={"abort-current-inline-script":function(e,t=null){const r=De("abort-current-inline-script"),n=t?Re(t):null,o=Fe(),i=je(document).currentScript;let a=window;const l=je(e).split("."),c=je(l).pop();for(let e of je(l))if(a=a[e],!a||"object"!=typeof a&&"function"!=typeof a)return void r(l," is not found");const{get:u,set:f}=ut.getOwnPropertyDescriptor(a,c)||{};let p=a[c];void 0===p&&r("The property",c,"doesn't exist yet. Check typos.");const d=()=>{const e=je(document).currentScript;if(e instanceof pt&&""==je(e,"HTMLScriptElement").src&&e!=i&&(!n||n.test(je(e).textContent)))throw r(l," is aborted \n",e),new ft(o)};et(a,c,{get(){return d(),u?s(u,this):p},set(e){d(),f?s(f,this,e):p=e}}),tt(o)},"abort-on-iframe-property-read":function(...e){ot(e,!0,!1)},"abort-on-iframe-property-write":function(...e){ot(e,!1,!0)},"abort-on-property-read":function(e,t){rt("abort-on-property-read",window,e,!("false"===t))},"abort-on-property-write":function(e,t){nt("abort-on-property-write",window,e,!("false"===t))},"cookie-remover":function(e){if(!e)throw new dt("[cookie-remover snippet]: No cookie to remove.");let t=De("cookie-remover"),r=Re(e);if(je(/^http|^about/).test(location.protocol)){t("Parsing cookies for matches");for(const e of je(je(ht()).split(";").filter((e=>r.test(je(e).split("=")[0]))))){let r=je(location.hostname),n=je(e).split("=")[0],o="expires=Thu, 01 Jan 1970 00:00:00 GMT",i="path=/",s="domain="+r.slice(r.indexOf(".")+1);ht(`${je(n).trim()}=;${o};${i};${s}`),t(`Set expiration date on ${n}`)}}else t("Snippet only works for http or https and about.")},debug:function(){ke=!0},"freeze-element":function(e,t="",...r){let n,i,a=!1,l=!1,c=je(r).filter((e=>!h(e))),u=je(r).filter((e=>h(e))).map(Re),f=Fe(),p=Ct(e);!function(){let r=je(t).split("+");1===r.length&&""===r[0]&&(r=[]);for(let t of r)switch(t){case"subtree":a=!0;break;case"abort":l=!0;break;default:throw new It("[freeze] Unknown option passed to the snippet. [selector]: "+e+" [option]: "+t)}}();let d={selector:e,shouldAbort:l,rid:f,exceptionSelectors:c,regexExceptions:u,changeId:0};function h(e){return e.length>=2&&"/"==e[0]&&"/"==e[e.length-1]}function w(){i=p(),g(i,!1)}function g(e,t=!0){for(let r of e)Rt.frozen.has(r)||(Rt.frozen.set(r,d),!t&&a&&new Jt((e=>{for(let t of je(e))g(je(t,"MutationRecord").addedNodes)})).observe(r,{childList:!0,subtree:!0}),a&&je(r).nodeType===At&&g(je(r).childNodes))}function y(e,...t){$e(`[freeze][${e}] `,...t)}function m(e,t,r,n){let o=n.selector,i=n.changeId,s="string"==typeof e,a=n.shouldAbort?"aborting":"watching";switch(zt.groupCollapsed(`[freeze][${i}] ${a}: ${o}`),r){case"appendChild":case"append":case"prepend":case"insertBefore":case"replaceChild":case"insertAdjacentElement":case"insertAdjacentHTML":case"insertAdjacentText":case"innerHTML":case"outerHTML":y(i,s?"text: ":"node: ",e),y(i,"added to node: ",t);break;case"replaceWith":case"after":case"before":y(i,s?"text: ":"node: ",e),y(i,"added to node: ",je(t).parentNode);break;case"textContent":case"innerText":case"nodeValue":y(i,"content of node: ",t),y(i,"changed to: ",e)}y(i,`using the function "${r}"`),zt.groupEnd(),n.changeId++}function b(e,t){if(t)for(let r of t)if(r.test(e))return!0;return!1}function v(e){throw new Bt(e)}function E(e,t,r,n){let o=new Ft,{body:i}=je(o.parseFromString(e,"text/html")),s=S(je(i).childNodes,t,r,n);return je(s).map((e=>{switch(je(e).nodeType){case At:return je(e).outerHTML;case Wt:return je(e).textContent;default:return""}})).join("")}function S(e,t,r,n){let o=je([]);for(let i of e)M(i,t,r,n)&&o.push(i);return o}function M(e,t,r,n){let o=n.shouldAbort,i=n.regexExceptions,s=n.exceptionSelectors,a=n.rid;if("string"==typeof e){let s=e;return!!b(s,i)||(Ce()&&m(s,t,r,n),o&&v(a),Ce())}let l=e;switch(je(l).nodeType){case At:return!!function(e,t){if(t){let r=je(e);for(let e of t)if(r.matches(e))return!0}return!1}(l,s)||(o&&(Ce()&&m(l,t,r,n),v(a)),!!Ce()&&(kt(l),m(l,t,r,n),!0));case Wt:return!!b(je(l).textContent,i)||(Ce()&&m(l,t,r,n),o&&v(a),!1);default:return!0}}function T(e,t,r,n){let i=Ut(e,t)||{},a=i.get&&s(i.get,e)||i.value;if(a)return{get:()=>function(...e){if(r(this)){let r=n(this);if(r){let n=e[0];if(!M(n,this,t,r))return n}}return o(a,this,e)}}}function x(e,t,r,n){let i=Ut(e,t)||{},a=i.get&&s(i.get,e)||i.value;if(a)return{get:()=>function(...e){if(!r(this))return o(a,this,e);let i=n(this);if(!i)return o(a,this,e);let s=S(e,this,t,i);return s.length>0?o(a,this,s):void 0}}}function O(e,t,r,n){let i=Ut(e,t)||{},a=i.get&&s(i.get,e)||i.value;if(a)return{get:()=>function(...e){let[i,l]=e,c="afterbegin"===i||"beforeend"===i;if(r(this,c)){let e=n(this,c);if(e){let r,n=c?this:je(this).parentNode;switch(t){case"insertAdjacentElement":if(!M(l,n,t,e))return l;break;case"insertAdjacentHTML":return r=E(l,n,t,e),r?s(a,this,i,r):void 0;case"insertAdjacentText":if(!M(l,n,t,e))return}}}return o(a,this,e)}}}function P(e,t,r,n){let o=Ut(e,t)||{},{set:i}=o;if(i)return{set(e){if(!r(this))return s(i,this,e);let o=n(this);if(!o)return s(i,this,e);let a=E(e,this,t,o);return a?s(i,this,a):void 0}}}function j(e,t,r,n){let o=Ut(e,t)||{},{set:i}=o;if(i)return{set(e){if(!r(this))return s(i,this,e);let o=n(this);return o?M(e,this,t,o)?s(i,this,e):void 0:s(i,this,e)}}}Rt.frozen.has(document)||(Rt.frozen.set(document,!0),function(){let e;function t(e){return e&&Rt.frozen.has(e)}function r(e){try{return e&&(Rt.frozen.has(e)||Rt.frozen.has(je(e).parentNode))}catch(e){return!1}}function n(e,t){try{return e&&(Rt.frozen.has(e)&&t||Rt.frozen.has(je(e).parentNode)&&!t)}catch(e){return!1}}function o(e){return Rt.frozen.get(e)}function i(e){try{if(Rt.frozen.has(e))return Rt.frozen.get(e);let t=je(e).parentNode;return Rt.frozen.get(t)}catch(e){}}function s(e,t){try{if(Rt.frozen.has(e)&&t)return Rt.frozen.get(e);let r=je(e).parentNode;return Rt.frozen.get(r)}catch(e){}}e=T($t,"appendChild",t,o),et($t,"appendChild",e),e=T($t,"insertBefore",t,o),et($t,"insertBefore",e),e=T($t,"replaceChild",t,o),et($t,"replaceChild",e),e=x(Dt,"append",t,o),et(Dt,"append",e),e=x(Dt,"prepend",t,o),et(Dt,"prepend",e),e=x(Dt,"replaceWith",r,i),et(Dt,"replaceWith",e),e=x(Dt,"after",r,i),et(Dt,"after",e),e=x(Dt,"before",r,i),et(Dt,"before",e),e=O(Dt,"insertAdjacentElement",n,s),et(Dt,"insertAdjacentElement",e),e=O(Dt,"insertAdjacentHTML",n,s),et(Dt,"insertAdjacentHTML",e),e=O(Dt,"insertAdjacentText",n,s),et(Dt,"insertAdjacentText",e),e=P(Dt,"innerHTML",t,o),et(Dt,"innerHTML",e),e=P(Dt,"outerHTML",r,i),et(Dt,"outerHTML",e),e=j($t,"textContent",t,o),et($t,"textContent",e),e=j(Ht,"innerText",t,o),et(Ht,"innerText",e),e=j($t,"nodeValue",t,o),et($t,"nodeValue",e)}()),n=new Jt(w),n.observe(document,{childList:!0,subtree:!0}),w()},"hide-if-shadow-contains":function(e,t="*"){let r=`${e}\\${t}`;tr.has(r)||tr.set(r,[Re(e),t,_t()]);const n=De("hide-if-shadow-contain");rr||(rr=new qt((e=>{let t=new Kt;for(let{target:r}of je(e)){let e=je(r).parentNode;for(;e;)[r,e]=[e,je(r).parentNode];if(!er.has(r)&&!t.has(r)){t.add(r);for(let[e,t,o]of tr.values())if(e.test(je(r).textContent)){let e=je(r.host).closest(t);e&&(o(),je(r).appendChild(document.createElement("style")).textContent=":host {display: none !important}",kt(e),er.add(r),n("Hiding: ",e," for params: ",...arguments))}}}})),Gt.defineProperty(Zt,"attachShadow",{value:c(Qt,(function(){let e=o(Qt,this,arguments);return n("attachShadow is called for: ",e),rr.observe(e,{childList:!0,characterData:!0,subtree:!0}),e}))}))},"json-override":function(e,t,r="",n=""){if(!e)throw new nr("[json-override snippet]: Missing paths to override.");if(void 0===t)throw new nr("[json-override snippet]: No value to override with.");if(!ar){let e=De("json-override"),{parse:t}=or;ar=new ir,sr.defineProperty(window.JSON,"parse",{value:c(t,(function(r){let n=o(t,this,arguments);for(let{prune:t,needle:o,filter:i,value:s}of ar.values())if(!i||i.test(r)){if(je(o).some((e=>!st(n,e))))return n;for(let r of t){let t=st(n,r);void 0!==t&&(e(`Found ${r} replaced it with ${s}`),t[0][t[1]]=lt(s))}}return n}))}),e("Wrapped JSON.parse for override")}ar.set(e,{prune:je(e).split(/ +/),needle:r.length?je(r).split(/ +/):[],filter:n?Re(n):null,value:t})},"json-prune":function(e,t=""){if(!e)throw new lr("Missing paths to prune");if(!pr){let e=De("json-prune"),{parse:t}=cr;pr=new ur,fr.defineProperty(window.JSON,"parse",{value:c(t,(function(){let r=o(t,this,arguments);for(let{prune:t,needle:n}of pr.values()){if(je(n).some((e=>!st(r,e))))return r;for(let n of t){let t=st(r,n);void 0!==t&&(e(`Found ${n} and deleted`),delete t[0][t[1]])}}return r}))}),e("Wrapped JSON.parse for prune")}pr.set(e,{prune:je(e).split(/ +/),needle:t.length?je(t).split(/ +/):[]})},"override-property-read":function(e,t){if(!e)throw new dr("[override-property-read snippet]: No property to override.");if(void 0===t)throw new dr("[override-property-read snippet]: No value to override with.");let r=De("override-property-read"),n=lt(t);r(`Overriding ${e}.`),et(window,e,{get:()=>(r(`${e} override done.`),n),set(){}})},"prevent-listener":function(e,t,r){if(!e)throw new hr("[prevent-listener snippet]: No event type.");if(!Er){Er=new wr;let e=De("[prevent]");gr.defineProperty(br,"addEventListener",{value:c(vr,(function(t,r){for(let{evt:n,handlers:o,selectors:i}of Er.values()){if(!n.test(t))continue;let a=this instanceof Element;for(let l=0;l<o.length;l++){let c=o[l],u=i[l],f=()=>c.test(s(mr,"function"==typeof r?r:r.handleEvent));if((!c||f())&&(!u||a&&je(this).matches(u)))return void(Ce()&&(yr.groupCollapsed("DEBUG [prevent] was successful"),e(`type: ${t} matching ${n}`),e("handler:",r),c&&e(`matching ${c}`),u&&e("on element: ",this,` matching ${u}`),e("was prevented from being added"),yr.groupEnd()))}}return o(vr,this,arguments)}))}),e("Wrapped addEventListener")}Er.has(e)||Er.set(e,{evt:Re(e),handlers:[],selectors:[]});let{handlers:n,selectors:i}=Er.get(e);n.push(t?Re(t):null),i.push(r)},"strip-fetch-query-parameter":function(e,t=null){const r=De("strip-fetch-query-parameter");Sr||(Sr=new Map,window.fetch=c(Tr,((...e)=>{let[t]=e;if("string"==typeof t){let n=new Mr(t);for(let[o,i]of Sr)i&&!i.test(t)||Or(n.searchParams,o)&&(r(`${o} has been stripped from url ${t}`),xr(n.searchParams,o),e[0]=n.href)}return o(Tr,self,e)}))),Sr.set(e,t&&Re(t))},trace:function(...e){o($e,null,e)}};
const snippets=Pr;
let context;
for (const [name, ...args] of filters) {
if (snippets.hasOwnProperty(name)) {
try { context = snippets[name].apply(context, args); }
catch (error) { console.error(error); }
}
}
context = void 0;
};
const main_graph = new Map([["abort-current-inline-script",null],["abort-on-iframe-property-read",null],["abort-on-iframe-property-write",null],["abort-on-property-read",null],["abort-on-property-write",null],["cookie-remover",null],["debug",null],["freeze-element",null],["hide-if-shadow-contains",null],["json-override",null],["json-prune",null],["override-property-read",null],["prevent-listener",null],["strip-fetch-query-parameter",null],["trace",null]]);
main_callback.get = snippet => main_graph.get(snippet);
main_callback.has = snippet => main_graph.has(snippet);
/* harmony default export */ const main = (main_callback);
;// CONCATENATED MODULE: ./node_modules/@eyeo/snippets/index.mjs






;// CONCATENATED MODULE: ./adblock-betafish/alias/contentFiltering.js
/*
 * Same as the original source adblockpluschrome/lib/contentFiltering.js
 * except:
 * - updated require paths
 * - added fetch() of second snippet library
 */
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module contentFiltering */




function loadSnippets() {
  ewe_api.snippets.setLibrary({
    injectedCode: main,
    isolatedCode: ml
  });
};
loadSnippets();


/***/ }),

/***/ 3398:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "QO": () => (/* binding */ showIconBadgeCTA),
/* harmony export */   "ec": () => (/* binding */ NEW_BADGE_REASONS),
/* harmony export */   "vo": () => (/* binding */ getNewBadgeTextReason)
/* harmony export */ });
/* unused harmony exports statsInIconKey, stopIconAnimation, startIconAnimation */
/* harmony import */ var info__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(755);
/* harmony import */ var _storage_tab_session_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(440);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_allowlisting__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7718);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2209);
/* harmony import */ var _utilities_background_bg_functions_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7337);
/*
 * Same as the original source adblockpluschrome/lib/icon.js
 * except:
 * - updated image file names from 'abp-' to 'ab-'
 * - updated the 'import' paths
 * - use the term 'whitelisted' instead of 'allowlisted' for now
 * - call renderIcons() at the end of the module for all platforms,
 *   not just Chromium
 * - added the showIconBadgeCTA, getNewBadgeTextReason functions
 */
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module icon */








const ANIMATION_LOOPS = 3;
const FRAME_IN_MS = 100;

const statsInIconKey = 'current_show_statsinicon';

let frameOpacities = calculateFrameOpacities(9, 7);
let frameOpacitiesCritical = calculateFrameOpacities(5, 3);

let stopRequested = false;
let canUpdateIcon = true;
let notRunning = Promise.resolve();
let allowlistedState = new _storage_tab_session_js__WEBPACK_IMPORTED_MODULE_1__/* .TabSessionStorage */ .H("icon:allowlistedState");

let icons = [null, null];

function easeOut(progress) {
  // This is merely an approximation to the built-in ease-out timing function
  // https://css-tricks.com/emulating-css-timing-functions-javascript/
  return 1 - Math.pow(1 - progress, 1.675);
}

function calculateFrameOpacities(keyframeFrames, transitionFrames) {
  let opacities = [];

  // Show second half of first keyframe
  // Omit first frame because it's only shown after the first timeout
  for (let i = 0; i < keyframeFrames / 2 - 1; i++)
    opacities.push(0);
  // Transition from first to second keyframe
  for (let i = 0; i < transitionFrames; i++)
    opacities.push(easeOut((i + 1) / (transitionFrames + 1)));
  // Show second keyframe
  for (let i = 0; i < keyframeFrames; i++)
    opacities.push(1);
  // Transition from second to first keyframe
  for (let i = 0; i < transitionFrames; i++)
    opacities.push(easeOut((transitionFrames - i) / (transitionFrames + 1)));
  // Show first half of first keyframe
  // Omit last frame due to an additional timeout that resets the icon
  for (let i = 0; i < keyframeFrames / 2 - 1; i++)
    opacities.push(0);

  return opacities;
}

async function loadImage(url) {
  let response = await fetch(url);
  let blob = await response.blob();
  return createImageBitmap(blob);
}

async function renderIcons() {
  let paths = [
    "icons/ab-16.png", "icons/ab-16-whitelisted.png",
    "icons/ab-32.png", "icons/ab-32-whitelisted.png"
  ];

  for (let path of paths) {
    let image = await loadImage(path);
    let [, size, allowlisted] = /\/ab-(16|32)(-whitelisted)?\./.exec(path);

    let canvas = new OffscreenCanvas(size, size);
    let context = canvas.getContext("2d");
    let imageData = icons[!!allowlisted | 0] || {};

    context.globalAlpha = 1;
    context.drawImage(image, 0, 0);
    imageData[size] = context.getImageData(0, 0, size, size);

    icons[!!allowlisted | 0] = imageData;
  }
}

async function setIcon(page, opacity, frames) {
  opacity = opacity || 0;
  let allowlisted = !!(await allowlistedState.get(page.id));

  if (!frames) {
    if (opacity > 0.5) {
      (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_3__/* .setIconPath */ .c4)(
        page.id,
        "/icons/ab-$size-notification.png"
      );
    }
    else if (icons[allowlisted | 0]) {
      (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_3__/* .setIconImageData */ .k8)(page.id, icons[allowlisted | 0]);
    }
    else {
      (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_3__/* .setIconPath */ .c4)(
        page.id,
        "/icons/ab-$size" + (allowlisted ? "-allowlisted" : "") + ".png"
      );
    }
  }
  else {
    browser.action.setIcon({
      tabId: page.id,
      imageData: frames["" + opacity + allowlisted]
    });
  }
}

_vendor_adblockplusui_adblockpluschrome_lib_allowlisting__WEBPACK_IMPORTED_MODULE_2__/* .allowlistingState.addListener */ ._o.addListener("changed", async (page, isAllowlisted) => {
  await allowlistedState.set(page.id, isAllowlisted);
  if (canUpdateIcon)
    await setIcon(page);
});

async function renderFrames(opacities) {
  let images = await Promise.all([
    loadImage("icons/ab-16.png"),
    loadImage("icons/ab-16-whitelisted.png"),
    loadImage("icons/ab-16-whitelisted.png"),
    loadImage("icons/ab-20.png"),
    loadImage("icons/ab-20-whitelisted.png"),
    loadImage("icons/ab-20-whitelisted.png"),
    loadImage("icons/ab-32.png"),
    loadImage("icons/ab-32-whitelisted.png"),
    loadImage("icons/ab-32-whitelisted.png"),
    loadImage("icons/ab-40.png"),
    loadImage("icons/ab-40-whitelisted.png"),
    loadImage("icons/ab-40-whitelisted.png"),
  ]);
  opacities = new Set(opacities);
  let imageMap = {
    16: { base: [images[0], images[1]], overlay: images[2] },
    20: { base: [images[3], images[4]], overlay: images[5] },
    32: { base: [images[6], images[7]], overlay: images[8] },
    40: { base: [images[9], images[10]], overlay: images[11] }
  };

  let frames = {};
  let canvas = new OffscreenCanvas(0, 0);
  let context = canvas.getContext("2d");

  for (let allowlisted of [false, true]) {
    for (let opacity of opacities) {
      let imageData = {};
      let sizes = [16, 20, 32, 40];
      for (let size of sizes) {
        canvas.width = size;
        canvas.height = size;
        context.globalAlpha = 1;
        context.drawImage(imageMap[size]["base"][allowlisted | 0], 0, 0);
        context.globalAlpha = opacity;
        context.drawImage(imageMap[size]["overlay"], 0, 0);
        imageData[size] = context.getImageData(0, 0, size, size);
      }
      frames["" + opacity + allowlisted] = imageData;
    }
  }

  return frames;
}

async function animateIcon(opacities, frames) {
  let tabs = await browser.tabs.query({ active: true });
  let pages = tabs.map(tab => new ext.Page(tab));

  let animationLoop = 0;
  let animationStep = 0;
  let numberOfFrames = opacities.length;
  let opacity = 0;

  let onActivated = async page => {
    pages.push(page);
    await setIcon(page, opacity, frames);
    toggleBadge(page.id, true);
  };
  ext.pages.onActivated.addListener(onActivated);

  canUpdateIcon = false;
  for (let page of pages)
    toggleBadge(page.id, true);
  return new Promise((resolve, reject) => {
    let interval = setInterval(async () => {
      let oldOpacity = opacity;
      opacity = opacities[animationStep++];

      if (opacity != oldOpacity) {
        for (let page of pages) {
          if (await allowlistedState.has(page.id))
            await setIcon(page, opacity, frames);
        }
      }

      if (animationStep > numberOfFrames) {
        if (++animationLoop > ANIMATION_LOOPS - 1 || stopRequested) {
          clearInterval(interval);
          ext.pages.onActivated.removeListener(onActivated);
          for (let page of pages)
            toggleBadge(page.id, false);
          canUpdateIcon = true;
          resolve();
        }
        else {
          animationStep = 0;
        }
      }
    }, FRAME_IN_MS);
  });
}

/**
 * Stops to animate the browser action icon
 * after the current interval has been finished.
 *
 * @return {Promise} A promise that is fullfilled when
 *                   the icon animation has been stopped.
 */
async function stopIconAnimation() {
  stopRequested = true;
  await notRunning;
  stopRequested = false;
}

/**
 * Starts to animate the browser action icon to indicate a pending notifcation.
 * If the icon is already animated, it replaces the previous
 * animation as soon as the current interval has been finished.
 *
 * @param {string} type  The notification type (i.e: "information" or
 *                       "critical".)
 */
function startIconAnimation(type) {
  let opacities = frameOpacities;
  if (type == "critical")
    opacities = frameOpacitiesCritical;

  notRunning = Promise.all([renderFrames(opacities), stopIconAnimation()])
    .then(results => {
      if (stopRequested)
        return;

      let frames = results[0];
      return animateIcon(opacities, frames);
    });
}

renderIcons();

/**
 * Returns the Object containing all of the reasons the text on the toolbar icon / badge is 'new'
 *
 */
const NEW_BADGE_REASONS = {
  SEVEN_DAY: 'seven day',
  UPDATE: 'update',
  VPN_CTA: 'vpn cta',
  FREE_DC_UPDATE: 'free dc update',
};

/**
 * Handles the display of the New badge on the toolbar icon.
 * @param {Boolean} [showBadge] true shows the badge, false removes the badge
 */

let newBadgeTextReason = "";

async function showIconBadgeCTA(showBadge, reason) {
  if (!License.shouldShowPremiumCTA()) {
    return;
  }
  if (showBadge) {
    let newBadgeText = browser.i18n.getMessage('new_badge');
    // Text that exceeds 4 characters is truncated on the toolbar badge,
    // so we default to English
    if (!newBadgeText || newBadgeText.length >= 5) {
      newBadgeText = 'New';
    }
    const storedValue = await (0,_utilities_background_bg_functions_js__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageGetHelper */ .nX)(statsInIconKey);
    if (!storedValue) {  // don't overwrite the original, saved value
      (0,_utilities_background_bg_functions_js__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageSetHelper */ .rJ)(statsInIconKey, Prefs.show_statsinicon);
    }
    Prefs.show_statsinicon = false;
    // wait 10 seconds to allow any other tasks to finish
    setTimeout(() => {
      // process all currently opened tabs
      browser.tabs.query({}).then((tabs) => {
        for (const tab of tabs) {
          if (tab.url && tab.url.startsWith('http')) {
            (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_3__/* .setBadge */ .q_)(tab.id, { color: '#03bcfc', number: newBadgeText });
            newBadgeTextReason = reason || '';
          }
        }
      });
    }, 10000); // 10 seconds
  } else {
    // Restore show_statsinicon if we previously stored its value
    const storedValue = await (0,_utilities_background_bg_functions_js__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageGetHelper */ .nX)(statsInIconKey);
    if (typeof storedValue === 'boolean') {
      Prefs.show_statsinicon = storedValue;
      (0,_utilities_background_bg_functions_js__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageDeleteHelper */ .lE)(statsInIconKey); // remove the data, since we no longer need it
      browser.tabs.query({}).then((tabs) => {
        for (const tab of tabs) {
          (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_3__/* .setBadge */ .q_)(tab.id, { number: '' });
        }
      });
      browser.action.setBadgeText({ text: '' });
    }
  }
};

/**
 * Returns the String reason the text on the toolbar icon / badge is 'new'
 *
 */
function getNewBadgeTextReason() {
  return newBadgeTextReason;
};


/***/ }),

/***/ 1478:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__);



browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.command !== "parseFilter" || !message.filterTextToParse) {
    return;
  }
  sendResponse(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__.filters.validate(message.filterTextToParse));
});


/***/ }),

/***/ 4428:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "B": () => (/* binding */ Prefs)
/* harmony export */ });
/* harmony import */ var info__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(755);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_messaging_events_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5094);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_messaging_port_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6960);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_events_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(9876);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module prefs */








const keyPrefix = "pref:";

let eventEmitter = new _vendor_adblockplusui_adblockpluschrome_lib_events_js__WEBPACK_IMPORTED_MODULE_4__/* .EventEmitter */ .v();
let overrides = Object.create(null);

/** @lends module:prefs.Prefs */
let defaults = Object.create(null);

/**
 * The application version as set during initialization. Used to detect updates.
 *
 * @type {string}
 */
defaults.currentVersion = "";
/**
 * @see https://adblockplus.org/en/preferences#documentation_link
 * @type {string}
 */
defaults.documentation_link = "https://adblockplus.org/redirect?link=%LINK%&lang=%LANG%";
/**
 * The total number of requests blocked by the extension.
 *
 * @type {number}
 */
defaults.blocked_total = 0;
/**
 * Public keys used to verify authenticity of entities that are authorized to
 * use the bypass API.
 *
 * @type {string[]}
 */
defaults.bypass_authorizedKeys = [
    `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsCtBp9/0qCM5lp0lJVSx
IAGgWZsX50xeJfBq6OkfsI+305Yj0igVfyVASOaC1fc2JRHD/uAOKk47SiPcBkiz
mPHUt9ziOtAEkW7GrU6gaVOSwp26vUbSuvg9ouut5U2m8ULOyzp+WyU8nCzTPV5o
AvCta04bK9or4UnyTRKyqADlNwz7WnH+0QiHYbgtfE/E3rowEoMEAC44C7OiawCm
rnBXAkyBJnh1oEfUVI4LurxVl/zLo8MWfzErkaJy1FpsFR3F3L9ymKXpmxbhlDdX
0rxjwnRD/2sCWW3SJOU26gfFgu/NI6LGxcWdPrucdkoOOOnNQjjDlhGYPTqqxugH
/I5r+tAeUrrwKjmFcpMdxX7dfw1LoBoZCZnShZKlGKDqXf985Dc+3StbGWcxwNn9
l9/Ho6YFA7fKpBKEED2V+SrDb4RCkScvOOiMOI1v5bwsLinUd/2yxRDrO25uwU7h
r4LqmOguqjjLGF17d2WvG5D+LIQwgusxQd9Jk/n9PRdwtVGJhSDsDc8el2nKIqk9
ofk3YJzAIbS9iHQ2LuHubuhzYjkxRLcdSbt1oONHCSHeecZn/OXwYeTvU7Po1KPW
emi3XUpyjylUe9ONlw50lynwRw117bNHQDDHwKPoVW1cjoAtRsCnviFHPWTPjQKe
A2LS9qa7eNdIonehrzG20cECAwEAAQ==`
];
/**
 * Whether to show a badge in the toolbar icon indicating the number
 * of blocked ads.
 *
 * @type {boolean}
 */
defaults.show_statsinicon = true;
/**
 * Whether to show the "Block element" context menu entry.
 *
 * @type {boolean}
 */
defaults.shouldShowBlockElementMenu = true;

/**
 * Whether to show tracking warning in options page when both
 * Acceptable Ads and subscription of type "Privacy" are enabled.
 *
 * @type {boolean}
 */
defaults.ui_warn_tracking = true;

/**
 * Whether to show the developer tools panel.
 *
 * @type {boolean}
 */
defaults.show_devtools_panel = true;

/**
 * Prevents unsolicited UI elements from showing up after installation. This
 * preference isn't set by the extension but can be pre-configured externally.
 *
 * @see https://adblockplus.org/development-builds/suppressing-the-first-run-page-on-chrome
 * @type {boolean}
 */
defaults.suppress_first_run_page = false;

/**
 * Additonal subscriptions to be automatically added when the extension is
 * loaded. This preference isn't set by the extension but can be pre-configured
 * externally.
 *
 * @type {string[]}
 */
defaults.additional_subscriptions = [];

/**
 * The version of major updates that the user is aware of. If it's too low,
 * the updates page will be shown to inform the user about intermediate changes.
 *
 * @type {number}
 */
defaults.last_updates_page_displayed = 0;

/**
 * Causes elements targeted by element hiding (and element hiding emulation)
 * to be highlighted instead of hidden.
 *
 * @type {boolean}
 */
defaults.elemhide_debug = false;

/**
 * Whether to recommend language filter lists to user.
 *
 * @type {boolean}
 */
defaults.recommend_language_subscriptions = false;

/**
 * Premium user ID
 *
 * @type {string}
 */
defaults.premium_user_id = "";

/**
 * Map of commands
 *
 * @type {Object}
 */
defaults.ipm_commands = {};

/**
 * Map of command stats
 *
 * @type {Object}
 */
defaults.ipm_commands_stats = {};

/**
 * Trusted origin for URLs used in IPMs
 *
 * @type {string}
 */
defaults.ipm_safe_origin = "https://getadblock.com";

/**
 * Minimum log level
 *
 * @type {number}
 */
defaults.logger_log_level = 3;

/**
 * Map of command stats
 *
 * @type {Object}
 */
defaults.onpage_dialog_command_stats = {};

/**
 * Map of on-page dialog timing configurations
 *
 * @type {Object}
 */
defaults.onpage_dialog_timing_configurations = {
    after_web_allowlisting: {
        cooldownDuration: 24,
        maxAllowlistingDelay: 2,
        maxDisplayCount: 3
    },
    revisit_web_allowlisted_site: {
        cooldownDuration: 48,
        maxDisplayCount: 3,
        minAllowlistingDelay: 48 * 60
    }
};

/**
 * Map of IPM user events
 *
 * @type {Object}
 */
defaults.ipm_events = [];

/**
 * The URL of the IPM server.
 *
 * @type {string}
 */
defaults.ipm_server_url = 'https://ipm.adblock.dev/api/stats';

/**
 * The URL of the Ping server.
 *
 * @type {string}
 */
defaults.ping_server_url = 'https://ping.getadblock.com/stats/';

/**
  * @namespace
  * @static
  */
let Prefs = {
    /**
     * Retrieves the given preference.
     *
     * @param {string} preference
     * @return {any}
     */
    get(preference) {
        let result = (preference in overrides ? overrides : defaults)[preference];

        // Object preferences are mutable, so we need to clone them to avoid
        // accidentally modifying the preference when modifying the object
        if (typeof result === "object")
            result = JSON.parse(JSON.stringify(result));

        return result;
    },

    /**
     * Resets the given preference to its default value.
     *
     * @param {string} preference
     * @return {Promise} A promise that resolves when the underlying
                         browser.storage.local.set/remove() operation completes
     */
    reset(preference) {
        return Prefs.set(preference, defaults[preference]);
    },

    /**
     * Sets the given preference.
     *
     * @param {string} preference
     * @param {any}    value
     * @return {Promise} A promise that resolves when the underlying
                         browser.storage.local.set/remove() operation completes
     */
    set(preference, value) {
        let defaultValue = defaults[preference];

        if (typeof value != typeof defaultValue)
            throw new Error("Attempt to change preference type");

        if (value == defaultValue) {
            let oldValue = overrides[preference];
            delete overrides[preference];

            // Firefox 66 fails to emit storage.local.onChanged events for falsey
            // values. https://bugzilla.mozilla.org/show_bug.cgi?id=1541449
            if (!oldValue &&
                info__WEBPACK_IMPORTED_MODULE_0__.platform == "gecko" && parseInt(info__WEBPACK_IMPORTED_MODULE_0__.platformVersion, 10) == 66)
                onStorageChanged({ [prefToKey(preference)]: { oldValue } }, "local");

            return browser.storage.local.remove(prefToKey(preference));
        }

        overrides[preference] = value;
        return (customSave.get(preference) || savePref)(preference);
    },

    /**
     * Adds a callback that is called when the
     * value of a specified preference changed.
     *
     * @param {string}   preference
     * @param {function} callback
     */
    on(preference, callback) {
        eventEmitter.on(preference, callback);
    },

    /**
     * Removes a callback for the specified preference.
     *
     * @param {string}   preference
     * @param {function} callback
     */
    off(preference, callback) {
        eventEmitter.off(preference, callback);
    },

    /**
     * Reads the documentation_link preference and substitutes placeholders.
     *
     * @param {string} linkID
     * @return {string}
     */
    getDocLink(linkID) {
        return this.documentation_link
            .replace(/%LINK%/g, linkID)
            .replace(/%LANG%/g, browser.i18n.getUILanguage());
    },

    /**
     * A promise that is fullfilled when all preferences have been loaded.
     * Wait for this promise to be fulfilled before using preferences during
     * extension initialization.
     *
     * @type {Promise}
     */
    untilLoaded: null
};

function keyToPref(key) {
    if (key.indexOf(keyPrefix) != 0)
        return null;

    return key.substr(keyPrefix.length);
}

function prefToKey(pref) {
    return keyPrefix + pref;
}

function savePref(pref) {
    return browser.storage.local.set({ [prefToKey(pref)]: overrides[pref] });
}

let customSave = new Map();
if (info__WEBPACK_IMPORTED_MODULE_0__.platform == "gecko" && parseInt(info__WEBPACK_IMPORTED_MODULE_0__.platformVersion, 10) < 66) {
    // Saving one storage value causes all others to be saved as well for
    // Firefox versions <66. Make sure that updating ad counter doesn't cause
    // the filters data to be saved frequently as a side-effect.
    let promise = null;
    customSave.set("blocked_total", pref => {
        if (!promise) {
            promise = new Promise((resolve, reject) => {
                setTimeout(
                    () => {
                        promise = null;
                        savePref(pref).then(resolve, reject);
                    },
                    60 * 1000
                );
            });
        }
        return promise;
    });
}

function addPreference(pref) {
    Object.defineProperty(Prefs, pref, {
        get() {
            return Prefs.get(pref);
        },
        set(value) {
            Prefs.set(pref, value);
        },
        enumerable: true
    });
}

function onStorageChanged(changes) {
    for (let key in changes) {
        let pref = keyToPref(key);
        if (pref && pref in defaults) {
            let change = changes[key];
            if ("newValue" in change && change.newValue != defaults[pref])
                overrides[pref] = change.newValue;
            else
                delete overrides[pref];

            eventEmitter.emit(pref);
        }
    }
}

async function init() {
    let prefs = Object.keys(defaults);
    prefs.forEach(addPreference);

    let isEdgeChromium = info__WEBPACK_IMPORTED_MODULE_0__.application == "edge" &&
        info__WEBPACK_IMPORTED_MODULE_0__.platform == "chromium";

    // When upgrading from EdgeHTML to Edge Chromium (v79) data stored in
    // browser.storage.local gets corrupted.
    // To fix it, we have to call JSON.parse twice.
    // See: https://gitlab.com/eyeo/adblockplus/adblockpluschrome/issues/152
    if (isEdgeChromium) {
        let items = await browser.storage.local.get(null);

        let fixedItems = {};
        for (let key in items) {
            if (typeof items[key] == "string") {
                try {
                    fixedItems[key] = JSON.parse(JSON.parse(items[key]));
                }
                catch (e) { }
            }
        }

        await browser.storage.local.set(fixedItems);
    }

    {
        let items = await browser.storage.local.get(prefs.map(prefToKey));
        for (let key in items)
            overrides[keyToPref(key)] = items[key];
    }

    if ("managed" in browser.storage) {
        try {
            let items = await browser.storage.managed.get(null);
            for (let key in items)
                defaults[key] = items[key];
        }
        catch (e) {
            // Opera doesn't support browser.storage.managed, but instead of simply
            // removing the API, it gives an asynchronous error which we ignore here.
        }
    }

    browser.storage.onChanged.addListener(onStorageChanged);

    // Initialize notifications_ignoredcategories pseudo preference
    Object.defineProperty(Prefs, "notifications_ignoredcategories", {
        get() {
            return _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.notifications.getIgnoredCategories();
        },
        set(value) {
            _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.notifications.toggleIgnoreCategory("*", !!value);
        },
        enumerable: true
    });

    _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.notifications.on(
        "ignored-category-added",
        () => eventEmitter.emit("notifications_ignoredcategories")
    );
    _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.notifications.on(
        "ignored-category-removed",
        () => eventEmitter.emit("notifications_ignoredcategories")
    );
}

Prefs.untilLoaded = init();

/**
 * Returns the value of the given preference key.
 *
 * @event "prefs.get"
 * @property {string} key - The preference key.
 * @returns {string|string[]|number|boolean}
 */
_vendor_adblockplusui_adblockpluschrome_lib_messaging_port_js__WEBPACK_IMPORTED_MODULE_3__/* .port.on */ .N.on("prefs.get", (message, sender) => Prefs[message.key]);

/**
 * Sets the value of the given preference key to the given value.
 *
 * @event "prefs.set"
 * @property {string} key - The preference key.
 * @property {string} value - The value to set.
 * @returns {string|string[]|number|boolean|undefined}
 */
_vendor_adblockplusui_adblockpluschrome_lib_messaging_port_js__WEBPACK_IMPORTED_MODULE_3__/* .port.on */ .N.on(
    "prefs.set",
    async (message, sender) => Prefs[message.key] = message.value
);

/**
 * Toggles the value of the given preference key.
 *
 * @event "prefs.toggle"
 * @property {string} key - The preference key
 * @returns {?boolean}
 */
_vendor_adblockplusui_adblockpluschrome_lib_messaging_port_js__WEBPACK_IMPORTED_MODULE_3__/* .port.on */ .N.on("prefs.toggle", async (message, sender) => {
    if (message.key == "notifications_ignoredcategories")
        return _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.notifications.toggleIgnoreCategory("*");

    return Prefs[message.key] = !Prefs[message.key];
});

/**
 * Returns a link to a page on our website, in the user's locale if possible.
 *
 * @event "prefs.getDocLink"
 * @property {string} link
 *   The link ID to generate the doc link for.
 * @returns {string}
 */
_vendor_adblockplusui_adblockpluschrome_lib_messaging_port_js__WEBPACK_IMPORTED_MODULE_3__/* .port.on */ .N.on("prefs.getDocLink", (message, sender) => {
    let { application, platform } = info__WEBPACK_IMPORTED_MODULE_0__;
    if (platform == "chromium" && application != "opera" && application != "edge")
        application = "chrome";
    else if (platform == "gecko")
        application = "firefox";

    return Prefs.getDocLink(message.link.replace("{browser}", application));
});

(0,_vendor_adblockplusui_adblockpluschrome_lib_messaging_events_js__WEBPACK_IMPORTED_MODULE_2__/* .installHandler */ .a)("prefs", null, (emit, action) => {
    const onChanged = () => emit(Prefs[action]);
    Prefs.on(action, onChanged);
    return () => Prefs.off(action, onChanged);
});


/***/ }),

/***/ 4051:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "x": () => (/* binding */ SessionStorage)
/* harmony export */ });
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * In-memory storage for use outside of service worker context.
 * @type {Map<string,any>}
 */
const memoryStorage = new Map();

/**
 * Indicates whether we need to store in-memory data using a dedicated browser
 * API. When we're running in the context of a service worker, we can no longer
 * rely on in-memory storage.
 * @type {boolean}
 */
const useMemoryStorage = !("session" in browser.storage);

/**
 * Session storage for storing in-memory data in a way that's safe to use in
 * a service worker context.
 */
class SessionStorage {
    /**
     * Initializes session storage.
     * @param {string} namespace
     */
    constructor(namespace) {
        this._namespace = namespace;
    }

    /**
     * Generates unique storage key for storing values globally for given key.
     * @param {string} key
     * @return {string}
     */
    _getGlobalKey(key) {
        return `session:${this._namespace}:${key}`;
    }

    /**
     * Deletes session storage entry for given key.
     * @param {string} key
     * @return {Promise}
     */
    async delete(key) {
        const globalKey = this._getGlobalKey(key);
        if (useMemoryStorage)
            return memoryStorage.delete(globalKey);

        return browser.storage.session.remove(globalKey);
    }

    /**
     * Retrieves session storage entry for given key.
     * @param {string} key
     * @return {Promise<any>}
     */
    async get(key) {
        const globalKey = this._getGlobalKey(key);
        if (useMemoryStorage)
            return memoryStorage.get(globalKey);

        const storage = await browser.storage.session.get(globalKey);
        return storage[globalKey];
    }

    /**
     * Sets session storage entry for given key.
     * @param {string} key
     * @param {any} value
     * @return {Promise}
     */
    async set(key, value) {
        const globalKey = this._getGlobalKey(key);
        if (useMemoryStorage) {
            memoryStorage.set(globalKey, value);
            return;
        }

        browser.storage.session.set({ [globalKey]: value });
    }
}


/***/ }),

/***/ 440:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "H": () => (/* binding */ TabSessionStorage)
/* harmony export */ });
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_events_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9876);
/* harmony import */ var _session_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4051);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */




/**
 * Session storage instance for storing tab-specific data.
 * @type {SessionStorage<number,any>}
 */
const sessionByTabId = new _session_js__WEBPACK_IMPORTED_MODULE_0__/* .SessionStorage */ .x("_tabs");

// We need to keep track of all tab session storage instances so that we can
// notify them about tab changes. Since we cannot iterate through a WeakSet,
// and since WeakRef is not yet available in all supported browsers, this means
// that we're adding them into memory without removing them. As long as we only
// create instances only right when the extension loads, this should not create
// a memory leak though.
/**
 * List of known tab session storage instances.
 * @type {Set<TabSessionStorage>}
 */
const tabStorages = new Set();

/**
 * Session storage for storing tab-specific in-memory data in a way that's safe
 * to use in a service worker context.
 */
class TabSessionStorage extends _vendor_adblockplusui_adblockpluschrome_lib_events_js__WEBPACK_IMPORTED_MODULE_1__/* .EventEmitter */ .v {
    /**
     * Initializes session storage.
     * @param {string} namespace
     */
    constructor(namespace) {
        super();

        this._namespace = namespace;
        tabStorages.add(this);
    }

    /**
     * Deletes session storage content specific to given tab ID.
     * @param {number} tabId
     * @return {Promise}
     */
    async delete(tabId) {
        const session = await sessionByTabId.get(tabId);
        if (!session)
            return;

        delete session[this._namespace];

        if (Object.keys(session).length)
            await sessionByTabId.set(tabId, session);
        else
            await sessionByTabId.delete(tabId);
    }

    /**
     * Emits session storage event relating to given tab ID.
     * @param {string} name
     * @param {number} tabId
     */
    async emit(name, tabId) {
        const session = await sessionByTabId.get(tabId);
        if (!session)
            return;

        super.emit(name, {
            tabId,
            value: session[this._namespace]
        });
    }

    /**
     * Retrieves session storage content specific to given tab ID.
     * @param {number} tabId
     * @return {Promise<any>}
     */
    async get(tabId) {
        const session = await sessionByTabId.get(tabId);
        if (!session)
            return;

        return session[this._namespace];
    }

    /**
     * Indicates whether session storage content exists specific to given tab ID.
     * @param {number} tabId
     * @return {Promise<boolean>}
     */
    async has(tabId) {
        const session = await sessionByTabId.get(tabId);
        return session && this._namespace in session;
    }

    /**
     * Sets session storage content specific to given tab ID.
     * @param {number} tabId
     * @param {any} value
     * @return {Promise}
     */
    async set(tabId, value) {
        const session = (await sessionByTabId.get(tabId)) || {};
        session[this._namespace] = value;
        await sessionByTabId.set(tabId, session);
    }
}

/**
 * Clears tab-specific data.
 * @param {number} tabId
 * @return {Promise}
 */
async function clearStorage(tabId) {
    // Provide stored data to listeners before removing it
    const session = await sessionByTabId.get(tabId);
    if (session) {
        for (const tabStorage of tabStorages)
            await tabStorage.emit("tab-removed", tabId);
    }

    await sessionByTabId.delete(tabId);
}

/**
 * Initializes tab-specific session storage.
 */
function start() {
    // Clear tab-specific data when the tab's content changes
    ext.pages.onLoading.addListener(page => {
        void clearStorage(page.id);
    });

    // Clear tab-specific data when the tab gets removed
    ext.pages.onRemoved.addListener(tabId => {
        void clearStorage(tabId);
    });
}
start();


/***/ }),

/***/ 704:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "j": () => (/* binding */ initialize)
});

// UNUSED EXPORTS: isDataCorrupted

// EXTERNAL MODULE: ./adblock-betafish/alias/prefs.js
var prefs = __webpack_require__(4428);
// EXTERNAL MODULE: ./build/templates/info.chrome.js.tmpl
var info_chrome_js = __webpack_require__(755);
// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
;// CONCATENATED MODULE: ./node_modules/@adblockinc/rules/dist/index/adblock.json
const adblock_namespaceObject = JSON.parse('[{"id":"684A25C6-6B5D-458A-8A2B-BAC0A12B0B15","type":"ads","languages":["ar"],"title":"Liste AR+Liste FR+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=98","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","8D421590-1A68-4B68-BE50-04E17C09460E","3D60E303-1141-4775-B800-834177922876"],"url":"https://easylist-downloads.adblockplus.org/v3/full/liste_ar+liste_fr+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/liste_ar+liste_fr+easylist.txt"},{"id":"25A31255-AB36-48A4-9086-06192DE71119","type":"ads","languages":["bn","gu","hi","pa","as","mr","ml","te","kn","or","ne","si"],"title":"IndianList+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","9FAA2906-CD5C-4520-BDC4-4E098B7EA228"],"url":"https://easylist-downloads.adblockplus.org/v3/full/indianlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/indianlist+easylist.txt"},{"id":"E22C3B40-DC90-49D7-8BF5-E60904AB159A","type":"ads","languages":["bg"],"title":"Bulgarian list+EasyList","homepage":"https://stanev.org/abp/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","1638B159-F64A-4307-84E7-16AB08ED409E"],"url":"https://easylist-downloads.adblockplus.org/v3/full/bulgarian_list+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/bulgarian_list+easylist.txt"},{"id":"4B6CE485-30AB-4213-AD17-504B3F2D2825","type":"ads","languages":["cs","sk"],"title":"EasyList Czech and Slovak+EasyList","homepage":"https://adblock.sk/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","2D8C4D88-34A0-4259-9098-30D28BA674BC"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistczechslovak+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistczechslovak+easylist.txt"},{"id":"96932CD9-6DDF-4D97-B92F-FDF747B6FAA2","type":"ads","languages":["no","nb","nn","da","is","fo","kl","sv","fi"],"title":"Dandelion Sprout\'s Nordic Filters+EasyList","homepage":"https://github.com/DandelionSprout/adfilt","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","6D489E8D-E61C-444C-BBC5-44741773ADC2"],"url":"https://easylist-downloads.adblockplus.org/v3/full/dandelion_sprouts_nordic_filters+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/dandelion_sprouts_nordic_filters+easylist.txt"},{"id":"0CD3D105-D3B3-4652-8489-94163DE9A08F","type":"ads","languages":["de"],"title":"EasyList Germany+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","4337FB2B-A95C-44D5-B78D-11AD40F7711B"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistgermany+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistgermany+easylist.txt"},{"id":"8C13E995-8F06-4927-BEA7-6C845FB7EEBF","type":"ads","languages":["en"],"title":"EasyList","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylist.txt"},{"id":"C3D13A19-3E8D-41F5-AD64-0F3B36DDE128","type":"ads","languages":["es"],"title":"EasyList Spanish+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","C8C1AA76-15B4-4CA3-8A9C-AD38D6AFCAEC"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistspanish+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistspanish+easylist.txt"},{"id":"2CEA1481-C29C-44F1-A084-A2A019533797","type":"ads","languages":["fr"],"title":"Liste FR+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=98","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","8D421590-1A68-4B68-BE50-04E17C09460E"],"url":"https://easylist-downloads.adblockplus.org/v3/full/liste_fr+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/liste_fr+easylist.txt"},{"id":"07549D8B-F06F-4D9D-A567-929AA59E9D1D","type":"ads","languages":["he"],"title":"EasyList Hebrew+EasyList","homepage":"https://github.com/easylist/EasyListHebrew","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","AE0D9320-665E-407D-B692-1A85AE481F34"],"url":"https://easylist-downloads.adblockplus.org/v3/full/israellist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/israellist+easylist.txt"},{"id":"B7D76369-DD19-4602-80E8-2E32DDB490AC","type":"ads","languages":["id","ms"],"title":"ABPindo+EasyList","homepage":"http://abpindo.blogspot.com/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","A4A32212-E6BD-45F6-AD0F-E0FD18E8537B"],"url":"https://easylist-downloads.adblockplus.org/v3/full/abpindo+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/abpindo+easylist.txt"},{"id":"BBC07C05-66F1-42EC-BD4D-7AD495FAC84B","type":"ads","languages":["it"],"title":"EasyList Italy+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","2F0A4F0D-DF16-40D0-B0E0-5EB6791EC119"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistitaly+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistitaly+easylist.txt"},{"id":"2708BCB7-2E45-41BC-B517-1730CF532F89","type":"ads","languages":["ko"],"title":"KoreanList+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","BCE2062F-0D99-4861-A1F7-E3DFEA6DAB69"],"url":"https://easylist-downloads.adblockplus.org/v3/full/koreanlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/koreanlist+easylist.txt"},{"id":"CBE50FA2-DE3F-480C-B1D7-04289391C033","type":"ads","languages":["lt"],"title":"EasyList Lithuania+EasyList","homepage":"https://github.com/EasyList-Lithuania/easylist_lithuania","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","E89B3C08-2DED-40EA-8EE1-339B90D7B451"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistlithuania+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistlithuania+easylist.txt"},{"id":"950C88EA-2DD1-42E3-B2A2-2DF2ED15563A","type":"ads","languages":["lv"],"title":"Latvian List+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=99-latvian-list","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","51893C6C-F39E-43C5-A2EF-9545E388A2CE"],"url":"https://easylist-downloads.adblockplus.org/v3/full/latvianlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/latvianlist+easylist.txt"},{"id":"A4B88FB6-E5E5-417F-8A49-20B8244995FD","type":"ads","languages":["nl"],"title":"EasyList Dutch+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","CB94E27D-6CD1-4DB9-83D9-6B7F1A3555F6"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistdutch+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistdutch+easylist.txt"},{"id":"3D2C09D0-DF1C-4C8E-9947-A23DCEAF8F8B","type":"ads","languages":["pl"],"title":"EasyList Polish+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","9F743FCD-801B-41D0-830F-5A4EA995216E"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistpolish+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistpolish+easylist.txt"},{"id":"14DF7BE6-9675-4E07-987A-D8A1000F9FEF","type":"ads","languages":["pt"],"title":"EasyList Portuguese+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","A41441EE-BF7C-4A48-9A43-42CCEA2B2A1D"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistportuguese+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistportuguese+easylist.txt"},{"id":"EEEF75EC-B2B4-49F4-BC49-17B08266F334","type":"ads","languages":["ro"],"title":"ROList+EasyList","homepage":"https://zoso.ro/rolist/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","99166908-5FDA-4F9E-8C4C-70BB4DEEFC08"],"url":"https://easylist-downloads.adblockplus.org/v3/full/rolist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/rolist+easylist.txt"},{"id":"1B5F78CA-8B30-4BDF-B0A3-451CB2202984","type":"ads","languages":["ru","uk"],"title":"RU AdList+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=102","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","879ECB9D-8935-4506-939E-5BBB7DD09402"],"url":"https://easylist-downloads.adblockplus.org/v3/full/ruadlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt"},{"id":"1C571EC7-6E52-47CC-B04A-4B3008D0AEBE","type":"ads","languages":["vi"],"title":"ABPVN List+EasyList","homepage":"http://abpvn.com/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","03648752-31EE-4FD0-85C1-20B07C5551C3"],"url":"https://easylist-downloads.adblockplus.org/v3/full/abpvn+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/abpvn+easylist.txt"},{"id":"9BD3EA2F-889D-4CC3-B680-CF484F2BD1B9","type":"ads","languages":["zh"],"title":"EasyList China+EasyList","homepage":"https://github.com/easylist/easylistchina/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","1D7F590C-B752-4BA0-9473-6A26DE1326B1"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistchina+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt"},{"id":"0798B6A2-94A4-4ADF-89ED-BEC112FC4C7F","type":"allowing","title":"Allow nonintrusive advertising","homepage":"https://acceptableads.com/","url":"https://easylist-downloads.adblockplus.org/v3/full/exceptionrules.txt","mv2_url":"https://easylist-downloads.adblockplus.org/exceptionrules.txt"},{"id":"F12E0801-A00B-49DE-B1E3-52C9C4F90C8C","type":"allowing","title":"Allow nonintrusive advertising without third-party tracking","homepage":"https://acceptableads.com/","url":"https://easylist-downloads.adblockplus.org/v3/full/exceptionrules-privacy-friendly.txt","mv2_url":"https://easylist-downloads.adblockplus.org/exceptionrules-privacy-friendly.txt"},{"id":"CDAD4CF5-2706-42CB-B404-F5B9B61B8CAA","type":"annoyances","title":"Premium - Distraction Control","includes":["D5561090-9ADB-4EEE-AA81-101B645D9F4F","8E2D687A-3B44-46E1-BE68-2FE5441A788E","3B85CD3F-553A-45D1-AA38-6288E1C4C7B9","1E7A240E-CD85-493D-BEEF-C68A6AEA1225"],"url":"https://easylist-downloads.adblockplus.org/v3/full/adblock_premium.txt","mv2_url":"https://easylist-downloads.adblockplus.org/adblock_premium.txt"},{"id":"D4028CDD-3D39-4624-ACC7-8140F4EC3238","type":"circumvention","title":"ABP filters","homepage":"https://github.com/abp-filters/abp-filters-anti-cv","url":"https://easylist-downloads.adblockplus.org/v3/full/abp-filters-anti-cv.txt","mv2_url":"https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt"},{"id":"2090F374-29D9-4202-B2CE-139D6492D95E","type":"cookies","title":"I don\'t care about cookies","homepage":"https://www.i-dont-care-about-cookies.eu/","url":"https://easylist-downloads.adblockplus.org/v3/full/i_dont_care_about_cookies.txt","mv2_url":"https://easylist-downloads.adblockplus.org/i_dont_care_about_cookies.txt"},{"id":"5BD2BB73-459D-4A74-AF9D-A10157268350","type":"notifications","title":"Fanboy\'s Notifications Blocking List","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/fanboy-notifications.txt","mv2_url":"https://easylist-downloads.adblockplus.org/fanboy-notifications.txt"},{"id":"D72B6F06-52B2-4FED-96A2-1BF59CDD7AEC","type":"privacy","title":"EasyPrivacy","homepage":"https://easylist.to/","requires":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easyprivacy.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easyprivacy.txt"},{"id":"0A679439-445F-4DE7-84B9-88341F6DA520","type":"social","title":"Fanboy\'s Social Blocking List","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/fanboy-social.txt","mv2_url":"https://easylist-downloads.adblockplus.org/fanboy-social.txt"},{"id":"0B0296EB-1CC5-49CD-AD38-8AF27420B7E4","type":"annoyances","title":"Fanboy\'s Annoyance List","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/fanboy-annoyance.txt","mv2_url":"https://secure.fanboy.co.nz/fanboy-annoyance.txt"},{"id":"9CC3AF4D-EB89-4100-97C6-4EEE4F8A2E82","type":"cryptomining","title":"NoCoin Filter List","homepage":"https://github.com/hoshsadiq/adblock-nocoin-list/","url":"https://easylist-downloads.adblockplus.org/v3/full/nocoin.txt","mv2_url":"https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/nocoin.txt"}]');
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/port.js
var port = __webpack_require__(6960);
// EXTERNAL MODULE: ./adblock-betafish/id/background/index.ts + 1 modules
var background = __webpack_require__(6703);
;// CONCATENATED MODULE: ./adblock-betafish/alias/subscriptionInit.js
/** @module adblock-betafish/alias/subscriptionInit */

/** similar to adblockpluschrome\lib\subscriptionInit.js */

/** @module subscriptionInit */








let firstRun;
let reinitialized = false;
let dataCorrupted = false;

/**
 * If there aren't any filters, the default subscriptions are added.
 * However, if patterns.ini already did exist and/or any preference
 * is set to a non-default value, this indicates that this isn't the
 * first run, but something went wrong.
 *
 * This function detects the first run, and makes sure that the user
 * gets notified (on the first run page) if the data appears incomplete
 * and therefore will be reinitialized.
 */
async function detectFirstRun(foundSubscriptions, foundStorage) {
  let userFilters = await ewe_api.filters.getUserFilters();
  firstRun = !foundSubscriptions && !userFilters.length;

  if (firstRun && (foundStorage || prefs/* Prefs.currentVersion */.B.currentVersion))
    reinitialized = true;

  prefs/* Prefs.currentVersion */.B.currentVersion = info_chrome_js.addonVersion;
}

/**
 * In case of data corruption, we don't want to show users
 * any non-essential notifications so we need to instruct
 * the notification manager to ignore them.
 *
 * @param {boolean} value
 */
function setDataCorrupted(value) {
  dataCorrupted = value;
  ewe_api.notifications.ignored = value;
}

/*
 * Remove any subscriptions that a user or administrator has added to a
 * central / common configuration (such as the Windows Registry)
 *
 * @return {Promise}
 */

function removeSubscriptions() {
  return new Promise(function (resolve, reject) {
    if ("managed" in browser.storage) {
      browser.storage.managed.get(null).then(
        async (items) => {
          for (let key in items) {
            if (key === "remove_subscriptions" && Array.isArray(items[key]) && items[key].length) {
              for (let inx = 0; inx < items[key].length; inx++) {
                await ewe_api.subscriptions.remove(items[key][inx]);
              }
            }
          }
          resolve();
        },

        // Opera doesn't support browser.storage.managed, but instead of simply
        // removing the API, it gives an asynchronous error which we ignore here.
        () => {
          resolve();
        }
      );
    } else {
      resolve();
    }
  });
}


async function openInstalled() {
  const userID = await (0,background/* getUserId */.n)();
  browser.tabs.create({
    url:
      "https://getadblock.com/installed/?u=" +
      userID +
      "&lg=" +
      browser.i18n.getUILanguage() +
      "&dc=" +
      dataCorrupted
  });
}


async function addSubscriptions() {
  if (firstRun || reinitialized) {
    await ewe_api.subscriptions.addDefaults();
  }
  // Remove "acceptable ads" if Gecko
  if (firstRun) {
    for (let url of prefs/* Prefs.additional_subscriptions */.B.additional_subscriptions) {
      try {
        await ewe_api.subscriptions.add(url);
      }
      catch (ex) {
        console.error(`Failed to add additional subscription: ${url}`);
      }
    }
    if (info_chrome_js.platform === "gecko") {
      try {
        await ewe_api.subscriptions.remove(ewe_api.subscriptions.ACCEPTABLE_ADS_URL);
      }
      catch (ex) {
        console.error(`Failed to remove AA subscription`);
      }
    }
  }

  // Show first run page.
  if (firstRun && !prefs/* Prefs.suppress_first_run_page */.B.suppress_first_run_page) {
    openInstalled();
  }
}

/**
 * We need to check whether we can safely write to/read from storage
 * before we start relying on it for storing preferences.
 */
async function testStorage() {
  let testKey = "readwrite_test";
  let testValue = Math.random();

  try {
    await browser.storage.local.set({ [testKey]: testValue });
    let result = await browser.storage.local.get(testKey);
    if (result[testKey] != testValue)
      throw new Error("Storage test: Failed to read and write value");
  } finally {
    await browser.storage.local.remove(testKey);
  }
}

const initialize = ewe_api.start({
  bundledSubscriptions: adblock_namespaceObject,
  name: info_chrome_js.addonName,
  version: info_chrome_js.addonVersion,
  bundledSubscriptionsPath: "/data/rules/abp",
}).then(async (eweFirstRun) => {
  await detectFirstRun(
    eweFirstRun.foundSubscriptions,
    eweFirstRun.foundStorage
  );
  eweFirstRun.warnings.forEach(console.warn);
  await prefs/* Prefs.untilLoaded.catch */.B.untilLoaded["catch"](() => { setDataCorrupted(true); });
  await testStorage().catch(() => { setDataCorrupted(true); })
  // adding default filter lists
  await addSubscriptions();
  await removeSubscriptions();
});


/**
 * Gets a value indicating whether a data corruption was detected.
 *
 * @return {boolean}
 */
function isDataCorrupted() {
  return dataCorrupted;
}




/**
 * @typedef {object} subscriptionsGetInitIssuesResult
 * @property {boolean} dataCorrupted
 *   true if it appears that the user's extension data was corrupted.
 * @property {boolean} reinitialized
 *   true if we have reset the user's settings due to data corruption.
 */

/**
 * Returns an Object with boolean flags for any subscription initialization
 * issues.
 *
 * @event "subscriptions.getInitIssues"
 * @returns {subscriptionsGetInitIssuesResult}
 */
port/* port.on */.N.on("subscriptions.getInitIssues", (message, sender) => ({ dataCorrupted, reinitialized }));


/***/ }),

/***/ 6392:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _servermessages__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2559);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7337);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global License*/





const authorizedKeys = [
  `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAuePfbm865kumeftXjlbt
J68DTXLTn0VeOgdSTqOcpADVqH0Kxz5hfLMaoKC/QhO3SmAu1yZwJZ1WP9Uyu3I5
EvJwEt7OHjJv54GhyYCtylMDCqSZgIIkUtB9PSXqFe3qyKAXACzwnLHmYIMMC1rx
bViqMD06+S4NKtzEh602/JsOOTHkXDJFQi5gGpd7Yn/r1YFG20JzU5lr0pf3dOEK
gNXiEwSRCuVSZ2+MHMtkFdP83/k59rTOfz5+ZThYmxECytD0JyY+bpDbso/XxQeL
fThNEEnSpbbeJRZQM5Lwf4D/f1wzSvyRrQiQz6Bo6TrA9DpL/BHqgUBv4O+DwhAu
8tFaaI+YWUmA1M6DRCL1aPQlFf3RB+aAf/TXFRU6enm8y/DFKWnwZja1YlApxTYT
MGnZ5hrsXZZImjcKBKwXi3JCtLkfV+osAHYrMAJPPAfECkch/ovrEUcdBEu4WsJ+
gKlL2C1/ZL+fTZc+H9qt38qba8my5XlQmhXmzXFKKyp+1pqNkQuYzzT0M8PUqtlh
z5aNu4gc/sOrQayusssUkkwISWm9yKc9pwOE+2Ax45iq2xNhjx0+rl9nc/chV21T
ZLfyePid/4N3Q7obmQ9a6trOBIF5ONyg16CK61RjacnG76AMKrVOoq9lzF2UufL8
Myzw9X8Wsw3VrjJyYbWhUtkCAwEAAQ==`,
  `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwWP4dO4iYcHpcO6lVmjC
gg/jfLM4fP+wWNaoDvMke0gQ7m9smXVtgbYXb6qzEd0aDaCRX3em+eo6bWp6ps5U
+8USRxuNH4cs6ZLjGynmZnm2TXrJScixUEw4ULq8Rdexr4ZmtT1WfUjJSFQpWWwp
e69kVR0iwwiCFRq90I/7MfJWnwgHX2tkUkVBttmXt9o0wP8th/UOIdx+0VbrqhgY
wMyo3xCUvqcSpcKsHXoLkKGlpcplE96rKg2vOqhSSQzoHMr8ZrGIn7hsPI7enVsP
D/nMiJptavVowfNZjM/rd6Iv/TYfI1JOJWUeIM+aPyhZKrvWHGdC8VO2jneNkNXj
1B6tnZy6owPt4Lgdimr0u/146WvjAL+ZK1dc4CNecOLeRINn26POCIeOpYPHGhbi
N6K1UrHpC1Oon2NW5ms9dciE242O1BrQF5j/GvNzGoV74GvnbVFZ9eyBJm9MlIOU
Sd5O2iTqWPmJ03wVSXLx+6g0fgaGHEDtKtbfhuHvDG2dIoAB7q+oKBHQJ7CIFEbI
lBnPV1v+dxDLb3DdK0Ip9wM74S2+Nf9359TCjAaWgNjiTnhBw6xpwTGn/8vzNL3p
fcEVJJt8DUfuCYV9mtKPHbj06RHnLsaXQ72x6I+ocXi8TygTjldZFx13ttJqVvju
UaTE0E4KN9Mzb/2zEYTgCzcCAwEAAQ==`,
];

/**
 * Function to be called when a valid allowlisting request was received
 *
 * @param domain - Domain to allowlist
 */
async function onAllowlisting(domain) {
  if (License.isActiveLicense()) {
    return;
  }

  await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.filters.add([`@@||${domain}^$document`], (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__/* .createFilterMetaData */ .Yv)('web'));
}

/**
 * Remove all web based allowlisting filters
 */
async function removeWebAllowlistingFilters() {
  const allowlistingFilters = (await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.filters.getUserFilters())
    .filter(filter => filter.type === 'allowing');

  const allowlistingFiltersWithMetadata = await Promise.all(
    allowlistingFilters.map(async (filter) => {
      const metadata = await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.filters.getMetadata(filter.text)
        .catch(() => null);
      return { filter, metadata };
    }),
  );
  const webAllowlistingFilters = allowlistingFiltersWithMetadata
    .filter(({ metadata }) => (metadata && metadata.origin === 'web'))
    .map(({ filter }) => filter);
  return _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.filters.remove(webAllowlistingFilters.map(filter => filter.text));
}


/**
 * Initializes module
 */
async function start() {
  _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.allowlisting.setAuthorizedKeys(authorizedKeys);
  _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.allowlisting.setAllowlistingCallback(onAllowlisting);

  await License.ready();
  if (License.isActiveLicense()) {
    removeWebAllowlistingFilters();
  }

  License.licenseNotifier.on('license.status.changed', () => {
    if (License.isActiveLicense()) {
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.allowlisting.setAuthorizedKeys([]);
      removeWebAllowlistingFilters();
    } else {
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.allowlisting.setAuthorizedKeys(authorizedKeys);
    }
  });

  _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.allowlisting.onUnauthorized.addListener((error) => {
    _servermessages__WEBPACK_IMPORTED_MODULE_0__/* ["default"].recordErrorMessage */ .Z.recordErrorMessage('one_click_allowlisting_error ', undefined, { errorMessage: error.toString() });
    // eslint-disable-next-line no-console
    console.error(error);
  });
}

start();


/***/ }),

/***/ 965:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// EXTERNAL MODULE: ./build/templates/info.chrome.js.tmpl
var info_chrome_js = __webpack_require__(755);
// EXTERNAL MODULE: ./adblock-betafish/alias/prefs.js
var prefs = __webpack_require__(4428);
// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./adblock-betafish/telemetry/background/index.js + 4 modules
var background = __webpack_require__(5441);
// EXTERNAL MODULE: ./adblock-betafish/id/background/index.ts + 1 modules
var id_background = __webpack_require__(6703);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/events.js
var events = __webpack_require__(5094);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/port.js
var port = __webpack_require__(6960);
// EXTERNAL MODULE: ./adblock-betafish/alias/storage/tab-session.js
var tab_session = __webpack_require__(440);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/browserAction.js
var browserAction = __webpack_require__(2209);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/events.js
var lib_events = __webpack_require__(9876);
// EXTERNAL MODULE: ./vendor/adblockplusui/src/core/scheduled-event-emitter/background/scheduled-event-emitter.ts + 1 modules
var scheduled_event_emitter = __webpack_require__(7650);
;// CONCATENATED MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/stats.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module stats */










const badgeColor = "#646464";
const badgeRefreshRate = 4;
const badgeUpdateTopic = "stats.badgeUpdate";

let eventEmitter = new lib_events/* EventEmitter */.v();
let blockedPerPage = new tab_session/* TabSessionStorage */.H("stats:blocked");

/**
 * Gets the number of requests blocked on the given page.
 *
 * @param  {Page} page
 * @return {Number}
 */
async function getBlockedPerPage(page)
{
  return (await blockedPerPage.get(page.id)) || 0;
}

let activeTabIds = new Set();
let activeTabIdByWindowId = new Map();

let badgeUpdateScheduled = false;

async function updateBadge(tabId)
{
  if (!prefs/* Prefs.show_statsinicon */.B.show_statsinicon)
    return;

  for (let id of (typeof tabId == "undefined" ? activeTabIds : [tabId]))
  {
    let blockedCount = await blockedPerPage.get(id);

    (0,browserAction/* setBadge */.q_)(id, blockedCount && {
      color: badgeColor,
      number: blockedCount
    });
  }
}

function scheduleBadgeUpdate(tabId)
{
  if (!badgeUpdateScheduled && prefs/* Prefs.show_statsinicon */.B.show_statsinicon &&
      (typeof tabId == "undefined" || activeTabIds.has(tabId)))
  {
    scheduled_event_emitter/* setSchedule */.U3(
      badgeUpdateTopic,
      1000 / badgeRefreshRate
    );
    badgeUpdateScheduled = true;
  }
}

scheduled_event_emitter/* setListener */.MU(badgeUpdateTopic, async() =>
{
  badgeUpdateScheduled = false;
  await updateBadge();
});

// Once nagivation for the tab has been committed to (e.g. it's no longer
// being prerendered) we clear its badge, or if some requests were already
// blocked beforehand we display those on the badge now.
browser.webNavigation.onCommitted.addListener(async details =>
{
  if (details.frameId == 0)
    await updateBadge(details.tabId);
});

async function onBlockableItem({filter, request})
{
  if (!filter || filter.type != "blocking")
    return;

  let {tabId} = request;

  let blocked = await blockedPerPage.get(tabId) || 0;
  ++blocked;

  await blockedPerPage.set(tabId, blocked);
  scheduleBadgeUpdate(tabId);

  eventEmitter.emit("blocked_per_page", {tabId, blocked});

  // Don't update the total for incognito tabs.
  let tab = await browser.tabs.get(tabId);
  if (tab.incognito)
    return;

  // Make sure blocked_total is only read after the storage was loaded.
  await prefs/* Prefs.untilLoaded */.B.untilLoaded;

  prefs/* Prefs.blocked_total */.B.blocked_total++;
  eventEmitter.emit("blocked_total", prefs/* Prefs.blocked_total */.B.blocked_total);
}

/**
 * Checks request errors for requests blocked by client and, if appropriate,
 * calls the function to update the block counter.
 *
 * Note that we cannot distinguish whether the request was blocked by us or
 * another extension.
 *
 * This is only here as a temporary workaround until
 * ewe.reporting.onBlockableItem works properly in MV3.
 *
 * See https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onErrorOccurred#details_2
 * for a type definition of the `details` object.
 *
 * @param {object} details The network error details
 */
async function handleRequestError({error, frameId, tabId, type, url})
{
  // Only check request errors inside of browser tabs, and only of
  // the `net::ERR_BLOCKED_BY_CLIENT` type.
  // NOTE: The error name "net::ERR_BLOCKED_BY_CLIENT" exists only in Chromium!
  if (
    tabId === browser.tabs.TAB_ID_NONE ||
    error !== "net::ERR_BLOCKED_BY_CLIENT"
  )
    return;

  // Ignore if request is allowlisted.
  const isAllowlisted = await ewe_api.filters.isResourceAllowlisted(
    url,
    ewe_api.reporting.contentTypesMap.get(type),
    tabId,
    frameId
  );
  if (isAllowlisted)
    return;

  // Call `onBlockableItem` and feed it data in a structure it can consume.
  void onBlockableItem({
    filter: {
      type: "blocking"
    },
    request: {
      tabId
    }
  });
}

// In the MV3 version, ewe.reporting.onBlockableItem doesn't yet report
// blocked items.
// Until ewe.reporting.onBlockableItem works correctly with MV3, we count
// every request that was blocked. However, we cannot distinguish whether the
// request was blocked by us or another extension.
if (browser.runtime.getManifest().manifest_version === 3)
{
  browser.webRequest.onErrorOccurred.addListener(
    handleRequestError,
    {urls: ["<all_urls>"]}
  );
}
else
{
  ewe_api.reporting.onBlockableItem.addListener(onBlockableItem);
}

/**
  * @namespace
  * @static
  */
let Stats = {
  /**
   * Adds a callback that is called when the
   * value of a specified stat changed.
   *
   * @param {string}   stat
   * @param {function} callback
   */
  on(stat, callback)
  {
    eventEmitter.on(stat, callback);
  },

  /**
   * Removes a callback for the specified stat.
   *
   * @param {string}   stat
   * @param {function} callback
   */
  off(stat, callback)
  {
    eventEmitter.off(stat, callback);
  },

  /**
   * The total number of blocked requests on non-incognito pages.
   *
   * @type {number}
   */
  get blocked_total()
  {
    return prefs/* Prefs.blocked_total */.B.blocked_total;
  }
};

prefs/* Prefs.on */.B.on("show_statsinicon", async() =>
{
  let tabs = await browser.tabs.query({});
  for (let tab of tabs)
  {
    if (prefs/* Prefs.show_statsinicon */.B.show_statsinicon)
      await updateBadge(tab.id);
    else
      (0,browserAction/* setBadge */.q_)(tab.id, null);
  }
});

/**
 * Returns the number of blocked requests for the sender's page.
 *
 * @event "stats.getBlockedPerPage"
 * @returns {number}
 */
port/* port.on */.N.on("stats.getBlockedPerPage",
        message => getBlockedPerPage(new ext.Page(message.tab)));

/**
 * Returns the total number of blocked requests on non-incognito pages.
 *
 * @event "stats.getBlockedTotal"
 * @returns {number}
 */
port/* port.on */.N.on("stats.getBlockedTotal", () => Stats.blocked_total);

browser.tabs.query({active: true}).then(tabs =>
{
  for (let tab of tabs)
  {
    activeTabIds.add(tab.id);
    activeTabIdByWindowId.set(tab.windowId, tab.id);
  }

  scheduleBadgeUpdate();
});

(0,events/* installHandler */.a)("stats", null, (emit, action) =>
{
  const onChanged = info => emit(info);
  Stats.on(action, onChanged);
  return () => Stats.off(action, onChanged);
});

browser.tabs.onActivated.addListener(tab =>
{
  let lastActiveTabId = activeTabIdByWindowId.get(tab.windowId);
  if (typeof lastActiveTabId != "undefined")
    activeTabIds.delete(lastActiveTabId);

  activeTabIds.add(tab.tabId);
  activeTabIdByWindowId.set(tab.windowId, tab.tabId);

  scheduleBadgeUpdate();
});

if ("windows" in browser)
{
  browser.windows.onRemoved.addListener(windowId =>
  {
    activeTabIds.delete(activeTabIdByWindowId.get(windowId));
    activeTabIdByWindowId.delete(windowId);
  });
}

// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/allowlisting.js
var allowlisting = __webpack_require__(7718);
// EXTERNAL MODULE: ./adblock-betafish/alias/subscriptionInit.js + 1 modules
var subscriptionInit = __webpack_require__(704);
// EXTERNAL MODULE: ./adblock-betafish/picreplacement/sync-service.js
var sync_service = __webpack_require__(3283);
// EXTERNAL MODULE: ./adblock-betafish/subscriptionadapter.js + 1 modules
var subscriptionadapter = __webpack_require__(1974);
// EXTERNAL MODULE: ./adblock-betafish/datacollection.v2.js
var datacollection_v2 = __webpack_require__(5953);
// EXTERNAL MODULE: ./adblock-betafish/alias/icon.js
var icon = __webpack_require__(3398);
// EXTERNAL MODULE: ./adblock-betafish/localdatacollection.js
var localdatacollection = __webpack_require__(4988);
// EXTERNAL MODULE: ./adblock-betafish/picreplacement/check.js
var check = __webpack_require__(2509);
// EXTERNAL MODULE: ./adblock-betafish/servermessages.js
var servermessages = __webpack_require__(2559);
;// CONCATENATED MODULE: ./adblock-betafish/alias/uninstall.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, ewe */

/** @module uninstall */
/** similar to adblockpluschrome\lib\uninstall.js */





/**
 * Returns the number of currently active filters that have been added using
 * the experimental allowlisting functionality (i.e. that originated in the
 * web, and not in the extension popup).
 *
 * @returns {number} The filter count
 */
async function getWebAllowlistingFilterCount() {
  // get all allowlisting filters that are enabled
  const filters = (await ewe.filters.getUserFilters()).filter(
    filter => filter.type === 'allowing' && filter.enabled,
  );

  // collect the origin from the metadata
  const filtersMetadata = await Promise.all(
    filters.map(async (rule) => {
      const metadata = await ewe.filters.getMetadata(rule.text)
        .catch(() => null);
      return metadata && metadata.origin;
    }),
  );

  // count the ones that originated in the web
  return filtersMetadata.filter(data => data === 'web').length;
}

async function setUninstallURL() {
  if (browser.runtime.setUninstallURL) {
    const userID = await (0,id_background/* getUserId */.n)();
    let uninstallURL = "https://getadblock.com/uninstall/?u=" + userID;
    // if the start property of blockCount exists (which is the AdBlock
    // installation timestamp)
    // use it to calculate the approximate length of time that user has
    // AdBlock installed
    if (prefs/* Prefs */.B && prefs/* Prefs.blocked_total */.B.blocked_total !== undefined) {
      const twoMinutes = 2 * 60 * 1000;
      const getLastUpdateTime = async function () {
        const userSubs = await subscriptionadapter/* default.getSubscriptionsMinusText */.Z.getSubscriptionsMinusText();
        let maxLastDownload = -1;
        for (const sub in userSubs) {
          if (userSubs[sub].lastSuccess > maxLastDownload) {
            maxLastDownload = userSubs[sub].lastSuccess;
          }
        }
        return maxLastDownload;
      };
      const updateUninstallURL = async function () {
        const data = await browser.storage.local.get('blockage_stats');
        let url = uninstallURL;
        if (data && data.blockage_stats && data.blockage_stats.start) {
          const installedDuration = Date.now() - data.blockage_stats.start;
          url = `${url}&t=${installedDuration}`;
        }
        const bc = prefs/* Prefs.blocked_total */.B.blocked_total;
        url = `${url}&bc=${bc}`;
        const lastUpdateTime = await getLastUpdateTime();
        url = `${url}&lt=${lastUpdateTime}`;
        url += `&wafc=${await getWebAllowlistingFilterCount()}`;
        browser.runtime.setUninstallURL(url);
      };
      // start an interval timer that will update the Uninstall URL every 2
      // minutes
      setInterval(updateUninstallURL, twoMinutes);
      updateUninstallURL();
    } else {
      browser.runtime.setUninstallURL(`${uninstallURL}&t=-1`);
    }
  }
}

// EXTERNAL MODULE: ./adblock-betafish/prefs/background/index.js + 1 modules
var prefs_background = __webpack_require__(1648);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/background.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, ext, twitchChannelNamePages, ytChannelNamePages,
   updateButtonUIAndContextMenus,  */
























// Message verification
const trustedBaseUrl = browser.runtime.getURL('');
const gabHostnames = ['https://getadblock.com', 'https://dev.getadblock.com', 'https://dev1.getadblock.com', 'https://dev2.getadblock.com', 'https://vpn.getadblock.com', 'https://help.getadblock.com'];

const isTrustedSender = sender => sender.url.startsWith(trustedBaseUrl);

const isTrustedTarget = url => (url.startsWith(trustedBaseUrl)
  || gabHostnames.includes(new URL(url).origin));

const isTrustedSenderDomain = (sender) => {
  if (sender.origin) {
    return gabHostnames.includes(sender.origin);
  }
  if (sender.url) {
    return gabHostnames.includes(new URL(sender.url).origin);
  }
  return false;
};
const adblocBetaID = 'pljaalgmajnlogcgiohkhdmgpomjcihk';

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  Prefs: prefs/* Prefs */.B,
  info: info_chrome_js,
  getBlockedPerPage: getBlockedPerPage,
  SyncService: sync_service["default"],
  LocalDataCollection: localdatacollection/* default */.Z,
  ServerMessages: servermessages/* default */.Z,
  SubscriptionAdapter: subscriptionadapter/* default */.Z,
  TELEMETRY: background/* TELEMETRY */.C,
  IPMTelemetry: background/* IPM */.fp,
  DataCollectionV2: datacollection_v2/* default */.Z,
  getNewBadgeTextReason: icon/* getNewBadgeTextReason */.vo,
  ewe: ewe_api,
  License: check/* License */.Cz,
  channels: check/* channels */.ZW,
  isTrustedSender,
  isTrustedTarget,
  isTrustedSenderDomain,
});

// CUSTOM FILTERS

const isSelectorFilter = function (text) {
  // This returns true for both hiding rules as hiding whitelist rules
  // This means that you'll first have to check if something is an excluded rule
  // before checking this, if the difference matters.
  return /#@?#./.test(text);
};

// custom filter countCache singleton.
const countCache = (function countCache() {
  let cache;

  // Update custom filter count stored in storage
  const updateCustomFilterCount = function () {
    (0,bg_functions/* chromeStorageSetHelper */.rJ)('custom_filter_count', cache);
  };

  return {
    // Update custom filter count cache and value stored in storage.
    // Inputs: new_count_map:count map - count map to replace existing count
    // cache
    updateCustomFilterCountMap(newCountMap) {
      cache = newCountMap || cache;
      updateCustomFilterCount();
    },

    // Remove custom filter count for host
    // Inputs: host:string - url of the host
    removeCustomFilterCount(host) {
      if (host && cache[host]) {
        delete cache[host];
        updateCustomFilterCount();
      }
    },

    // Get current custom filter count for a particular domain
    // Inputs: host:string - url of the host
    getCustomFilterCount(host) {
      let customCount = 0;
      if (cache) {
        customCount = cache[host];
      }
      return customCount || 0;
    },

    // Add 1 to custom filter count for the filters domain.
    // Inputs: filter:string - line of text to be added to custom filters.
    addCustomFilterCount(filter) {
      const host = filter.split('##')[0];
      cache[host] = this.getCustomFilterCount(host) + 1;
      updateCustomFilterCount();
    },

    init() {
      browser.storage.local.get('custom_filter_count').then((response) => {
        cache = response.custom_filter_count || {};
      });
    },
  };
}());
countCache.init();

// Add a new custom filter entry.
// Inputs: filter:string - line of text to add to custom filters.
//         origin:string - the source or trigger for the filter list entry
// Returns: null if succesfull, otherwise an exception
const addCustomFilter = async function (filterText, origin) {
  try {
    const response = ewe_api.filters.validate(filterText);
    if (response) {
      return response;
    }
    await ewe_api.filters.add([filterText], (0,bg_functions/* createFilterMetaData */.Yv)(origin));
    await ewe_api.filters.enable([filterText]);
    if (isSelectorFilter(filterText)) {
      countCache.addCustomFilterCount(filterText);
    }
    return null;
  } catch (ex) {
    // convert to a string so that Safari can pass
    // it back to content scripts
    return ex.toString();
  }
};

// Creates a custom filter entry that allowlists a given domain
// Inputs: pageUrl:string - url of the page
//         origin:string - the source or trigger for the filter list entry
// Returns: null if successful, otherwise an exception
const createDomainAllowlistFilter = async function (pageUrl, origin) {
  const theURL = new URL(pageUrl);
  const host = theURL.hostname.replace(/^www\./, '');
  const filter = `@@||${host}/*^$document`;
  return addCustomFilter(filter, origin);
};

// UNWHITELISTING

async function getUserFilters() {
  return ewe_api.filters.getUserFilters();
}

const isWhitelistFilter = function (text) {
  return /^@@/.test(text);
};

// Look for a custom filter that would whitelist the 'url' parameter
// and if any exist, remove the first one.
// Inputs: url:string - a URL that may be allowlisted by a custom filter
//         tabId: integer - tab id of the tab that may be allowlisted by a custom filter
// Returns: true if a filter was found and removed; false otherwise.
const tryToUnwhitelist = async function (pageUrl, tabId) {
  const url = pageUrl.replace(/#.*$/, ''); // Whitelist ignores anchors
  const customFilters = await getUserFilters();
  if (!customFilters || !customFilters.length === 0) {
    return false;
  }

  /* eslint-disable no-await-in-loop */
  for (let i = 0; i < customFilters.length; i++) {
    const { text } = customFilters[i];
    const whitelist = text.search(/@@\*\$document,domain=~/);
    // Blacklist site, which is whitelisted by global @@*&document,domain=~
    // filter
    if (whitelist > -1) {
      // Remove protocols
      const [finalUrl] = url.replace(/((http|https):\/\/)?(www.)?/, '').split(/[/?#]/);
      await ewe_api.filters.remove([text]);
      await ewe_api.filters.remove([`${text}|~${finalUrl}`]);
      return true;
    }
    if (isWhitelistFilter(text) && (await ewe_api.filters.getAllowingFilters(tabId)).includes(text)) {
      await ewe_api.filters.remove([text]);
      return true;
    }
  }
  return false;
};

// Removes a custom filter entry.
// Inputs: host:domain of the custom filters to be reset.
const removeCustomFilter = async function (host) {
  const customFilters = await getUserFilters();
  if (!customFilters || !customFilters.length === 0) {
    return;
  }

  const identifier = host;

  for (let i = 0; i < customFilters.length; i++) {
    const entry = customFilters[i];
    // If the identifier is at the start of the entry
    // then delete it.
    if (entry.text.indexOf(identifier) === 0) {
      ewe_api.filters.remove([entry.text]);
    }
  }
};

// Entry point for customize.js, used to update custom filter count cache.
const updateCustomFilterCountMap = function (newCountMap) {
  // Firefox passes weak references to objects, so we need a local copy
  const localCountMap = JSON.parse(JSON.stringify(newCountMap));
  countCache.updateCustomFilterCountMap(localCountMap);
};

const removeCustomFilterForHost = function (host) {
  if (countCache.getCustomFilterCount(host)) {
    removeCustomFilter(host);
    countCache.removeCustomFilterCount(host);
  }
};

// Currently, Firefox doesn't allow the background page to use alert() or confirm(),
// so some JavaScript is injected into the active tab, which does the confirmation for us.
// If the user confirms the removal of the entries, then they are removed, and the page reloaded.
const confirmRemovalOfCustomFiltersOnHost = function (host, activeTabId) {
  if (!browser.tabs.executeScript) {
    /* eslint-disable-next-line no-console */
    console.error('confirmRemovalOfCustomFiltersOnHost disable for MV3 extensions');
    return; // this function isn't supported under MV3, and shouldn't be invoked for MV3 extensions.
  }
  const customFilterCount = countCache.getCustomFilterCount(host);
  const confirmationText = browser.i18n.getMessage('confirm_undo_custom_filters', [customFilterCount, host]);
  const messageListenerFN = function (request) {
    browser.runtime.onMessage.removeListener(messageListenerFN);
    if (request === `remove_custom_filters_on_host${host}:true`) {
      removeCustomFilterForHost(host);
      browser.tabs.reload(activeTabId);
    }
  };

  browser.runtime.onMessage.addListener(messageListenerFN);
  /* eslint-disable prefer-template */
  const codeToExecute = 'var host = "' + host + '"; var confirmResponse = confirm("' + confirmationText + '"); browser.runtime.sendMessage("remove_custom_filters_on_host" + host + ":" + confirmResponse); ';
  const details = { allFrames: false, code: codeToExecute };
  browser.tabs.executeScript(activeTabId, details);
};
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.command !== 'confirmRemovalOfCustomFiltersOnHost' || !message.host || !message.activeTabId) {
    return;
  }
  confirmRemovalOfCustomFiltersOnHost(message.host, message.activeTabId);
  sendResponse({});
});


// Reload already opened tab
// Input:
// id: integer - id of the tab which should be reloaded
const reloadTab = function (id, callback) {
  let tabId = id;
  const localCallback = callback;
  const listener = function (updatedTabId, changeInfo, tab) {
    if (changeInfo.status === 'complete' && tab.status === 'complete') {
      setTimeout(() => {
        browser.tabs.sendMessage(updatedTabId, { command: 'reloadcomplete' });
        if (typeof localCallback === 'function') {
          localCallback(tab);
        }
        browser.tabs.onUpdated.removeListener(listener);
      }, 2000);
    }
  };

  if (typeof tabId === 'string') {
    tabId = parseInt(tabId, 10);
  }
  browser.tabs.onUpdated.addListener(listener);
  browser.tabs.reload(tabId, { bypassCache: true });
};

const isSelectorExcludeFilter = function (text) {
  return /#@#./.test(text);
};

const getAdblockUserId = async function () {
  return (0,id_background/* getUserId */.n)();
};

// INFO ABOUT CURRENT PAGE

// Returns true if the url cannot be blocked
const pageIsUnblockable = function (url) {
  if (!url) { // Protect against empty URLs - e.g. Safari empty/bookmarks/top sites page
    return true;
  }
  let scheme = '';
  if (!url.protocol) {
    scheme = (0,bg_functions/* parseUri */.he)(url).protocol;
  } else {
    scheme = url.protocol;
  }

  return (scheme !== 'http:' && scheme !== 'https:' && scheme !== 'feed:');
};

// Returns true if the page is whitelisted.
// Called from a content script
const pageIsWhitelisted = async function (page) {
  const whitelisted = !!await ewe_api.filters.getAllowingFilters(page.id).length;
  return (whitelisted !== undefined && whitelisted !== null);
};

const pausedKey = 'paused';
// white-list all blocking requests regardless of frame / document, but still allows element hiding
const pausedFilterText1 = '@@*';
// white-list all documents, which prevents element hiding
const pausedFilterText2 = '@@*$document';

// Get or set if AdBlock is paused
// Inputs: newValue (optional boolean): if true, AdBlock will be paused, if
// false, AdBlock will not be paused.
// Returns: undefined if newValue was specified, otherwise it returns true
// if paused, false otherwise.
const adblockIsPaused = function (newValue) {
  if (newValue === undefined) {
    return ((0,bg_functions/* sessionStorageGet */.E_)(pausedKey) === true);
  }

  if (newValue === true) {
    (0,bg_functions/* chromeStorageSetHelper */.rJ)(pausedKey, true, () => {
      ewe_api.filters.add([pausedFilterText1]);
      ewe_api.filters.add([pausedFilterText2]);
    });
  } else {
    ewe_api.filters.remove([pausedFilterText1]);
    ewe_api.filters.remove([pausedFilterText2]);
    browser.storage.local.remove(pausedKey);
  }
  (0,bg_functions/* sessionStorageSet */.bg)(pausedKey, newValue);
  return undefined;
};

const domainPausedKey = 'domainPaused';

// Helper that saves the domain pauses
// Inputs:  domainPauses (required object): domain pauses to save
// Returns: undefined
const saveDomainPauses = function (domainPauses) {
  (0,bg_functions/* chromeStorageSetHelper */.rJ)(domainPausedKey, domainPauses);
  (0,bg_functions/* sessionStorageSet */.bg)(domainPausedKey, domainPauses);
};

// Helper that removes any domain pause filter rules based on tab events
// Inputs:  tabId (required integer): identifier for the affected tab
//          newDomain (optional string): the current domain of the tab
// Returns: undefined
const domainPauseChangeHelper = function (tabId, newDomain) {
  // get stored domain pauses
  const storedDomainPauses = (0,bg_functions/* sessionStorageGet */.E_)(domainPausedKey);

  // check if any of the stored domain pauses match the affected tab
  for (const aDomain in storedDomainPauses) {
    if (storedDomainPauses[aDomain] === tabId && aDomain !== newDomain) {
      // Remove the filter that white-listed the domain
      ewe_api.filters.remove([`@@${aDomain}$document`]);
      delete storedDomainPauses[aDomain];

      // save updated domain pauses
      saveDomainPauses(storedDomainPauses);
    }
  }
  updateButtonUIAndContextMenus();
};

// Handle the effects of a tab update event on any existing domain pauses
// Inputs:  tabId (required integer): identifier for the affected tab
//          changeInfo (required object with a url property): contains the
// new url for the tab
//          tab (optional Tab object): the affected tab
// Returns: undefined
const domainPauseNavigationHandler = function (tabId, changeInfo) {
  if (changeInfo === undefined || changeInfo.url === undefined || tabId === undefined) {
    return;
  }

  const newDomain = (0,bg_functions/* parseUri */.he)(changeInfo.url).host;

  domainPauseChangeHelper(tabId, newDomain);
};

// Handle the effects of a tab remove event on any existing domain pauses
// Inputs:  tabId (required integer): identifier for the affected tab
//          changeInfo (optional object): info about the remove event
// Returns: undefined
const domainPauseClosedTabHandler = function (tabId) {
  if (tabId === undefined) {
    return;
  }

  domainPauseChangeHelper(tabId);
};

// Get or set if AdBlock is domain paused for the domain of the specified tab
// Inputs:  activeTab (optional object with url and id properties): the paused tab
//          newValue (optional boolean): if true, AdBlock will be domain paused
// on the tab's domain, if false, AdBlock will not be domain paused on that domain.
// Returns: undefined if activeTab and newValue were specified; otherwise if activeTab
// is specified it returns true if domain paused, false otherwise; finally it returns
// the complete storedDomainPauses if activeTab is not specified

const adblockIsDomainPaused = function (activeTab, newValue) {
  // get stored domain pauses
  let storedDomainPauses = (0,bg_functions/* sessionStorageGet */.E_)(domainPausedKey);

  // return the complete list of stored domain pauses if activeTab is undefined
  if (activeTab === undefined) {
    return storedDomainPauses;
  }

  // return a boolean indicating whether the domain is paused if newValue is undefined
  const activeDomain = (0,bg_functions/* parseUri */.he)(activeTab.url).host;
  if (newValue === undefined) {
    if (storedDomainPauses) {
      return Object.prototype.hasOwnProperty.call(storedDomainPauses, activeDomain);
    }
    return false;
  }

  // create storedDomainPauses object if needed
  if (!storedDomainPauses) {
    storedDomainPauses = {};
  }

  // set or delete a domain pause
  if (newValue === true) {
    // add a domain pause
    ewe_api.filters.add([`@@${activeDomain}$document`]);
    storedDomainPauses[activeDomain] = activeTab.id;
    browser.tabs.onUpdated.removeListener(domainPauseNavigationHandler);
    browser.tabs.onRemoved.removeListener(domainPauseClosedTabHandler);
    browser.tabs.onUpdated.addListener(domainPauseNavigationHandler);
    browser.tabs.onRemoved.addListener(domainPauseClosedTabHandler);
  } else {
    // remove the domain pause
    ewe_api.filters.remove([`@@${activeDomain}$document`]);
    delete storedDomainPauses[activeDomain];
  }

  // save the updated list of domain pauses
  saveDomainPauses(storedDomainPauses);
  return undefined;
};

// If AdBlock was paused on shutdown (adblock_is_paused is true), then
// unpause / remove the white-list all entry at startup.
browser.storage.local.get(pausedKey).then((response) => {
  if (response[pausedKey]) {
    subscriptionInit/* initialize.then */.j.then(() => {
      ewe_api.filters.remove([pausedFilterText1]);
      ewe_api.filters.remove([pausedFilterText2]);
      browser.storage.local.remove(pausedKey);
    });
  }
});


// If AdBlock was domain paused on shutdown, then unpause / remove
// all domain pause white-list entries at startup.
browser.storage.local.get(domainPausedKey).then((response) => {
  const storedDomainPauses = response[domainPausedKey];
  if (!(0,bg_functions/* isEmptyObject */.Qr)(storedDomainPauses)) {
    subscriptionInit/* initialize.then */.j.then(() => {
      for (const aDomain in storedDomainPauses) {
        ewe_api.filters.remove([`@@${aDomain}$document`]);
      }
      browser.storage.local.remove(domainPausedKey);
    });
  }
});

browser.commands.onCommand.addListener((command) => {
  if (command === 'toggle_pause') {
    adblockIsPaused(!adblockIsPaused());
    servermessages/* default.recordGeneralMessage */.Z.recordGeneralMessage('pause_shortcut_used');
  }
});

const getTab = function (tabId) {
  return new Promise((resolve) => {
    if (tabId) {
      let id = tabId;
      if (typeof id === 'string') {
        id = parseInt(id, 10);
      }
      browser.tabs.get(id).then((tab) => {
        resolve(tab);
      });
    } else {
      browser.tabs.query({
        active: true,
        lastFocusedWindow: true,
      }).then((tabs) => {
        if (tabs.length === 0) {
          resolve(); // For example: only the background devtools or a popup are opened
        }
        resolve(tabs[0]);
      });
    }
  });
};


// Get interesting information about the current tab.
// Inputs:
// secondTime: bool - whether this is a recursive call
// info object passed to resolve: {
// page: Page object
// tab: Tab object
// whitelisted: bool - whether the current tab's URL is whitelisted.
// disabled_site: bool - true if the url is e.g. about:blank or the
// Extension Gallery, where extensions don't run.
// settings: Settings object
// paused: bool - whether AdBlock is paused
// domainPaused: bool - whether the current tab's URL is paused
// blockCountPage: int - number of ads blocked on the current page
// blockCountTotal: int - total number of ads blocked since install
// customFilterCount: int - number of custom rules for the current tab's URL
// showMABEnrollment: bool - whether to show MAB enrollment
// popupMenuThemeCTA: string - name of current popup menu CTA theme
// lastGetStatusCode: int - status code for last GET request
// lastGetErrorResponse: error object - error response for last GET request
// lastPostStatusCode: int - status code for last POST request
// allowlistRuleText: string - allowlist rule text for use on YouTube and Twitch
// }
// Returns: Promise
const getCurrentTabInfo = function (secondTime, tabId) {
  return new Promise((resolve) => {
    getTab(tabId).then(async (tab) => {
      if (tab && !tab.url) {
        // Issue 6877: tab URL is not set directly after you opened a window
        // using window.open()
        if (!secondTime) {
          setTimeout(() => {
            getCurrentTabInfo(true);
          }, 250);
        }
        return resolve();
      }
      try {
        const page = new ext.Page(tab);
        const disabledSite = pageIsUnblockable(page.url.href);
        const customFilterCheckUrl = disabledSite ? undefined : page.url.hostname;

        const result = {
          disabledSite,
          url: String(page.url || tab.url),
          id: page.id,
          settings: (0,prefs_background/* getSettings */.Gw)(),
          paused: adblockIsPaused(),
          domainPaused: adblockIsDomainPaused({ url: page.url.href, id: page.id }),
          blockCountPage: await getBlockedPerPage(tab),
          blockCountTotal: Stats.blocked_total,
          customFilterCount: countCache.getCustomFilterCount(customFilterCheckUrl),
          showMABEnrollment: check/* License.shouldShowMyAdBlockEnrollment */.Cz.shouldShowMyAdBlockEnrollment(),
          popupMenuThemeCTA: check/* License.getCurrentPopupMenuThemeCTA */.Cz.getCurrentPopupMenuThemeCTA(),
          showDcCTA: check/* License.shouldShowPremiumDcCTA */.Cz.shouldShowPremiumDcCTA(),
          lastGetStatusCode: sync_service["default"].getLastGetStatusCode(),
          lastGetErrorResponse: sync_service["default"].getLastGetErrorResponse(),
          lastPostStatusCode: sync_service["default"].getLastPostStatusCode(),
          newBadgeTextReason: (0,icon/* getNewBadgeTextReason */.vo)(),
        };
        if (!disabledSite) {
          result.whitelisted = !!(await ewe_api.filters.getAllowingFilters(page.id)).length;
          result.whitelistedText = await ewe_api.filters.getAllowingFilters(page.id);
        }
        if (check/* License */.Cz && check/* License.isActiveLicense */.Cz.isActiveLicense()) {
          result.activeLicense = true;
          result.subscriptions = await subscriptionadapter/* default.getSubscriptionsMinusText */.Z.getSubscriptionsMinusText();
        }
        if (
          (0,prefs_background/* getSettings */.Gw)()
          && (0,prefs_background/* getSettings */.Gw)().youtube_channel_whitelist
          && (0,bg_functions/* parseUri */.he)(tab.url).hostname === 'www.youtube.com'
        ) {
          result.youTubeChannelName = ytChannelNamePages.get(page.id);
          // handle the odd occurence of when the  YT Channel Name
          // isn't available in the ytChannelNamePages map
          // obtain the channel name from the URL
          // for instance, when the forward / back button is clicked
          if (!result.youTubeChannelName && /ab_channel/.test(tab.url)) {
            result.youTubeChannelName = bg_functions/* parseUri.parseSearch */.he.parseSearch(tab.url).ab_channel;
          }
          if (result.youTubeChannelName) {
            result.allowlistRuleText = `@@||www.youtube.com/*${result.youTubeChannelName}|$document`;
          }
        }
        if (
          twitchChannelNamePages
          && (0,prefs_background/* getSettings */.Gw)()
          && (0,prefs_background/* getSettings */.Gw)().twitch_channel_allowlist
          && (0,bg_functions/* parseUri */.he)(tab.url).hostname === 'www.twitch.tv'
        ) {
          result.twitchChannelName = twitchChannelNamePages.get(page.id);
          if (result.twitchChannelName) {
            result.allowlistRuleText = `@@||twitch.tv/*${result.twitchChannelName}^$document`;
          }
        }
        return resolve(result);
      } catch (err) {
        return resolve({ errorStr: err.toString(), stack: err.stack, message: err.message });
      }
    });
  });
};

const updateStorageKey = 'last_known_version';
browser.runtime.onInstalled.addListener(async (details) => {
  // Display beta page after each update for beta-users only
  if ((details.reason === 'update' || details.reason === 'install')
    && browser.runtime.id === adblocBetaID) {
    browser.tabs.create({ url: 'https://getadblock.com/beta' });
  }

  // We want to move away from localStorage, so remove item if it exists.
  if (typeof localStorage !== 'undefined') {
    localStorage.removeItem(updateStorageKey);
  }
  // Update version in browser.storage.local.
  void browser.storage.local.set({ [updateStorageKey]: browser.runtime.getManifest().version });
});

const openTab = function (url) {
  browser.tabs.create({ url });
};

// These functions are usually only called by content scripts.

// DEBUG INFO

async function getCustomFilterMetaData() {
  const currentUserFilters = await getUserFilters();
  if (!currentUserFilters || currentUserFilters.length === 0) {
    return Promise.resolve({});
  }
  /* eslint-disable consistent-return */
  return Promise.all(
    currentUserFilters.map(async (rule) => {
      if (rule && rule.text) {
        try {
          const metaData = await ewe_api.filters.getMetadata(rule.text);
          return { text: rule.text, metaData };
        } catch {
          return { text: rule.text };
        }
      }
    }),
  );
}
const getDebugAlarmInfo = async () => {
  const response = {};
  const alarms = await browser.alarms.getAll();
  if (alarms && alarms.length > 0) {
    response['Alarm info'] = `length: ${alarms.length}`;
    for (let i = 0; i < alarms.length; i++) {
      const alarm = alarms[i];
      response[`${i} Alarm Name`] = alarm.name;
      response[`${i} Alarm Scheduled Time`] = new Date(alarm.scheduledTime).toLocaleString();
    }
  } else {
    response['No alarm info'] = 'No alarm info';
  }
  return response;
};// end of getDebugAlarmInfo()

const getDebugLicenseInfo = async () => {
  const response = {};
  if (check/* License.isActiveLicense */.Cz.isActiveLicense()) {
    response.licenseInfo = {};
    response.licenseInfo.extensionGUID = await (0,id_background/* getUserId */.n)();
    response.licenseInfo.licenseId = check/* License.get */.Cz.get().licenseId;
    if ((0,prefs_background/* getSettings */.Gw)().sync_settings) {
      const syncInfo = {};
      syncInfo.SyncCommitVersion = sync_service["default"].getCommitVersion();
      syncInfo.SyncCommitName = sync_service["default"].getCurrentExtensionName();
      syncInfo.SyncCommitLog = sync_service["default"].getSyncLog();
      response.syncInfo = syncInfo;
    }
    response['License Installation Date'] = await check/* License.getLicenseInstallationDate */.Cz.getLicenseInstallationDate();
    const customChannelId = check/* channels.getIdByName */.ZW.getIdByName('CustomChannel');
    if (check/* channels.getGuide */.ZW.getGuide()[customChannelId].enabled) {
      const customChannel = check/* channels.channelGuide */.ZW.channelGuide[customChannelId].channel;
      const result = await customChannel.getTotalBytesInUse();
      response['Custom Channel total bytes in use'] = result;
    }
  }
  return response;
};

// Get debug info as a JSON object for bug reporting and ad reporting
const getDebugInfo = function () {
  return new Promise(async (resolve) => {
    const response = {};
    response.otherInfo = {};
    const { otherInfo } = response;

    // Is this installed build of AdBlock the official one?
    if (browser.runtime.id === 'pljaalgmajnlogcgiohkhdmgpomjcihk') {
      otherInfo.buildtype = ' Beta';
    } else if (browser.runtime.id === 'gighmmpiobklfepjocnamgkkbiglidom'
      || browser.runtime.id === 'aobdicepooefnbaeokijohmhjlleamfj'
      || browser.runtime.id === 'ndcileolkflehcjpmjnfbnaibdcgglog'
      || browser.runtime.id === 'jid1-NIfFY2CA8fy1tg@jetpack') {
      otherInfo.buildtype = ' Stable';
    } else {
      otherInfo.buildtype = ' Unofficial';
    }

    // Get AdBlock version
    otherInfo.version = browser.runtime.getManifest().version;

    // Get subscribed filter lists
    const subscriptionInfo = {};
    const subscriptions = await subscriptionadapter/* default.getSubscriptionsMinusText */.Z.getSubscriptionsMinusText();
    for (const id in subscriptions) {
      if (subscriptions[id].subscribed) {
        subscriptionInfo[id] = {};
        subscriptionInfo[id].lastSuccess = new Date(subscriptions[id].lastSuccess * 1000);
        subscriptionInfo[id].lastDownload = new Date(subscriptions[id].lastDownload * 1000);
        subscriptionInfo[id].downloadStatus = subscriptions[id].downloadStatus;
      }
    }
    response.subscriptions = subscriptionInfo;

    const userFilters = await getUserFilters();
    if (userFilters && userFilters.length) {
      response.customFilters = userFilters.map(filter => filter.text).join('\n');
    }

    // Get settings
    const adblockSettings = {};
    const settingsObj = (0,prefs_background/* getSettings */.Gw)();
    for (const [key, value] of Object.entries(settingsObj)) {
      adblockSettings[key] = JSON.stringify(value);
    }

    response.settings = adblockSettings;
    response.prefs = JSON.stringify(prefs/* Prefs */.B);
    otherInfo.browser = background/* TELEMETRY.browser */.C.browser;
    otherInfo.browserVersion = background/* TELEMETRY.browserVersion */.C.browserVersion;
    otherInfo.osVersion = background/* TELEMETRY.osVersion */.C.osVersion;
    otherInfo.os = background/* TELEMETRY.os */.C.os;

    if (typeof localStorage !== 'undefined' && localStorage.length) {
      otherInfo.localStorageInfo = {};
      otherInfo.localStorageInfo.length = localStorage.length;
      let inx = 1;
      for (const key in localStorage) {
        otherInfo.localStorageInfo[`key${inx}`] = key;
        inx += 1;
      }
    } else {
      otherInfo.localStorageInfo = 'no data';
    }
    otherInfo.isAdblockPaused = adblockIsPaused();
    otherInfo.licenseState = check/* License.get */.Cz.get().status;
    otherInfo.licenseVersion = check/* License.get */.Cz.get().lv;

    // Get 'Stats' size
    otherInfo.rawStatsSize = await localdatacollection/* default.getRawStatsSize */.Z.getRawStatsSize();

    // Get total pings
    const storageResponse = await browser.storage.local.get('total_pings');
    otherInfo.totalPings = storageResponse.totalPings || 0;

    // Add exclude filters (if there are any)
    const excludeFiltersKey = 'exclude_filters';
    const secondResponse = await browser.storage.local.get(excludeFiltersKey);
    if (secondResponse && secondResponse[excludeFiltersKey]) {
      response.excludedFilters = secondResponse[excludeFiltersKey];
    }

    // Add JavaScript exception error (if there is one)
    const errorKey = 'errorkey';
    const errorResponse = await browser.storage.local.get(errorKey);
    if (errorResponse && errorResponse[errorKey]) {
      otherInfo[errorKey] = errorResponse[errorKey];
    }

    // Add any migration messages (if there are any)
    const migrateLogMessageKey = 'migrateLogMessageKey';
    const migrateLogMessageResponse = await browser.storage.local.get(migrateLogMessageKey);
    if (migrateLogMessageResponse && migrateLogMessageResponse[migrateLogMessageKey]) {
      const messages = migrateLogMessageResponse[migrateLogMessageKey].split('\n');
      for (let i = 0; i < messages.length; i++) {
        const key = `migration_message_${i}`;
        otherInfo[key] = messages[i];
      }
    }

    otherInfo.alarmInfo = await getDebugAlarmInfo();
    if (browser.permissions && browser.permissions.getAll) {
      otherInfo.hostPermissions = await browser.permissions.getAll();
    } else {
      otherInfo.hostPermissions = 'no data';
    }
    otherInfo.licenseInfo = await getDebugLicenseInfo();
    otherInfo.customRuleMetaData = await getCustomFilterMetaData();
    resolve(response);
  }); // end of Promise
};

// Called when user explicitly requests filter list updates
async function updateFilterLists() {
  const subscriptions = await ewe_api.subscriptions.getDownloadable();
  subscriptions.forEach(async (subscription) => {
    await ewe_api.subscriptions.sync(subscription.url);
  });
}

// Checks if the filter lists are currently in the process of
// updating and if there were errors the last time they were
// updated
async function checkUpdateProgress() {
  let inProgress = false;
  let filterError = false;
  const subscriptions = await ewe_api.subscriptions.getDownloadable();
  subscriptions.forEach(async (subscription) => {
    if (subscription.downloading) {
      inProgress = true;
    } else if (subscription.downloadStatus && subscription.downloadStatus !== 'synchronize_ok') {
      filterError = true;
    }
  });
  return { inProgress, filterError };
}

subscriptionInit/* initialize.then */.j.then(async () => {
  await (0,id_background/* getUserId */.n)();
  background/* TELEMETRY.start */.C.start();
  setUninstallURL();
  await background/* IPM.untilLoaded */.fp.untilLoaded();
  background/* IPM.start */.fp.start();
  (0,allowlisting/* revalidateAllowlistingStates */.s)();
  prefs_background/* migrateUserData */.uF();
});

// Create the "blockage stats" for the uninstall logic ...
browser.runtime.onInstalled.addListener((details) => {
  if (details.reason === 'install') {
    browser.storage.local.get('blockage_stats').then((response) => {
      const { blockage_stats } = response;
      if (!blockage_stats) {
        const data = {};
        data.start = Date.now();
        data.version = 1;
        (0,bg_functions/* chromeStorageSetHelper */.rJ)('blockage_stats', data);
      }
    });
  }
});

// Attach methods to window
// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  adblockIsPaused,
  getUserFilters,
  updateFilterLists,
  checkUpdateProgress,
  createDomainAllowlistFilter,
  getDebugInfo,
  openTab,
  saveDomainPauses,
  adblockIsDomainPaused,
  pageIsWhitelisted,
  pageIsUnblockable,
  getCurrentTabInfo,
  getAdblockUserId,
  tryToUnwhitelist,
  addCustomFilter,
  removeCustomFilter,
  countCache,
  updateCustomFilterCountMap,
  removeCustomFilterForHost,
  reloadTab,
  isSelectorFilter,
  isWhitelistFilter,
  isSelectorExcludeFilter,
  pausedFilterText1,
  pausedFilterText2,
  updateStorageKey,
  getCustomFilterMetaData,
});


/***/ }),

/***/ 211:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var prefs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4428);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(2209);
/* harmony import */ var _servermessages__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2559);
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7337);
/* harmony import */ var _messaging_messagevalidator__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(7185);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, ext, adblockIsPaused, adblockIsDomainPaused
   License, reloadTab, getSettings, tryToUnwhitelist */









const updateBadge = async function (tabArg) {
  if (tabArg) {
    const tab = tabArg;
    tab.url = tab.url ? tab.url : tab.pendingUrl;
    if (
      tab.active
      && (
        adblockIsPaused()
        || adblockIsDomainPaused({ url: tab.url.href, id: tab.id })
        || !!(await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.filters.getAllowingFilters(tab.id)).length
      )
    ) {
      (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_2__/* .setBadge */ .q_)(tab.id, { number: '' });
    }
  }
};

const updateContextMenus = function (tab) {
  if (tab && tab.active) {
    const page = new ext.Page(tab);
    // eslint-disable-next-line no-use-before-define
    updateContextMenuItems(page);
  }
};

const updateButtonUIAndContextMenus = async function (tabArg) {
  if (tabArg) {
    updateBadge(tabArg);
    updateContextMenus(tabArg);
    return;
  }
  const tabs = await browser.tabs.query({});
  for (const tab of tabs) {
    updateBadge(tab);
    updateContextMenus(tab);
  }
};

// Bounce messages back to content scripts.
const emitPageBroadcast = (function emitBroadcast() {
  const injectMap = {
    topOpenWhitelistUI:
    {
      allFrames: false,
      include: [
        'jquery-3.5.1.min.js',
        'adblock-uiscripts-load_wizard_resources.js',
        'adblock-uiscripts-top_open_whitelist_ui.js',
      ],
    },
    topOpenWhitelistCompletionUI:
    {
      allFrames: false,
      include: [
        'jquery-3.5.1.min.js',
        'adblock-uiscripts-load_wizard_resources.js',
        'adblock-uiscripts-top_open_whitelist_completion_ui.js',
      ],
    },
    topOpenBlacklistUI:
    {
      allFrames: false,
      include: [
        'jquery-3.5.1.min.js',
        'purify.min.js',
        'adblock-uiscripts-load_wizard_resources.js',
        'adblock-uiscripts-blacklisting-overlay.js',
        'adblock-uiscripts-blacklisting-clickwatcher.js',
        'adblock-uiscripts-blacklisting-elementchain.js',
        'adblock-uiscripts-blacklisting-blacklistui.js',
        'adblock-uiscripts-top_open_blacklist_ui.js',
      ],
    },
    sendContentToBack:
    {
      allFrames: true,
      include: ['adblock-uiscripts-send_content_to_back.js'],
    },
  };

  // Inject the required scripts to execute fnName(parameter) in
  // the given tab.
  // Inputs: fnName:string name of function to execute on tab.
  //         fnName must exist in injectMap above.
  //         parameter:object to pass to fnName.  Must be JSON.stringify()able.
  //         alreadyInjected?:int used to recursively inject required scripts.
  //         tabID:int representing the ID of the tab to execute in.
  //         tabID defaults to the active tab
  const executeOnTab = async function (fnName, parameter, alreadyInjected, tabID) {
    const injectedSoFar = alreadyInjected || 0;
    const data = injectMap[fnName];
    const details = { allFrames: data.allFrames };

    if ('scripting' in browser) {
      await browser.scripting.executeScript({
        target: { tabId: tabID, allFrames: data.allFrames },
        files: data.include,
      }).catch(_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .log */ .cM);
      const functionToExecute = (args) => {
        if (typeof window[args.fnName] === 'function') {
          window[args.fnName](args);
        }
      };
      const params = parameter;
      params.fnName = fnName;
      await browser.scripting.executeScript({
        target: { tabId: tabID, allFrames: data.allFrames },
        args: [params],
        function: functionToExecute,
      }).catch(_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .log */ .cM);
      return;
    }

    // If there's anything to inject, inject the next item and recurse.
    if (data.include.length > injectedSoFar) {
      details.file = data.include[injectedSoFar];
      browser.tabs.executeScript(tabID, details).then(() => {
        executeOnTab(fnName, parameter, injectedSoFar + 1, tabID);
      }).catch((error) => {
        (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .log */ .cM)(error);
      });
    } else {
      // Nothing left to inject, so execute the function.
      const param = JSON.stringify(parameter);
      details.code = `${fnName}(${param});`;
      browser.tabs.executeScript(tabID, details);
    }
  };

  // The emitPageBroadcast() function
  const theFunction = function (request) {
    executeOnTab(request.fn, request.options, 0, request.tabID);
  };

  return theFunction;
}());

browser.contextMenus.onClicked.addListener(async (info, tab) => {
  if (info && info.menuItemId) {
    const { menuItemId } = info;
    switch (menuItemId) {
      case 'pause_adblock_everywhere':
        _servermessages__WEBPACK_IMPORTED_MODULE_3__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('cm_pause_clicked');
        adblockIsPaused(true);
        updateButtonUIAndContextMenus(tab);
        break;
      case 'resume_blocking_ads':
        _servermessages__WEBPACK_IMPORTED_MODULE_3__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('cm_unpause_clicked');
        adblockIsPaused(false);
        updateButtonUIAndContextMenus(tab);
        break;
      case 'resume_blocking_ads_unallow':
        _servermessages__WEBPACK_IMPORTED_MODULE_3__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('cm_unpause_clicked');
        await tryToUnwhitelist(info.pageUrl, tab.id);
        updateButtonUIAndContextMenus(tab);
        break;
      case 'domain_pause_adblock':
        _servermessages__WEBPACK_IMPORTED_MODULE_3__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('cm_domain_pause_clicked');
        adblockIsDomainPaused({ url: tab.url, id: tab.id }, true);
        updateButtonUIAndContextMenus(tab);
        break;
      case 'resume_blocking_ads_domain':
        _servermessages__WEBPACK_IMPORTED_MODULE_3__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('cm_domain_unpause_clicked');
        adblockIsDomainPaused({ url: tab.url, id: tab.id }, false);
        updateButtonUIAndContextMenus(tab);
        break;
      case 'block_this_ad':
        emitPageBroadcast({
          fn: 'topOpenBlacklistUI',
          options: {
            info,
            showBlacklistCTA: License.shouldShowBlacklistCTA(),
            isActiveLicense: License.isActiveLicense(),
            settings: getSettings(),
            addCustomFilterRandomName: _messaging_messagevalidator__WEBPACK_IMPORTED_MODULE_5__/* ["default"].generateNewRandomText */ .Z.generateNewRandomText(),
          },
          tabID: tab.id,
        });
        break;
      case 'block_an_ad_on_this_page':
        emitPageBroadcast({
          fn: 'topOpenBlacklistUI',
          options: {
            nothingClicked: true,
            showBlacklistCTA: License.shouldShowBlacklistCTA(),
            isActiveLicense: License.isActiveLicense(),
            settings: getSettings(),
            addCustomFilterRandomName: _messaging_messagevalidator__WEBPACK_IMPORTED_MODULE_5__/* ["default"].generateNewRandomText */ .Z.generateNewRandomText(),
          },
          tabID: tab.id,
        });
        break;
      default:
    }
  }
});

const contextMenuItem = (() => ({
  pauseAll:
  {
    title: browser.i18n.getMessage('pause_adblock_everywhere'),
    id: 'pause_adblock_everywhere',
    contexts: ['all'],
  },
  unpauseAll:
  {
    title: browser.i18n.getMessage('resume_blocking_ads'),
    id: 'resume_blocking_ads',
    contexts: ['all'],
  },
  unAllowList:
  {
    title: browser.i18n.getMessage('resume_blocking_ads'),
    id: 'resume_blocking_ads_unallow',
    contexts: ['all'],
  },
  pauseDomain:
  {
    title: browser.i18n.getMessage('domain_pause_adblock'),
    id: 'domain_pause_adblock',
    contexts: ['all'],
  },
  unpauseDomain:
  {
    title: browser.i18n.getMessage('resume_blocking_ads'),
    id: 'resume_blocking_ads_domain',
    contexts: ['all'],
  },
  blockThisAd:
  {
    title: browser.i18n.getMessage('block_this_ad'),
    id: 'block_this_ad',
    contexts: ['all'],
  },
  blockAnAd:
  {
    title: browser.i18n.getMessage('block_an_ad_on_this_page'),
    id: 'block_an_ad_on_this_page',
    contexts: ['all'],
  },
}))();


const checkLastError = function () {
  if (browser.runtime.lastError) {
    // do nothing
  }
};

let updateContextMenuItems = async function (page) {
  await browser.contextMenus.removeAll();
  // Check if the context menu items should be added
  if (!prefs__WEBPACK_IMPORTED_MODULE_0__/* .Prefs.shouldShowBlockElementMenu */ .B.shouldShowBlockElementMenu) {
    return;
  }
  const domainIsPaused = adblockIsDomainPaused({ url: page.url.href, id: page.id });
  if (adblockIsPaused()) {
    await browser.contextMenus.create(contextMenuItem.unpauseAll, checkLastError);
  } else if (domainIsPaused) {
    await browser.contextMenus.create(contextMenuItem.unpauseDomain, checkLastError);
  } else if ((await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.filters.getAllowingFilters(page.id)).length) {
    await browser.contextMenus.create(contextMenuItem.unAllowList, checkLastError);
  } else {
    await browser.contextMenus.create(contextMenuItem.blockThisAd, checkLastError);
    await browser.contextMenus.create(contextMenuItem.blockAnAd, checkLastError);
    await browser.contextMenus.create(contextMenuItem.pauseDomain, checkLastError);
    await browser.contextMenus.create(contextMenuItem.pauseAll, checkLastError);
  }
};

const updateContextMenuItemsNoOp = function () {
  // Remove the AdBlock context menu items
  browser.contextMenus.removeAll();
};
// startup test to check if the context menu API functions correctly
// the `create` function is invoked twice, because it's the second
// and all subsequent calls that fail.
try {
  browser.contextMenus.create(contextMenuItem.blockThisAd, checkLastError);
  browser.contextMenus.create(contextMenuItem.blockThisAd, checkLastError);
} catch (e) {
  updateContextMenuItems = updateContextMenuItemsNoOp;
}
browser.contextMenus.removeAll();

browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
  if (changeInfo.status) {
    updateContextMenuItems(new ext.Page(tab));
  }
});

browser.tabs.onActivated.addListener(async (activeInfo) => {
  const tab = await browser.tabs.get(activeInfo.tabId);
  updateButtonUIAndContextMenus(tab);
});

browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.command !== 'sendContentToBack') {
    return;
  } // not for us
  emitPageBroadcast({ fn: 'sendContentToBack', options: {}, tabID: sender.tab.id });
  sendResponse({});
});

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.command === 'reloadTabForWhitelist') {
    reloadTab(sender.tab.id, () => {
      emitPageBroadcast({
        fn: 'topOpenWhitelistCompletionUI',
        options: {
          rule: request.rule,
          isActiveLicense: License.isActiveLicense(),
          showWhitelistCTA: License.shouldShowWhitelistCTA(),
        },
        tabID: sender.tab.id,
      });
    });
    sendResponse({});
  }
});

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.command === 'showWhitelistCompletion') {
    emitPageBroadcast({
      fn: 'topOpenWhitelistCompletionUI',
      options: {
        rule: request.rule,
        isActiveLicense: License.isActiveLicense(),
        showWhitelistCTA: License.shouldShowWhitelistCTA(),
      },
      tabID: sender.tab.id,
    });
    sendResponse({});
  }
});

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.command === 'showBlacklist' && typeof request.nothingClicked === 'boolean') {
    emitPageBroadcast({
      fn: 'topOpenBlacklistUI',
      options: {
        nothingClicked: request.nothingClicked,
        isActiveLicense: License.isActiveLicense(),
        showBlacklistCTA: License.shouldShowBlacklistCTA(),
        settings: getSettings(),
        addCustomFilterRandomName: _messaging_messagevalidator__WEBPACK_IMPORTED_MODULE_5__/* ["default"].generateNewRandomText */ .Z.generateNewRandomText(),
      },
      tabID: request.tabId,
    });
    sendResponse({});
  }
});

browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
  if (request.command === 'showWhitelist') {
    emitPageBroadcast({
      fn: 'topOpenWhitelistUI',
      options: {
        addCustomFilterRandomName: _messaging_messagevalidator__WEBPACK_IMPORTED_MODULE_5__/* ["default"].generateNewRandomText */ .Z.generateNewRandomText(),
      },
      tabID: request.tabId,
    });
    sendResponse({});
  }
});

// Update browser actions and context menus when whitelisting might have
// changed. That is now when initally loading the filters and later when
// importing backups or saving filter changes.
// Update browser actions and context menus when whitelisting might have
// changed. That is now when initally loading the filters and later when
// importing backups or saving filter changes.
_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.subscriptions.onAdded.addListener(updateButtonUIAndContextMenus);
_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.subscriptions.onChanged.addListener(updateButtonUIAndContextMenus);
_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.subscriptions.onRemoved.addListener(updateButtonUIAndContextMenus);

prefs__WEBPACK_IMPORTED_MODULE_0__/* .Prefs.on */ .B.on(prefs__WEBPACK_IMPORTED_MODULE_0__/* .Prefs.shouldShowBlockElementMenu */ .B.shouldShowBlockElementMenu, () => {
  updateButtonUIAndContextMenus();
});

updateButtonUIAndContextMenus();

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  emitPageBroadcast,
  updateButtonUIAndContextMenus,
});


/***/ }),

/***/ 5953:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var info__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(755);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var _subscriptionadapter__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1974);
/* harmony import */ var _fetch_util__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(8171);
/* harmony import */ var _prefs_background__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1648);
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7337);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, adblockIsPaused,
   adblockIsDomainPaused, getUserFilters, */








const DataCollectionV2 = (function getDataCollectionV2() {
  const HOUR_IN_MIN = 60;
  const TIME_LAST_PUSH_KEY = 'timeLastPush';
  const DATA_COLLECTION_ALARM_NAME = 'datacollectionalarm';
  const STORAGE_KEY = 'ab:data.collection.storage.key';
  const REPORTING_OPTIONS = {
    filterType: 'all',
    includeElementHiding: false,
  };

  // Setup memory cache
  let dataCollectionCache = {};
  dataCollectionCache.filters = {};
  dataCollectionCache.domains = {};

  const addFilterToCache = async function (details, filter) {
    const validFilterText = filter && filter.text && (typeof filter.text === 'string');
    if (validFilterText && details && details.url) {
      let domain = details.url.hostname;
      if (!domain) {
        domain = new URL(details.url).hostname;
        if (!domain) {
          return;
        }
      }
      const { text } = filter;

      if (!(text in dataCollectionCache.filters)) {
        dataCollectionCache.filters[text] = {};
        dataCollectionCache.filters[text].firstParty = {};
        dataCollectionCache.filters[text].thirdParty = {};
        dataCollectionCache.filters[text].subscriptions = [];
      }
      if (filter.thirdParty) {
        if (!dataCollectionCache.filters[text].thirdParty[domain]) {
          dataCollectionCache.filters[text].thirdParty[domain] = {};
          dataCollectionCache.filters[text].thirdParty[domain].hits = 0;
        }
        dataCollectionCache.filters[text].thirdParty[domain].hits += 1;
      } else {
        if (!dataCollectionCache.filters[text].firstParty[domain]) {
          dataCollectionCache.filters[text].firstParty[domain] = {};
          dataCollectionCache.filters[text].firstParty[domain].hits = 0;
        }
        dataCollectionCache.filters[text].firstParty[domain].hits += 1;
      }
      const subscriptions = await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.subscriptions.getForFilter(text);
      subscriptions.forEach((sub) => {
        if (sub.enabled && sub.url && sub.downloadable) {
          const subURL = sub.url.substring(0, 256);
          if (!dataCollectionCache.filters[text].subscriptions.includes(subURL)) {
            dataCollectionCache.filters[text].subscriptions.push(subURL);
          }
        }
      });
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageSetHelper */ .rJ)(STORAGE_KEY, dataCollectionCache);
    }
  };

  const webRequestListener = function (details) {
    if (details.url && details.type === 'main_frame' && !adblockIsPaused() && !adblockIsDomainPaused({ url: details.url, id: details.id })) {
      const domain = (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .parseUri */ .he)(details.url).host;
      if (!dataCollectionCache.domains[domain]) {
        dataCollectionCache.domains[domain] = {};
        dataCollectionCache.domains[domain].pages = 0;
      }
      dataCollectionCache.domains[domain].pages += 1;
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageSetHelper */ .rJ)(STORAGE_KEY, dataCollectionCache);
    }
  };

  const filterListener = function ({ request, filter }) {
    if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().data_collection_v2 && !adblockIsPaused()) {
      addFilterToCache(request, filter);
    } else if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().data_collection_v2) {
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.reporting.onBlockableItem.removeListener(filterListener, REPORTING_OPTIONS);
      browser.alarms.clear(DATA_COLLECTION_ALARM_NAME);
    }
  };

  const sendToServer = async function () {
    const dataCollectionSetting = (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().data_collection_v2;
    if (!dataCollectionSetting) {
      browser.alarms.clear(DATA_COLLECTION_ALARM_NAME);
    }
    if (dataCollectionSetting && Object.keys(dataCollectionCache.filters).length > 0) {
      const subscribedSubs = [];
      const subs = await _subscriptionadapter__WEBPACK_IMPORTED_MODULE_2__/* ["default"].getSubscriptionsMinusText */ .Z.getSubscriptionsMinusText();
      for (const subscription of Object.values(subs)) {
        if (subscription && subscription.url) {
          subscribedSubs.push(subscription.url.substring(0, 256));
        }
      }
      if (await getUserFilters().length) {
        subscribedSubs.push('customlist');
      }
      const data = {
        version: '5',
        addonName: info__WEBPACK_IMPORTED_MODULE_0__.addonName,
        addonVersion: info__WEBPACK_IMPORTED_MODULE_0__.addonVersion,
        application: info__WEBPACK_IMPORTED_MODULE_0__.application,
        applicationVersion: info__WEBPACK_IMPORTED_MODULE_0__.applicationVersion,
        platform: info__WEBPACK_IMPORTED_MODULE_0__.platform,
        platformVersion: info__WEBPACK_IMPORTED_MODULE_0__.platformVersion,
        appLocale: browser.i18n.getUILanguage(),
        filterListSubscriptions: subscribedSubs,
        domains: dataCollectionCache.domains,
        filters: dataCollectionCache.filters,
      };
      browser.storage.local.get(TIME_LAST_PUSH_KEY).then((response) => {
        let timeLastPush = 'n/a';
        if (response[TIME_LAST_PUSH_KEY]) {
          const serverTimestamp = new Date(response[TIME_LAST_PUSH_KEY]);
          // Format the timeLastPush
          const yearStr = `${serverTimestamp.getUTCFullYear()}`;
          let monthStr = `${serverTimestamp.getUTCMonth() + 1}`;
          let dateStr = `${serverTimestamp.getUTCDate()}`;
          let hourStr = `${serverTimestamp.getUTCHours()}`;
          // round the minutes up to the nearest 10
          let minStr = `${Math.floor(serverTimestamp.getUTCMinutes() / 10) * 10}`;

          if (monthStr.length === 1) {
            monthStr = `0${monthStr}`;
          }
          if (dateStr.length === 1) {
            dateStr = `0${dateStr}`;
          }
          if (hourStr.length === 1) {
            hourStr = `0${hourStr}`;
          }
          if (minStr.length === 1) {
            minStr = `0${minStr}`;
          }
          if (minStr === '60') {
            minStr = '00';
          }
          timeLastPush = `${yearStr}-${monthStr}-${dateStr} ${hourStr}:${minStr}:00`;
        }
        data.timeOfLastPush = timeLastPush;
        (0,_fetch_util__WEBPACK_IMPORTED_MODULE_5__/* ["default"] */ .Z)('https://log.getadblock.com/v2/record_log.php', data)
          .then((postResponse) => {
            if (postResponse.ok) {
              let nowTimestamp = (new Date()).toGMTString();
              try {
                if (postResponse.headers.has('date')) {
                  nowTimestamp = postResponse.headers.get('date');
                }
              } catch (e) {
                nowTimestamp = (new Date()).toGMTString();
              }
              (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .chromeStorageSetHelper */ .rJ)(TIME_LAST_PUSH_KEY, nowTimestamp);
              // Reset memory cache
              dataCollectionCache = {};
              dataCollectionCache.filters = {};
              dataCollectionCache.domains = {};
              browser.storage.local.remove(STORAGE_KEY);
              return;
            }
            (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_4__/* .log */ .cM)('bad response from log server', postResponse);
          });
      }); // end of TIME_LAST_PUSH_KEY
    }
  };

  const loadCache = async function () {
    const response = await browser.storage.local.get(STORAGE_KEY);
    if (response[STORAGE_KEY]) {
      dataCollectionCache = response[STORAGE_KEY];
    }
  };

  const initializeAlarm = function () {
    const processAlarm = async function (alarm) {
      if (!alarm && alarm.name !== DATA_COLLECTION_ALARM_NAME) {
        return;
      }
      await _prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .settings.onload */ .Xd.onload();
      if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().data_collection_v2) {
        await loadCache();
        sendToServer();
      } else {
        browser.alarms.clear(DATA_COLLECTION_ALARM_NAME);
        browser.alarms.onAlarm.removeListener(processAlarm);
      }
    };
    browser.alarms.onAlarm.addListener(processAlarm);
  };

  // If enabled at startup periodic saving of memory cache &
  // sending of data to the log server
  const initialize = function () {
    initializeAlarm();
    _prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .settings.onload */ .Xd.onload().then(async () => {
      if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().data_collection_v2) {
        return;
      }
      await loadCache();
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.reporting.onBlockableItem.addListener(filterListener, REPORTING_OPTIONS);
      browser.webRequest.onBeforeRequest.addListener(webRequestListener, {
        urls: ['http://*/*', 'https://*/*'],
        types: ['main_frame'],
      });
      browser.alarms.create(DATA_COLLECTION_ALARM_NAME, { periodInMinutes: HOUR_IN_MIN });
    });
  };
  initialize();


  const returnObj = {};
  returnObj.start = function returnObjStart() {
    dataCollectionCache.filters = {};
    dataCollectionCache.domains = {};
    (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .setSetting */ .Lt)('data_collection_v2', true, () => {
      initialize();
    });
  };
  returnObj.end = function returnObjEnd() {
    dataCollectionCache = {};
    _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_1__.reporting.onBlockableItem.removeListener(filterListener, REPORTING_OPTIONS);
    browser.webRequest.onBeforeRequest.removeListener(webRequestListener);
    browser.storage.local.remove(TIME_LAST_PUSH_KEY);
    browser.storage.local.remove(STORAGE_KEY);
    browser.alarms.clear(DATA_COLLECTION_ALARM_NAME);
    (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .setSetting */ .Lt)('data_collection_v2', false);
  };
  returnObj.getCache = function returnObjGetCache() {
    return dataCollectionCache;
  };

  return returnObj;
}());

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (DataCollectionV2);


/***/ }),

/***/ 228:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7337);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser */



// Send the file name and line number of any error message. This will help us
// to trace down any frequent errors we can't confirm ourselves.
/* eslint-disable no-restricted-globals */
self.addEventListener('error', (e) => {
  if (!e.filename && !e.lineno && !e.colno && !e.error && !e.message) {
    return;
  }
  let str = `Error: ${
    (e.filename || 'anywhere').replace(browser.runtime.getURL(''), '')
  }:${e.lineno || 'anywhere'
  }:${e.colno || 'anycol'}`;
  if (e.message) {
    str += `: ${e.message}`;
  }
  const src = e.target.src || e.target.href;
  if (src) {
    str += `src: ${src}`;
  }
  if (e.error) {
    let stack = `-${e.error.message || ''
    }-${e.error.stack || ''}`;
    stack = stack.replace(/:/gi, ';').replace(/\n/gi, '');
    // only append the stack info if there isn't any URL info in the stack trace
    if (stack.indexOf('http') === -1) {
      str += stack;
    }
    // don't send large stack traces
    if (str.length > 1024) {
      str = str.substr(0, 1023);
    }
  }
  (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__/* .chromeStorageSetHelper */ .rJ)('errorkey', `Date added:${new Date()} ${str}`);
  // eslint-disable-next-line no-console
  console.log(str);
});


/***/ }),

/***/ 3890:
/***/ (() => {

/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global importScripts
*/

if (typeof importScripts !== 'undefined') {
  importScripts('polyfill.js');
  importScripts('ext/common.js');
  importScripts('ext/background.js');
}


/***/ }),

/***/ 8171:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (/* binding */ postData)
/* harmony export */ });
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */

async function postData(url = '', payload = {}) {
  return fetch(url, {
    method: 'POST',
    cache: 'no-cache',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  });
}


/***/ }),

/***/ 1940:
/***/ (function(module, exports) {

var __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function(e,t){"use strict"; true&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0<t&&t-1 in e)}S.fn=S.prototype={jquery:f,constructor:S,length:0,toArray:function(){return s.call(this)},get:function(e){return null==e?s.call(this):e<0?this[e+this.length]:this[e]},pushStack:function(e){var t=S.merge(this.constructor(),e);return t.prevObject=this,t},each:function(e){return S.each(this,e)},map:function(n){return this.pushStack(S.map(this,function(e,t){return n.call(e,t,e)}))},slice:function(){return this.pushStack(s.apply(this,arguments))},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},even:function(){return this.pushStack(S.grep(this,function(e,t){return(t+1)%2}))},odd:function(){return this.pushStack(S.grep(this,function(e,t){return t%2}))},eq:function(e){var t=this.length,n=+e+(e<0?t:0);return this.pushStack(0<=n&&n<t?[this[n]]:[])},end:function(){return this.prevObject||this.constructor()},push:u,sort:t.sort,splice:t.splice},S.extend=S.fn.extend=function(){var e,t,n,r,i,o,a=arguments[0]||{},s=1,u=arguments.length,l=!1;for("boolean"==typeof a&&(l=a,a=arguments[s]||{},s++),"object"==typeof a||m(a)||(a={}),s===u&&(a=this,s--);s<u;s++)if(null!=(e=arguments[s]))for(t in e)r=e[t],"__proto__"!==t&&a!==r&&(l&&r&&(S.isPlainObject(r)||(i=Array.isArray(r)))?(n=a[t],o=i&&!Array.isArray(n)?[]:i||S.isPlainObject(n)?n:{},i=!1,a[t]=S.extend(l,o,r)):void 0!==r&&(a[t]=r));return a},S.extend({expando:"jQuery"+(f+Math.random()).replace(/\D/g,""),isReady:!0,error:function(e){throw new Error(e)},noop:function(){},isPlainObject:function(e){var t,n;return!(!e||"[object Object]"!==o.call(e))&&(!(t=r(e))||"function"==typeof(n=v.call(t,"constructor")&&t.constructor)&&a.call(n)===l)},isEmptyObject:function(e){var t;for(t in e)return!1;return!0},globalEval:function(e,t,n){b(e,{nonce:t&&t.nonce},n)},each:function(e,t){var n,r=0;if(p(e)){for(n=e.length;r<n;r++)if(!1===t.call(e[r],r,e[r]))break}else for(r in e)if(!1===t.call(e[r],r,e[r]))break;return e},makeArray:function(e,t){var n=t||[];return null!=e&&(p(Object(e))?S.merge(n,"string"==typeof e?[e]:e):u.call(n,e)),n},inArray:function(e,t,n){return null==t?-1:i.call(t,e,n)},merge:function(e,t){for(var n=+t.length,r=0,i=e.length;r<n;r++)e[i++]=t[r];return e.length=i,e},grep:function(e,t,n){for(var r=[],i=0,o=e.length,a=!n;i<o;i++)!t(e[i],i)!==a&&r.push(e[i]);return r},map:function(e,t,n){var r,i,o=0,a=[];if(p(e))for(r=e.length;o<r;o++)null!=(i=t(e[o],o,n))&&a.push(i);else for(o in e)null!=(i=t(e[o],o,n))&&a.push(i);return g(a)},guid:1,support:y}),"function"==typeof Symbol&&(S.fn[Symbol.iterator]=t[Symbol.iterator]),S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "),function(e,t){n["[object "+t+"]"]=t.toLowerCase()});var d=function(n){var e,d,b,o,i,h,f,g,w,u,l,T,C,a,E,v,s,c,y,S="sizzle"+1*new Date,p=n.document,k=0,r=0,m=ue(),x=ue(),A=ue(),N=ue(),D=function(e,t){return e===t&&(l=!0),0},j={}.hasOwnProperty,t=[],q=t.pop,L=t.push,H=t.push,O=t.slice,P=function(e,t){for(var n=0,r=e.length;n<r;n++)if(e[n]===t)return n;return-1},R="checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",M="[\\x20\\t\\r\\n\\f]",I="(?:\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+",W="\\["+M+"*("+I+")(?:"+M+"*([*^$|!~]?=)"+M+"*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|("+I+"))|)"+M+"*\\]",F=":("+I+")(?:\\((('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|((?:\\\\.|[^\\\\()[\\]]|"+W+")*)|.*)\\)|)",B=new RegExp(M+"+","g"),$=new RegExp("^"+M+"+|((?:^|[^\\\\])(?:\\\\.)*)"+M+"+$","g"),_=new RegExp("^"+M+"*,"+M+"*"),z=new RegExp("^"+M+"*([>+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="<a id='"+S+"'></a><select id='"+S+"-\r\\' msallowcapture=''><option selected=''></option></select>",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="<a href='' disabled='disabled'></a><select disabled='disabled'><option/></select>";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0<se(t,C,null,[e]).length},se.contains=function(e,t){return(e.ownerDocument||e)!=C&&T(e),y(e,t)},se.attr=function(e,t){(e.ownerDocument||e)!=C&&T(e);var n=b.attrHandle[t.toLowerCase()],r=n&&j.call(b.attrHandle,t.toLowerCase())?n(e,t,!E):void 0;return void 0!==r?r:d.attributes||!E?e.getAttribute(t):(r=e.getAttributeNode(t))&&r.specified?r.value:null},se.escape=function(e){return(e+"").replace(re,ie)},se.error=function(e){throw new Error("Syntax error, unrecognized expression: "+e)},se.uniqueSort=function(e){var t,n=[],r=0,i=0;if(l=!d.detectDuplicates,u=!d.sortStable&&e.slice(0),e.sort(D),l){while(t=e[i++])t===e[i]&&(r=n.push(i));while(r--)e.splice(n[r],1)}return u=null,e},o=se.getText=function(e){var t,n="",r=0,i=e.nodeType;if(i){if(1===i||9===i||11===i){if("string"==typeof e.textContent)return e.textContent;for(e=e.firstChild;e;e=e.nextSibling)n+=o(e)}else if(3===i||4===i)return e.nodeValue}else while(t=e[r++])n+=o(t);return n},(b=se.selectors={cacheLength:50,createPseudo:le,match:G,attrHandle:{},find:{},relative:{">":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1<t.indexOf(i):"$="===r?i&&t.slice(-i.length)===i:"~="===r?-1<(" "+t.replace(B," ")+" ").indexOf(i):"|="===r&&(t===i||t.slice(0,i.length+1)===i+"-"))}},CHILD:function(h,e,t,g,v){var y="nth"!==h.slice(0,3),m="last"!==h.slice(-4),x="of-type"===e;return 1===g&&0===v?function(e){return!!e.parentNode}:function(e,t,n){var r,i,o,a,s,u,l=y!==m?"nextSibling":"previousSibling",c=e.parentNode,f=x&&e.nodeName.toLowerCase(),p=!n&&!x,d=!1;if(c){if(y){while(l){a=e;while(a=a[l])if(x?a.nodeName.toLowerCase()===f:1===a.nodeType)return!1;u=l="only"===h&&!u&&"nextSibling"}return!0}if(u=[m?c.firstChild:c.lastChild],m&&p){d=(s=(r=(i=(o=(a=c)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1])&&r[2],a=s&&c.childNodes[s];while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if(1===a.nodeType&&++d&&a===e){i[h]=[k,s,d];break}}else if(p&&(d=s=(r=(i=(o=(a=e)[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]||[])[0]===k&&r[1]),!1===d)while(a=++s&&a&&a[l]||(d=s=0)||u.pop())if((x?a.nodeName.toLowerCase()===f:1===a.nodeType)&&++d&&(p&&((i=(o=a[S]||(a[S]={}))[a.uniqueID]||(o[a.uniqueID]={}))[h]=[k,d]),a===e))break;return(d-=v)===g||d%g==0&&0<=d/g}}},PSEUDO:function(e,o){var t,a=b.pseudos[e]||b.setFilters[e.toLowerCase()]||se.error("unsupported pseudo: "+e);return a[S]?a(o):1<a.length?(t=[e,e,"",o],b.setFilters.hasOwnProperty(e.toLowerCase())?le(function(e,t){var n,r=a(e,o),i=r.length;while(i--)e[n=P(e,r[i])]=!(t[n]=r[i])}):function(e){return a(e,0,t)}):a}},pseudos:{not:le(function(e){var r=[],i=[],s=f(e.replace($,"$1"));return s[S]?le(function(e,t,n,r){var i,o=s(e,null,r,[]),a=e.length;while(a--)(i=o[a])&&(e[a]=!(t[a]=i))}):function(e,t,n){return r[0]=e,s(r,null,n,i),r[0]=null,!i.pop()}}),has:le(function(t){return function(e){return 0<se(t,e).length}}),contains:le(function(t){return t=t.replace(te,ne),function(e){return-1<(e.textContent||o(e)).indexOf(t)}}),lang:le(function(n){return V.test(n||"")||se.error("unsupported lang: "+n),n=n.replace(te,ne).toLowerCase(),function(e){var t;do{if(t=E?e.lang:e.getAttribute("xml:lang")||e.getAttribute("lang"))return(t=t.toLowerCase())===n||0===t.indexOf(n+"-")}while((e=e.parentNode)&&1===e.nodeType);return!1}}),target:function(e){var t=n.location&&n.location.hash;return t&&t.slice(1)===e.id},root:function(e){return e===a},focus:function(e){return e===C.activeElement&&(!C.hasFocus||C.hasFocus())&&!!(e.type||e.href||~e.tabIndex)},enabled:ge(!1),disabled:ge(!0),checked:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&!!e.checked||"option"===t&&!!e.selected},selected:function(e){return e.parentNode&&e.parentNode.selectedIndex,!0===e.selected},empty:function(e){for(e=e.firstChild;e;e=e.nextSibling)if(e.nodeType<6)return!1;return!0},parent:function(e){return!b.pseudos.empty(e)},header:function(e){return J.test(e.nodeName)},input:function(e){return Q.test(e.nodeName)},button:function(e){var t=e.nodeName.toLowerCase();return"input"===t&&"button"===e.type||"button"===t},text:function(e){var t;return"input"===e.nodeName.toLowerCase()&&"text"===e.type&&(null==(t=e.getAttribute("type"))||"text"===t.toLowerCase())},first:ve(function(){return[0]}),last:ve(function(e,t){return[t-1]}),eq:ve(function(e,t,n){return[n<0?n+t:n]}),even:ve(function(e,t){for(var n=0;n<t;n+=2)e.push(n);return e}),odd:ve(function(e,t){for(var n=1;n<t;n+=2)e.push(n);return e}),lt:ve(function(e,t,n){for(var r=n<0?n+t:t<n?t:n;0<=--r;)e.push(r);return e}),gt:ve(function(e,t,n){for(var r=n<0?n+t:n;++r<t;)e.push(r);return e})}}).pseudos.nth=b.pseudos.eq,{radio:!0,checkbox:!0,file:!0,password:!0,image:!0})b.pseudos[e]=de(e);for(e in{submit:!0,reset:!0})b.pseudos[e]=he(e);function me(){}function xe(e){for(var t=0,n=e.length,r="";t<n;t++)r+=e[t].value;return r}function be(s,e,t){var u=e.dir,l=e.next,c=l||u,f=t&&"parentNode"===c,p=r++;return e.first?function(e,t,n){while(e=e[u])if(1===e.nodeType||f)return s(e,t,n);return!1}:function(e,t,n){var r,i,o,a=[k,p];if(n){while(e=e[u])if((1===e.nodeType||f)&&s(e,t,n))return!0}else while(e=e[u])if(1===e.nodeType||f)if(i=(o=e[S]||(e[S]={}))[e.uniqueID]||(o[e.uniqueID]={}),l&&l===e.nodeName.toLowerCase())e=e[u]||e;else{if((r=i[c])&&r[0]===k&&r[1]===p)return a[2]=r[2];if((i[c]=a)[2]=s(e,t,n))return!0}return!1}}function we(i){return 1<i.length?function(e,t,n){var r=i.length;while(r--)if(!i[r](e,t,n))return!1;return!0}:i[0]}function Te(e,t,n,r,i){for(var o,a=[],s=0,u=e.length,l=null!=t;s<u;s++)(o=e[s])&&(n&&!n(o,r,i)||(a.push(o),l&&t.push(s)));return a}function Ce(d,h,g,v,y,e){return v&&!v[S]&&(v=Ce(v)),y&&!y[S]&&(y=Ce(y,e)),le(function(e,t,n,r){var i,o,a,s=[],u=[],l=t.length,c=e||function(e,t,n){for(var r=0,i=t.length;r<i;r++)se(e,t[r],n);return n}(h||"*",n.nodeType?[n]:n,[]),f=!d||!e&&h?c:Te(c,s,d,n,r),p=g?y||(e?d:l||v)?[]:t:f;if(g&&g(f,p,n,r),v){i=Te(p,u),v(i,[],n,r),o=i.length;while(o--)(a=i[o])&&(p[u[o]]=!(f[u[o]]=a))}if(e){if(y||d){if(y){i=[],o=p.length;while(o--)(a=p[o])&&i.push(f[o]=a);y(null,p=[],i,r)}o=p.length;while(o--)(a=p[o])&&-1<(i=y?P(e,a):s[o])&&(e[i]=!(t[i]=a))}}else p=Te(p===t?p.splice(l,p.length):p),y?y(null,t,p,r):H.apply(t,p)})}function Ee(e){for(var i,t,n,r=e.length,o=b.relative[e[0].type],a=o||b.relative[" "],s=o?1:0,u=be(function(e){return e===i},a,!0),l=be(function(e){return-1<P(i,e)},a,!0),c=[function(e,t,n){var r=!o&&(n||t!==w)||((i=t).nodeType?u(e,t,n):l(e,t,n));return i=null,r}];s<r;s++)if(t=b.relative[e[s].type])c=[be(we(c),t)];else{if((t=b.filter[e[s].type].apply(null,e[s].matches))[S]){for(n=++s;n<r;n++)if(b.relative[e[n].type])break;return Ce(1<s&&we(c),1<s&&xe(e.slice(0,s-1).concat({value:" "===e[s-2].type?"*":""})).replace($,"$1"),t,s<n&&Ee(e.slice(s,n)),n<r&&Ee(e=e.slice(n)),n<r&&xe(e))}c.push(t)}return we(c)}return me.prototype=b.filters=b.pseudos,b.setFilters=new me,h=se.tokenize=function(e,t){var n,r,i,o,a,s,u,l=x[e+" "];if(l)return t?0:l.slice(0);a=e,s=[],u=b.preFilter;while(a){for(o in n&&!(r=_.exec(a))||(r&&(a=a.slice(r[0].length)||a),s.push(i=[])),n=!1,(r=z.exec(a))&&(n=r.shift(),i.push({value:n,type:r[0].replace($," ")}),a=a.slice(n.length)),b.filter)!(r=G[o].exec(a))||u[o]&&!(r=u[o](r))||(n=r.shift(),i.push({value:n,type:o,matches:r}),a=a.slice(n.length));if(!n)break}return t?a.length:a?se.error(e):x(e,s).slice(0)},f=se.compile=function(e,t){var n,v,y,m,x,r,i=[],o=[],a=A[e+" "];if(!a){t||(t=h(e)),n=t.length;while(n--)(a=Ee(t[n]))[S]?i.push(a):o.push(a);(a=A(e,(v=o,m=0<(y=i).length,x=0<v.length,r=function(e,t,n,r,i){var o,a,s,u=0,l="0",c=e&&[],f=[],p=w,d=e||x&&b.find.TAG("*",i),h=k+=null==p?1:Math.random()||.1,g=d.length;for(i&&(w=t==C||t||i);l!==g&&null!=(o=d[l]);l++){if(x&&o){a=0,t||o.ownerDocument==C||(T(o),n=!E);while(s=v[a++])if(s(o,t||C,n)){r.push(o);break}i&&(k=h)}m&&((o=!s&&o)&&u--,e&&c.push(o))}if(u+=l,m&&l!==u){a=0;while(s=y[a++])s(c,f,t,n);if(e){if(0<u)while(l--)c[l]||f[l]||(f[l]=q.call(r));f=Te(f)}H.apply(r,f),i&&!e&&0<f.length&&1<u+y.length&&se.uniqueSort(r)}return i&&(k=h,w=p),c},m?le(r):r))).selector=e}return a},g=se.select=function(e,t,n,r){var i,o,a,s,u,l="function"==typeof e&&e,c=!r&&h(e=l.selector||e);if(n=n||[],1===c.length){if(2<(o=c[0]=c[0].slice(0)).length&&"ID"===(a=o[0]).type&&9===t.nodeType&&E&&b.relative[o[1].type]){if(!(t=(b.find.ID(a.matches[0].replace(te,ne),t)||[])[0]))return n;l&&(t=t.parentNode),e=e.slice(o.shift().value.length)}i=G.needsContext.test(e)?0:o.length;while(i--){if(a=o[i],b.relative[s=a.type])break;if((u=b.find[s])&&(r=u(a.matches[0].replace(te,ne),ee.test(o[0].type)&&ye(t.parentNode)||t))){if(o.splice(i,1),!(e=r.length&&xe(o)))return H.apply(n,r),n;break}}}return(l||f(e,c))(r,t,!E,n,!t||ee.test(e)&&ye(t.parentNode)||t),n},d.sortStable=S.split("").sort(D).join("")===S,d.detectDuplicates=!!l,T(),d.sortDetached=ce(function(e){return 1&e.compareDocumentPosition(C.createElement("fieldset"))}),ce(function(e){return e.innerHTML="<a href='#'></a>","#"===e.firstChild.getAttribute("href")})||fe("type|href|height|width",function(e,t,n){if(!n)return e.getAttribute(t,"type"===t.toLowerCase()?1:2)}),d.attributes&&ce(function(e){return e.innerHTML="<input/>",e.firstChild.setAttribute("value",""),""===e.firstChild.getAttribute("value")})||fe("value",function(e,t,n){if(!n&&"input"===e.nodeName.toLowerCase())return e.defaultValue}),ce(function(e){return null==e.getAttribute("disabled")})||fe(R,function(e,t,n){var r;if(!n)return!0===e[t]?t.toLowerCase():(r=e.getAttributeNode(t))&&r.specified?r.value:null}),se}(C);S.find=d,S.expr=d.selectors,S.expr[":"]=S.expr.pseudos,S.uniqueSort=S.unique=d.uniqueSort,S.text=d.getText,S.isXMLDoc=d.isXML,S.contains=d.contains,S.escapeSelector=d.escape;var h=function(e,t,n){var r=[],i=void 0!==n;while((e=e[t])&&9!==e.nodeType)if(1===e.nodeType){if(i&&S(e).is(n))break;r.push(e)}return r},T=function(e,t){for(var n=[];e;e=e.nextSibling)1===e.nodeType&&e!==t&&n.push(e);return n},k=S.expr.match.needsContext;function A(e,t){return e.nodeName&&e.nodeName.toLowerCase()===t.toLowerCase()}var N=/^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1<i.call(n,e)!==r}):S.filter(n,e,r)}S.filter=function(e,t,n){var r=t[0];return n&&(e=":not("+e+")"),1===t.length&&1===r.nodeType?S.find.matchesSelector(r,e)?[r]:[]:S.find.matches(e,S.grep(t,function(e){return 1===e.nodeType}))},S.fn.extend({find:function(e){var t,n,r=this.length,i=this;if("string"!=typeof e)return this.pushStack(S(e).filter(function(){for(t=0;t<r;t++)if(S.contains(i[t],this))return!0}));for(n=this.pushStack([]),t=0;t<r;t++)S.find(e,i[t],n);return 1<r?S.uniqueSort(n):n},filter:function(e){return this.pushStack(D(this,e||[],!1))},not:function(e){return this.pushStack(D(this,e||[],!0))},is:function(e){return!!D(this,"string"==typeof e&&k.test(e)?S(e):e||[],!1).length}});var j,q=/^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e<n;e++)if(S.contains(this,t[e]))return!0})},closest:function(e,t){var n,r=0,i=this.length,o=[],a="string"!=typeof e&&S(e);if(!k.test(e))for(;r<i;r++)for(n=this[r];n&&n!==t;n=n.parentNode)if(n.nodeType<11&&(a?-1<a.index(n):1===n.nodeType&&S.find.matchesSelector(n,e))){o.push(n);break}return this.pushStack(1<o.length?S.uniqueSort(o):o)},index:function(e){return e?"string"==typeof e?i.call(S(e),this[0]):i.call(this,e.jquery?e[0]:e):this[0]&&this[0].parentNode?this.first().prevAll().length:-1},add:function(e,t){return this.pushStack(S.uniqueSort(S.merge(this.get(),S(e,t))))},addBack:function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}}),S.each({parent:function(e){var t=e.parentNode;return t&&11!==t.nodeType?t:null},parents:function(e){return h(e,"parentNode")},parentsUntil:function(e,t,n){return h(e,"parentNode",n)},next:function(e){return O(e,"nextSibling")},prev:function(e){return O(e,"previousSibling")},nextAll:function(e){return h(e,"nextSibling")},prevAll:function(e){return h(e,"previousSibling")},nextUntil:function(e,t,n){return h(e,"nextSibling",n)},prevUntil:function(e,t,n){return h(e,"previousSibling",n)},siblings:function(e){return T((e.parentNode||{}).firstChild,e)},children:function(e){return T(e.firstChild)},contents:function(e){return null!=e.contentDocument&&r(e.contentDocument)?e.contentDocument:(A(e,"template")&&(e=e.content||e),S.merge([],e.childNodes))}},function(r,i){S.fn[r]=function(e,t){var n=S.map(this,i,e);return"Until"!==r.slice(-5)&&(t=e),t&&"string"==typeof t&&(n=S.filter(t,n)),1<this.length&&(H[r]||S.uniqueSort(n),L.test(r)&&n.reverse()),this.pushStack(n)}});var P=/[^\x20\t\r\n\f]+/g;function R(e){return e}function M(e){throw e}function I(e,t,n,r){var i;try{e&&m(i=e.promise)?i.call(e).done(t).fail(n):e&&m(i=e.then)?i.call(e,t,n):t.apply(void 0,[e].slice(r))}catch(e){n.apply(void 0,[e])}}S.Callbacks=function(r){var e,n;r="string"==typeof r?(e=r,n={},S.each(e.match(P)||[],function(e,t){n[t]=!0}),n):S.extend({},r);var i,t,o,a,s=[],u=[],l=-1,c=function(){for(a=a||r.once,o=i=!0;u.length;l=-1){t=u.shift();while(++l<s.length)!1===s[l].apply(t[0],t[1])&&r.stopOnFalse&&(l=s.length,t=!1)}r.memory||(t=!1),i=!1,a&&(s=t?[]:"")},f={add:function(){return s&&(t&&!i&&(l=s.length-1,u.push(t)),function n(e){S.each(e,function(e,t){m(t)?r.unique&&f.has(t)||s.push(t):t&&t.length&&"string"!==w(t)&&n(t)})}(arguments),t&&!i&&c()),this},remove:function(){return S.each(arguments,function(e,t){var n;while(-1<(n=S.inArray(t,s,n)))s.splice(n,1),n<=l&&l--}),this},has:function(e){return e?-1<S.inArray(e,s):0<s.length},empty:function(){return s&&(s=[]),this},disable:function(){return a=u=[],s=t="",this},disabled:function(){return!s},lock:function(){return a=u=[],t||i||(s=t=""),this},locked:function(){return!!a},fireWith:function(e,t){return a||(t=[e,(t=t||[]).slice?t.slice():t],u.push(t),i||c()),this},fire:function(){return f.fireWith(this,arguments),this},fired:function(){return!!o}};return f},S.extend({Deferred:function(e){var o=[["notify","progress",S.Callbacks("memory"),S.Callbacks("memory"),2],["resolve","done",S.Callbacks("once memory"),S.Callbacks("once memory"),0,"resolved"],["reject","fail",S.Callbacks("once memory"),S.Callbacks("once memory"),1,"rejected"]],i="pending",a={state:function(){return i},always:function(){return s.done(arguments).fail(arguments),this},"catch":function(e){return a.then(null,e)},pipe:function(){var i=arguments;return S.Deferred(function(r){S.each(o,function(e,t){var n=m(i[t[4]])&&i[t[4]];s[t[1]](function(){var e=n&&n.apply(this,arguments);e&&m(e.promise)?e.promise().progress(r.notify).done(r.resolve).fail(r.reject):r[t[0]+"With"](this,n?[e]:arguments)})}),i=null}).promise()},then:function(t,n,r){var u=0;function l(i,o,a,s){return function(){var n=this,r=arguments,e=function(){var e,t;if(!(i<u)){if((e=a.apply(n,r))===o.promise())throw new TypeError("Thenable self-resolution");t=e&&("object"==typeof e||"function"==typeof e)&&e.then,m(t)?s?t.call(e,l(u,o,R,s),l(u,o,M,s)):(u++,t.call(e,l(u,o,R,s),l(u,o,M,s),l(u,o,R,o.notifyWith))):(a!==R&&(n=void 0,r=[e]),(s||o.resolveWith)(n,r))}},t=s?e:function(){try{e()}catch(e){S.Deferred.exceptionHook&&S.Deferred.exceptionHook(e,t.stackTrace),u<=i+1&&(a!==M&&(n=void 0,r=[e]),o.rejectWith(n,r))}};i?t():(S.Deferred.getStackHook&&(t.stackTrace=S.Deferred.getStackHook()),C.setTimeout(t))}}return S.Deferred(function(e){o[0][3].add(l(0,e,m(r)?r:R,e.notifyWith)),o[1][3].add(l(0,e,m(t)?t:R)),o[2][3].add(l(0,e,m(n)?n:M))}).promise()},promise:function(e){return null!=e?S.extend(e,a):a}},s={};return S.each(o,function(e,t){var n=t[2],r=t[5];a[t[1]]=n.add,r&&n.add(function(){i=r},o[3-e][2].disable,o[3-e][3].disable,o[0][2].lock,o[0][3].lock),n.add(t[3].fire),s[t[0]]=function(){return s[t[0]+"With"](this===s?void 0:this,arguments),this},s[t[0]+"With"]=n.fireWith}),a.promise(s),e&&e.call(s,s),s},when:function(e){var n=arguments.length,t=n,r=Array(t),i=s.call(arguments),o=S.Deferred(),a=function(t){return function(e){r[t]=this,i[t]=1<arguments.length?s.call(arguments):e,--n||o.resolveWith(r,i)}};if(n<=1&&(I(e,o.done(a(t)).resolve,o.reject,!n),"pending"===o.state()||m(i[t]&&i[t].then)))return o.then();while(t--)I(i[t],a(t),o.reject);return o.promise()}});var W=/^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;S.Deferred.exceptionHook=function(e,t){C.console&&C.console.warn&&e&&W.test(e.name)&&C.console.warn("jQuery.Deferred exception: "+e.message,e.stack,t)},S.readyException=function(e){C.setTimeout(function(){throw e})};var F=S.Deferred();function B(){E.removeEventListener("DOMContentLoaded",B),C.removeEventListener("load",B),S.ready()}S.fn.ready=function(e){return F.then(e)["catch"](function(e){S.readyException(e)}),this},S.extend({isReady:!1,readyWait:1,ready:function(e){(!0===e?--S.readyWait:S.isReady)||(S.isReady=!0)!==e&&0<--S.readyWait||F.resolveWith(E,[S])}}),S.ready.then=F.then,"complete"===E.readyState||"loading"!==E.readyState&&!E.documentElement.doScroll?C.setTimeout(S.ready):(E.addEventListener("DOMContentLoaded",B),C.addEventListener("load",B));var $=function(e,t,n,r,i,o,a){var s=0,u=e.length,l=null==n;if("object"===w(n))for(s in i=!0,n)$(e,t,s,n[s],!0,o,a);else if(void 0!==r&&(i=!0,m(r)||(a=!0),l&&(a?(t.call(e,r),t=null):(l=t,t=function(e,t,n){return l.call(S(e),n)})),t))for(;s<u;s++)t(e[s],n,a?r:r.call(e[s],s,t(e[s],n)));return i?e:l?t.call(e):u?t(e[0],n):o},_=/^-ms-/,z=/-([a-z])/g;function U(e,t){return t.toUpperCase()}function X(e){return e.replace(_,"ms-").replace(z,U)}var V=function(e){return 1===e.nodeType||9===e.nodeType||!+e.nodeType};function G(){this.expando=S.expando+G.uid++}G.uid=1,G.prototype={cache:function(e){var t=e[this.expando];return t||(t={},V(e)&&(e.nodeType?e[this.expando]=t:Object.defineProperty(e,this.expando,{value:t,configurable:!0}))),t},set:function(e,t,n){var r,i=this.cache(e);if("string"==typeof t)i[X(t)]=n;else for(r in t)i[X(r)]=t[r];return i},get:function(e,t){return void 0===t?this.cache(e):e[this.expando]&&e[this.expando][X(t)]},access:function(e,t,n){return void 0===t||t&&"string"==typeof t&&void 0===n?this.get(e,t):(this.set(e,t,n),void 0!==n?n:t)},remove:function(e,t){var n,r=e[this.expando];if(void 0!==r){if(void 0!==t){n=(t=Array.isArray(t)?t.map(X):(t=X(t))in r?[t]:t.match(P)||[]).length;while(n--)delete r[t[n]]}(void 0===t||S.isEmptyObject(r))&&(e.nodeType?e[this.expando]=void 0:delete e[this.expando])}},hasData:function(e){var t=e[this.expando];return void 0!==t&&!S.isEmptyObject(t)}};var Y=new G,Q=new G,J=/^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,K=/[A-Z]/g;function Z(e,t,n){var r,i;if(void 0===n&&1===e.nodeType)if(r="data-"+t.replace(K,"-$&").toLowerCase(),"string"==typeof(n=e.getAttribute(r))){try{n="true"===(i=n)||"false"!==i&&("null"===i?null:i===+i+""?+i:J.test(i)?JSON.parse(i):i)}catch(e){}Q.set(e,t,n)}else n=void 0;return n}S.extend({hasData:function(e){return Q.hasData(e)||Y.hasData(e)},data:function(e,t,n){return Q.access(e,t,n)},removeData:function(e,t){Q.remove(e,t)},_data:function(e,t,n){return Y.access(e,t,n)},_removeData:function(e,t){Y.remove(e,t)}}),S.fn.extend({data:function(n,e){var t,r,i,o=this[0],a=o&&o.attributes;if(void 0===n){if(this.length&&(i=Q.get(o),1===o.nodeType&&!Y.get(o,"hasDataAttrs"))){t=a.length;while(t--)a[t]&&0===(r=a[t].name).indexOf("data-")&&(r=X(r.slice(5)),Z(o,r,i[r]));Y.set(o,"hasDataAttrs",!0)}return i}return"object"==typeof n?this.each(function(){Q.set(this,n)}):$(this,function(e){var t;if(o&&void 0===e)return void 0!==(t=Q.get(o,n))?t:void 0!==(t=Z(o,n))?t:void 0;this.each(function(){Q.set(this,n,e)})},null,e,1<arguments.length,null,!0)},removeData:function(e){return this.each(function(){Q.remove(this,e)})}}),S.extend({queue:function(e,t,n){var r;if(e)return t=(t||"fx")+"queue",r=Y.get(e,t),n&&(!r||Array.isArray(n)?r=Y.access(e,t,S.makeArray(n)):r.push(n)),r||[]},dequeue:function(e,t){t=t||"fx";var n=S.queue(e,t),r=n.length,i=n.shift(),o=S._queueHooks(e,t);"inprogress"===i&&(i=n.shift(),r--),i&&("fx"===t&&n.unshift("inprogress"),delete o.stop,i.call(e,function(){S.dequeue(e,t)},o)),!r&&o&&o.empty.fire()},_queueHooks:function(e,t){var n=t+"queueHooks";return Y.get(e,n)||Y.access(e,n,{empty:S.Callbacks("once memory").add(function(){Y.remove(e,[t+"queue",n])})})}}),S.fn.extend({queue:function(t,n){var e=2;return"string"!=typeof t&&(n=t,t="fx",e--),arguments.length<e?S.queue(this[0],t):void 0===n?this:this.each(function(){var e=S.queue(this,t,n);S._queueHooks(this,t),"fx"===t&&"inprogress"!==e[0]&&S.dequeue(this,t)})},dequeue:function(e){return this.each(function(){S.dequeue(this,e)})},clearQueue:function(e){return this.queue(e||"fx",[])},promise:function(e,t){var n,r=1,i=S.Deferred(),o=this,a=this.length,s=function(){--r||i.resolveWith(o,[o])};"string"!=typeof e&&(t=e,e=void 0),e=e||"fx";while(a--)(n=Y.get(o[a],e+"queueHooks"))&&n.empty&&(r++,n.empty.add(s));return s(),i.promise(t)}});var ee=/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/.source,te=new RegExp("^(?:([+-])=|)("+ee+")([a-z%]*)$","i"),ne=["Top","Right","Bottom","Left"],re=E.documentElement,ie=function(e){return S.contains(e.ownerDocument,e)},oe={composed:!0};re.getRootNode&&(ie=function(e){return S.contains(e.ownerDocument,e)||e.getRootNode(oe)===e.ownerDocument});var ae=function(e,t){return"none"===(e=t||e).style.display||""===e.style.display&&ie(e)&&"none"===S.css(e,"display")};function se(e,t,n,r){var i,o,a=20,s=r?function(){return r.cur()}:function(){return S.css(e,t,"")},u=s(),l=n&&n[3]||(S.cssNumber[t]?"":"px"),c=e.nodeType&&(S.cssNumber[t]||"px"!==l&&+u)&&te.exec(S.css(e,t));if(c&&c[3]!==l){u/=2,l=l||c[3],c=+u||1;while(a--)S.style(e,t,c+l),(1-o)*(1-(o=s()/u||.5))<=0&&(a=0),c/=o;c*=2,S.style(e,t,c+l),n=n||[]}return n&&(c=+c||+u||0,i=n[1]?c+(n[1]+1)*n[2]:+n[2],r&&(r.unit=l,r.start=c,r.end=i)),i}var ue={};function le(e,t){for(var n,r,i,o,a,s,u,l=[],c=0,f=e.length;c<f;c++)(r=e[c]).style&&(n=r.style.display,t?("none"===n&&(l[c]=Y.get(r,"display")||null,l[c]||(r.style.display="")),""===r.style.display&&ae(r)&&(l[c]=(u=a=o=void 0,a=(i=r).ownerDocument,s=i.nodeName,(u=ue[s])||(o=a.body.appendChild(a.createElement(s)),u=S.css(o,"display"),o.parentNode.removeChild(o),"none"===u&&(u="block"),ue[s]=u)))):"none"!==n&&(l[c]="none",Y.set(r,"display",n)));for(c=0;c<f;c++)null!=l[c]&&(e[c].style.display=l[c]);return e}S.fn.extend({show:function(){return le(this,!0)},hide:function(){return le(this)},toggle:function(e){return"boolean"==typeof e?e?this.show():this.hide():this.each(function(){ae(this)?S(this).show():S(this).hide()})}});var ce,fe,pe=/^(?:checkbox|radio)$/i,de=/<([a-z][^\/\0>\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="<textarea>x</textarea>",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="<option></option>",y.option=!!ce.lastChild;var ge={thead:[1,"<table>","</table>"],col:[2,"<table><colgroup>","</colgroup></table>"],tr:[2,"<table><tbody>","</tbody></table>"],td:[3,"<table><tbody><tr>","</tr></tbody></table>"],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n<r;n++)Y.set(e[n],"globalEval",!t||Y.get(t[n],"globalEval"))}ge.tbody=ge.tfoot=ge.colgroup=ge.caption=ge.thead,ge.th=ge.td,y.option||(ge.optgroup=ge.option=[1,"<select multiple='multiple'>","</select>"]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d<h;d++)if((o=e[d])||0===o)if("object"===w(o))S.merge(p,o.nodeType?[o]:o);else if(me.test(o)){a=a||f.appendChild(t.createElement("div")),s=(de.exec(o)||["",""])[1].toLowerCase(),u=ge[s]||ge._default,a.innerHTML=u[1]+S.htmlPrefilter(o)+u[2],c=u[0];while(c--)a=a.lastChild;S.merge(p,a.childNodes),(a=f.firstChild).textContent=""}else p.push(t.createTextNode(o));f.textContent="",d=0;while(o=p[d++])if(r&&-1<S.inArray(o,r))i&&i.push(o);else if(l=ie(o),a=ve(f.appendChild(o),"script"),l&&ye(a),n){c=0;while(o=a[c++])he.test(o.type||"")&&n.push(o)}return f}var be=/^key/,we=/^(?:mouse|pointer|contextmenu|drag|drop)|click/,Te=/^([^.]*)(?:\.(.+)|)/;function Ce(){return!0}function Ee(){return!1}function Se(e,t){return e===function(){try{return E.activeElement}catch(e){}}()==("focus"===t)}function ke(e,t,n,r,i,o){var a,s;if("object"==typeof t){for(s in"string"!=typeof n&&(r=r||n,n=void 0),t)ke(e,s,n,r,t[s],o);return e}if(null==r&&null==i?(i=n,r=n=void 0):null==i&&("string"==typeof n?(i=r,r=void 0):(i=r,r=n,n=void 0)),!1===i)i=Ee;else if(!i)return e;return 1===o&&(a=i,(i=function(e){return S().off(e),a.apply(this,arguments)}).guid=a.guid||(a.guid=S.guid++)),e.each(function(){S.event.add(this,t,i,r,n)})}function Ae(e,i,o){o?(Y.set(e,i,!1),S.event.add(e,i,{namespace:!1,handler:function(e){var t,n,r=Y.get(this,i);if(1&e.isTrigger&&this[i]){if(r.length)(S.event.special[i]||{}).delegateType&&e.stopPropagation();else if(r=s.call(arguments),Y.set(this,i,r),t=o(this,i),this[i](),r!==(n=Y.get(this,i))||t?Y.set(this,i,!1):n={},r!==n)return e.stopImmediatePropagation(),e.preventDefault(),n.value}else r.length&&(Y.set(this,i,{value:S.event.trigger(S.extend(r[0],S.Event.prototype),r.slice(1),this)}),e.stopImmediatePropagation())}})):void 0===Y.get(e,i)&&S.event.add(e,i,Ce)}S.event={global:{},add:function(t,e,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.get(t);if(V(t)){n.handler&&(n=(o=n).handler,i=o.selector),i&&S.find.matchesSelector(re,i),n.guid||(n.guid=S.guid++),(u=v.events)||(u=v.events=Object.create(null)),(a=v.handle)||(a=v.handle=function(e){return"undefined"!=typeof S&&S.event.triggered!==e.type?S.event.dispatch.apply(t,arguments):void 0}),l=(e=(e||"").match(P)||[""]).length;while(l--)d=g=(s=Te.exec(e[l])||[])[1],h=(s[2]||"").split(".").sort(),d&&(f=S.event.special[d]||{},d=(i?f.delegateType:f.bindType)||d,f=S.event.special[d]||{},c=S.extend({type:d,origType:g,data:r,handler:n,guid:n.guid,selector:i,needsContext:i&&S.expr.match.needsContext.test(i),namespace:h.join(".")},o),(p=u[d])||((p=u[d]=[]).delegateCount=0,f.setup&&!1!==f.setup.call(t,r,h,a)||t.addEventListener&&t.addEventListener(d,a)),f.add&&(f.add.call(t,c),c.handler.guid||(c.handler.guid=n.guid)),i?p.splice(p.delegateCount++,0,c):p.push(c),S.event.global[d]=!0)}},remove:function(e,t,n,r,i){var o,a,s,u,l,c,f,p,d,h,g,v=Y.hasData(e)&&Y.get(e);if(v&&(u=v.events)){l=(t=(t||"").match(P)||[""]).length;while(l--)if(d=g=(s=Te.exec(t[l])||[])[1],h=(s[2]||"").split(".").sort(),d){f=S.event.special[d]||{},p=u[d=(r?f.delegateType:f.bindType)||d]||[],s=s[2]&&new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"),a=o=p.length;while(o--)c=p[o],!i&&g!==c.origType||n&&n.guid!==c.guid||s&&!s.test(c.namespace)||r&&r!==c.selector&&("**"!==r||!c.selector)||(p.splice(o,1),c.selector&&p.delegateCount--,f.remove&&f.remove.call(e,c));a&&!p.length&&(f.teardown&&!1!==f.teardown.call(e,h,v.handle)||S.removeEvent(e,d,v.handle),delete u[d])}else for(d in u)S.event.remove(e,d+t[l],n,r,!0);S.isEmptyObject(u)&&Y.remove(e,"handle events")}},dispatch:function(e){var t,n,r,i,o,a,s=new Array(arguments.length),u=S.event.fix(e),l=(Y.get(this,"events")||Object.create(null))[u.type]||[],c=S.event.special[u.type]||{};for(s[0]=u,t=1;t<arguments.length;t++)s[t]=arguments[t];if(u.delegateTarget=this,!c.preDispatch||!1!==c.preDispatch.call(this,u)){a=S.event.handlers.call(this,u,l),t=0;while((i=a[t++])&&!u.isPropagationStopped()){u.currentTarget=i.elem,n=0;while((o=i.handlers[n++])&&!u.isImmediatePropagationStopped())u.rnamespace&&!1!==o.namespace&&!u.rnamespace.test(o.namespace)||(u.handleObj=o,u.data=o.data,void 0!==(r=((S.event.special[o.origType]||{}).handle||o.handler).apply(i.elem,s))&&!1===(u.result=r)&&(u.preventDefault(),u.stopPropagation()))}return c.postDispatch&&c.postDispatch.call(this,u),u.result}},handlers:function(e,t){var n,r,i,o,a,s=[],u=t.delegateCount,l=e.target;if(u&&l.nodeType&&!("click"===e.type&&1<=e.button))for(;l!==this;l=l.parentNode||this)if(1===l.nodeType&&("click"!==e.type||!0!==l.disabled)){for(o=[],a={},n=0;n<u;n++)void 0===a[i=(r=t[n]).selector+" "]&&(a[i]=r.needsContext?-1<S(i,this).index(l):S.find(i,this,null,[l]).length),a[i]&&o.push(r);o.length&&s.push({elem:l,handlers:o})}return l=this,u<t.length&&s.push({elem:l,handlers:t.slice(u)}),s},addProp:function(t,e){Object.defineProperty(S.Event.prototype,t,{enumerable:!0,configurable:!0,get:m(e)?function(){if(this.originalEvent)return e(this.originalEvent)}:function(){if(this.originalEvent)return this.originalEvent[t]},set:function(e){Object.defineProperty(this,t,{enumerable:!0,configurable:!0,writable:!0,value:e})}})},fix:function(e){return e[S.expando]?e:new S.Event(e)},special:{load:{noBubble:!0},click:{setup:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Ae(t,"click",Ce),!1},trigger:function(e){var t=this||e;return pe.test(t.type)&&t.click&&A(t,"input")&&Ae(t,"click"),!0},_default:function(e){var t=e.target;return pe.test(t.type)&&t.click&&A(t,"input")&&Y.get(t,"click")||A(t,"a")}},beforeunload:{postDispatch:function(e){void 0!==e.result&&e.originalEvent&&(e.originalEvent.returnValue=e.result)}}}},S.removeEvent=function(e,t,n){e.removeEventListener&&e.removeEventListener(t,n)},S.Event=function(e,t){if(!(this instanceof S.Event))return new S.Event(e,t);e&&e.type?(this.originalEvent=e,this.type=e.type,this.isDefaultPrevented=e.defaultPrevented||void 0===e.defaultPrevented&&!1===e.returnValue?Ce:Ee,this.target=e.target&&3===e.target.nodeType?e.target.parentNode:e.target,this.currentTarget=e.currentTarget,this.relatedTarget=e.relatedTarget):this.type=e,t&&S.extend(this,t),this.timeStamp=e&&e.timeStamp||Date.now(),this[S.expando]=!0},S.Event.prototype={constructor:S.Event,isDefaultPrevented:Ee,isPropagationStopped:Ee,isImmediatePropagationStopped:Ee,isSimulated:!1,preventDefault:function(){var e=this.originalEvent;this.isDefaultPrevented=Ce,e&&!this.isSimulated&&e.preventDefault()},stopPropagation:function(){var e=this.originalEvent;this.isPropagationStopped=Ce,e&&!this.isSimulated&&e.stopPropagation()},stopImmediatePropagation:function(){var e=this.originalEvent;this.isImmediatePropagationStopped=Ce,e&&!this.isSimulated&&e.stopImmediatePropagation(),this.stopPropagation()}},S.each({altKey:!0,bubbles:!0,cancelable:!0,changedTouches:!0,ctrlKey:!0,detail:!0,eventPhase:!0,metaKey:!0,pageX:!0,pageY:!0,shiftKey:!0,view:!0,"char":!0,code:!0,charCode:!0,key:!0,keyCode:!0,button:!0,buttons:!0,clientX:!0,clientY:!0,offsetX:!0,offsetY:!0,pointerId:!0,pointerType:!0,screenX:!0,screenY:!0,targetTouches:!0,toElement:!0,touches:!0,which:function(e){var t=e.button;return null==e.which&&be.test(e.type)?null!=e.charCode?e.charCode:e.keyCode:!e.which&&void 0!==t&&we.test(e.type)?1&t?1:2&t?3:4&t?2:0:e.which}},S.event.addProp),S.each({focus:"focusin",blur:"focusout"},function(e,t){S.event.special[e]={setup:function(){return Ae(this,e,Se),!1},trigger:function(){return Ae(this,e),!0},delegateType:t}}),S.each({mouseenter:"mouseover",mouseleave:"mouseout",pointerenter:"pointerover",pointerleave:"pointerout"},function(e,i){S.event.special[e]={delegateType:i,bindType:i,handle:function(e){var t,n=e.relatedTarget,r=e.handleObj;return n&&(n===this||S.contains(this,n))||(e.type=r.origType,t=r.handler.apply(this,arguments),e.type=i),t}}}),S.fn.extend({on:function(e,t,n,r){return ke(this,e,t,n,r)},one:function(e,t,n,r){return ke(this,e,t,n,r,1)},off:function(e,t,n){var r,i;if(e&&e.preventDefault&&e.handleObj)return r=e.handleObj,S(e.delegateTarget).off(r.namespace?r.origType+"."+r.namespace:r.origType,r.selector,r.handler),this;if("object"==typeof e){for(i in e)this.off(i,t,e[i]);return this}return!1!==t&&"function"!=typeof t||(n=t,t=void 0),!1===n&&(n=Ee),this.each(function(){S.event.remove(this,e,n,t)})}});var Ne=/<script|<style|<link/i,De=/checked\s*(?:[^=]|=\s*.checked.)/i,je=/^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n<r;n++)S.event.add(t,i,s[i][n]);Q.hasData(e)&&(o=Q.access(e),a=S.extend({},o),Q.set(t,a))}}function Pe(n,r,i,o){r=g(r);var e,t,a,s,u,l,c=0,f=n.length,p=f-1,d=r[0],h=m(d);if(h||1<f&&"string"==typeof d&&!y.checkClone&&De.test(d))return n.each(function(e){var t=n.eq(e);h&&(r[0]=d.call(this,e,t.html())),Pe(t,r,i,o)});if(f&&(t=(e=xe(r,n[0].ownerDocument,!1,n,o)).firstChild,1===e.childNodes.length&&(e=t),t||o)){for(s=(a=S.map(ve(e,"script"),Le)).length;c<f;c++)u=e,c!==p&&(u=S.clone(u,!0,!0),s&&S.merge(a,ve(u,"script"))),i.call(n[c],u,c);if(s)for(l=a[a.length-1].ownerDocument,S.map(a,He),c=0;c<s;c++)u=a[c],he.test(u.type||"")&&!Y.access(u,"globalEval")&&S.contains(l,u)&&(u.src&&"module"!==(u.type||"").toLowerCase()?S._evalUrl&&!u.noModule&&S._evalUrl(u.src,{nonce:u.nonce||u.getAttribute("nonce")},l):b(u.textContent.replace(je,""),u,l))}return n}function Re(e,t,n){for(var r,i=t?S.filter(t,e):e,o=0;null!=(r=i[o]);o++)n||1!==r.nodeType||S.cleanData(ve(r)),r.parentNode&&(n&&ie(r)&&ye(ve(r,"script")),r.parentNode.removeChild(r));return e}S.extend({htmlPrefilter:function(e){return e},clone:function(e,t,n){var r,i,o,a,s,u,l,c=e.cloneNode(!0),f=ie(e);if(!(y.noCloneChecked||1!==e.nodeType&&11!==e.nodeType||S.isXMLDoc(e)))for(a=ve(c),r=0,i=(o=ve(e)).length;r<i;r++)s=o[r],u=a[r],void 0,"input"===(l=u.nodeName.toLowerCase())&&pe.test(s.type)?u.checked=s.checked:"input"!==l&&"textarea"!==l||(u.defaultValue=s.defaultValue);if(t)if(n)for(o=o||ve(e),a=a||ve(c),r=0,i=o.length;r<i;r++)Oe(o[r],a[r]);else Oe(e,c);return 0<(a=ve(c,"script")).length&&ye(a,!f&&ve(e,"script")),c},cleanData:function(e){for(var t,n,r,i=S.event.special,o=0;void 0!==(n=e[o]);o++)if(V(n)){if(t=n[Y.expando]){if(t.events)for(r in t.events)i[r]?S.event.remove(n,r):S.removeEvent(n,r,t.handle);n[Y.expando]=void 0}n[Q.expando]&&(n[Q.expando]=void 0)}}}),S.fn.extend({detach:function(e){return Re(this,e,!0)},remove:function(e){return Re(this,e)},text:function(e){return $(this,function(e){return void 0===e?S.text(this):this.empty().each(function(){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||(this.textContent=e)})},null,e,arguments.length)},append:function(){return Pe(this,arguments,function(e){1!==this.nodeType&&11!==this.nodeType&&9!==this.nodeType||qe(this,e).appendChild(e)})},prepend:function(){return Pe(this,arguments,function(e){if(1===this.nodeType||11===this.nodeType||9===this.nodeType){var t=qe(this,e);t.insertBefore(e,t.firstChild)}})},before:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this)})},after:function(){return Pe(this,arguments,function(e){this.parentNode&&this.parentNode.insertBefore(e,this.nextSibling)})},empty:function(){for(var e,t=0;null!=(e=this[t]);t++)1===e.nodeType&&(S.cleanData(ve(e,!1)),e.textContent="");return this},clone:function(e,t){return e=null!=e&&e,t=null==t?e:t,this.map(function(){return S.clone(this,e,t)})},html:function(e){return $(this,function(e){var t=this[0]||{},n=0,r=this.length;if(void 0===e&&1===t.nodeType)return t.innerHTML;if("string"==typeof e&&!Ne.test(e)&&!ge[(de.exec(e)||["",""])[1].toLowerCase()]){e=S.htmlPrefilter(e);try{for(;n<r;n++)1===(t=this[n]||{}).nodeType&&(S.cleanData(ve(t,!1)),t.innerHTML=e);t=0}catch(e){}}t&&this.empty().append(e)},null,e,arguments.length)},replaceWith:function(){var n=[];return Pe(this,arguments,function(e){var t=this.parentNode;S.inArray(this,n)<0&&(S.cleanData(ve(this)),t&&t.replaceChild(e,this))},n)}}),S.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(e,a){S.fn[e]=function(e){for(var t,n=[],r=S(e),i=r.length-1,o=0;o<=i;o++)t=o===i?this:this.clone(!0),S(r[o])[a](t),u.apply(n,t.get());return this.pushStack(n)}});var Me=new RegExp("^("+ee+")(?!px)[a-z%]+$","i"),Ie=function(e){var t=e.ownerDocument.defaultView;return t&&t.opener||(t=C),t.getComputedStyle(e)},We=function(e,t,n){var r,i,o={};for(i in t)o[i]=e.style[i],e.style[i]=t[i];for(i in r=n.call(e),t)e.style[i]=o[i];return r},Fe=new RegExp(ne.join("|"),"i");function Be(e,t,n){var r,i,o,a,s=e.style;return(n=n||Ie(e))&&(""!==(a=n.getPropertyValue(t)||n[t])||ie(e)||(a=S.style(e,t)),!y.pixelBoxStyles()&&Me.test(a)&&Fe.test(t)&&(r=s.width,i=s.minWidth,o=s.maxWidth,s.minWidth=s.maxWidth=s.width=a,a=n.width,s.width=r,s.minWidth=i,s.maxWidth=o)),void 0!==a?a+"":a}function $e(e,t){return{get:function(){if(!e())return(this.get=t).apply(this,arguments);delete this.get}}}!function(){function e(){if(l){u.style.cssText="position:absolute;left:-11111px;width:60px;margin-top:1px;padding:0;border:0",l.style.cssText="position:relative;display:block;box-sizing:border-box;overflow:scroll;margin:auto;border:1px;padding:1px;width:60%;top:1%",re.appendChild(u).appendChild(l);var e=C.getComputedStyle(l);n="1%"!==e.top,s=12===t(e.marginLeft),l.style.right="60%",o=36===t(e.right),r=36===t(e.width),l.style.position="absolute",i=12===t(l.offsetWidth/3),re.removeChild(u),l=null}}function t(e){return Math.round(parseFloat(e))}var n,r,i,o,a,s,u=E.createElement("div"),l=E.createElement("div");l.style&&(l.style.backgroundClip="content-box",l.cloneNode(!0).style.backgroundClip="",y.clearCloneStyle="content-box"===l.style.backgroundClip,S.extend(y,{boxSizingReliable:function(){return e(),r},pixelBoxStyles:function(){return e(),o},pixelPosition:function(){return e(),n},reliableMarginLeft:function(){return e(),s},scrollboxSize:function(){return e(),i},reliableTrDimensions:function(){var e,t,n,r;return null==a&&(e=E.createElement("table"),t=E.createElement("tr"),n=E.createElement("div"),e.style.cssText="position:absolute;left:-11111px",t.style.height="1px",n.style.height="9px",re.appendChild(e).appendChild(t).appendChild(n),r=C.getComputedStyle(t),a=3<parseInt(r.height),re.removeChild(e)),a}}))}();var _e=["Webkit","Moz","ms"],ze=E.createElement("div").style,Ue={};function Xe(e){var t=S.cssProps[e]||Ue[e];return t||(e in ze?e:Ue[e]=function(e){var t=e[0].toUpperCase()+e.slice(1),n=_e.length;while(n--)if((e=_e[n]+t)in ze)return e}(e)||e)}var Ve=/^(none|table(?!-c[ea]).+)/,Ge=/^--/,Ye={position:"absolute",visibility:"hidden",display:"block"},Qe={letterSpacing:"0",fontWeight:"400"};function Je(e,t,n){var r=te.exec(t);return r?Math.max(0,r[2]-(n||0))+(r[3]||"px"):t}function Ke(e,t,n,r,i,o){var a="width"===t?1:0,s=0,u=0;if(n===(r?"border":"content"))return 0;for(;a<4;a+=2)"margin"===n&&(u+=S.css(e,n+ne[a],!0,i)),r?("content"===n&&(u-=S.css(e,"padding"+ne[a],!0,i)),"margin"!==n&&(u-=S.css(e,"border"+ne[a]+"Width",!0,i))):(u+=S.css(e,"padding"+ne[a],!0,i),"padding"!==n?u+=S.css(e,"border"+ne[a]+"Width",!0,i):s+=S.css(e,"border"+ne[a]+"Width",!0,i));return!r&&0<=o&&(u+=Math.max(0,Math.ceil(e["offset"+t[0].toUpperCase()+t.slice(1)]-o-u-s-.5))||0),u}function Ze(e,t,n){var r=Ie(e),i=(!y.boxSizingReliable()||n)&&"border-box"===S.css(e,"boxSizing",!1,r),o=i,a=Be(e,t,r),s="offset"+t[0].toUpperCase()+t.slice(1);if(Me.test(a)){if(!n)return a;a="auto"}return(!y.boxSizingReliable()&&i||!y.reliableTrDimensions()&&A(e,"tr")||"auto"===a||!parseFloat(a)&&"inline"===S.css(e,"display",!1,r))&&e.getClientRects().length&&(i="border-box"===S.css(e,"boxSizing",!1,r),(o=s in e)&&(a=e[s])),(a=parseFloat(a)||0)+Ke(e,t,n||(i?"border":"content"),o,r,a)+"px"}function et(e,t,n,r,i){return new et.prototype.init(e,t,n,r,i)}S.extend({cssHooks:{opacity:{get:function(e,t){if(t){var n=Be(e,"opacity");return""===n?"1":n}}}},cssNumber:{animationIterationCount:!0,columnCount:!0,fillOpacity:!0,flexGrow:!0,flexShrink:!0,fontWeight:!0,gridArea:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnStart:!0,gridRow:!0,gridRowEnd:!0,gridRowStart:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0},cssProps:{},style:function(e,t,n,r){if(e&&3!==e.nodeType&&8!==e.nodeType&&e.style){var i,o,a,s=X(t),u=Ge.test(t),l=e.style;if(u||(t=Xe(s)),a=S.cssHooks[t]||S.cssHooks[s],void 0===n)return a&&"get"in a&&void 0!==(i=a.get(e,!1,r))?i:l[t];"string"===(o=typeof n)&&(i=te.exec(n))&&i[1]&&(n=se(e,t,i),o="number"),null!=n&&n==n&&("number"!==o||u||(n+=i&&i[3]||(S.cssNumber[s]?"":"px")),y.clearCloneStyle||""!==n||0!==t.indexOf("background")||(l[t]="inherit"),a&&"set"in a&&void 0===(n=a.set(e,n,r))||(u?l.setProperty(t,n):l[t]=n))}},css:function(e,t,n,r){var i,o,a,s=X(t);return Ge.test(t)||(t=Xe(s)),(a=S.cssHooks[t]||S.cssHooks[s])&&"get"in a&&(i=a.get(e,!0,n)),void 0===i&&(i=Be(e,t,r)),"normal"===i&&t in Qe&&(i=Qe[t]),""===n||n?(o=parseFloat(i),!0===n||isFinite(o)?o||0:i):i}}),S.each(["height","width"],function(e,u){S.cssHooks[u]={get:function(e,t,n){if(t)return!Ve.test(S.css(e,"display"))||e.getClientRects().length&&e.getBoundingClientRect().width?Ze(e,u,n):We(e,Ye,function(){return Ze(e,u,n)})},set:function(e,t,n){var r,i=Ie(e),o=!y.scrollboxSize()&&"absolute"===i.position,a=(o||n)&&"border-box"===S.css(e,"boxSizing",!1,i),s=n?Ke(e,u,n,a,i):0;return a&&o&&(s-=Math.ceil(e["offset"+u[0].toUpperCase()+u.slice(1)]-parseFloat(i[u])-Ke(e,u,"border",!1,i)-.5)),s&&(r=te.exec(t))&&"px"!==(r[3]||"px")&&(e.style[u]=t,t=S.css(e,u)),Je(0,t,s)}}}),S.cssHooks.marginLeft=$e(y.reliableMarginLeft,function(e,t){if(t)return(parseFloat(Be(e,"marginLeft"))||e.getBoundingClientRect().left-We(e,{marginLeft:0},function(){return e.getBoundingClientRect().left}))+"px"}),S.each({margin:"",padding:"",border:"Width"},function(i,o){S.cssHooks[i+o]={expand:function(e){for(var t=0,n={},r="string"==typeof e?e.split(" "):[e];t<4;t++)n[i+ne[t]+o]=r[t]||r[t-2]||r[0];return n}},"margin"!==i&&(S.cssHooks[i+o].set=Je)}),S.fn.extend({css:function(e,t){return $(this,function(e,t,n){var r,i,o={},a=0;if(Array.isArray(t)){for(r=Ie(e),i=t.length;a<i;a++)o[t[a]]=S.css(e,t[a],!1,r);return o}return void 0!==n?S.style(e,t,n):S.css(e,t)},e,t,1<arguments.length)}}),((S.Tween=et).prototype={constructor:et,init:function(e,t,n,r,i,o){this.elem=e,this.prop=n,this.easing=i||S.easing._default,this.options=t,this.start=this.now=this.cur(),this.end=r,this.unit=o||(S.cssNumber[n]?"":"px")},cur:function(){var e=et.propHooks[this.prop];return e&&e.get?e.get(this):et.propHooks._default.get(this)},run:function(e){var t,n=et.propHooks[this.prop];return this.options.duration?this.pos=t=S.easing[this.easing](e,this.options.duration*e,0,1,this.options.duration):this.pos=t=e,this.now=(this.end-this.start)*t+this.start,this.options.step&&this.options.step.call(this.elem,this.now,this),n&&n.set?n.set(this):et.propHooks._default.set(this),this}}).init.prototype=et.prototype,(et.propHooks={_default:{get:function(e){var t;return 1!==e.elem.nodeType||null!=e.elem[e.prop]&&null==e.elem.style[e.prop]?e.elem[e.prop]:(t=S.css(e.elem,e.prop,""))&&"auto"!==t?t:0},set:function(e){S.fx.step[e.prop]?S.fx.step[e.prop](e):1!==e.elem.nodeType||!S.cssHooks[e.prop]&&null==e.elem.style[Xe(e.prop)]?e.elem[e.prop]=e.now:S.style(e.elem,e.prop,e.now+e.unit)}}}).scrollTop=et.propHooks.scrollLeft={set:function(e){e.elem.nodeType&&e.elem.parentNode&&(e.elem[e.prop]=e.now)}},S.easing={linear:function(e){return e},swing:function(e){return.5-Math.cos(e*Math.PI)/2},_default:"swing"},S.fx=et.prototype.init,S.fx.step={};var tt,nt,rt,it,ot=/^(?:toggle|show|hide)$/,at=/queueHooks$/;function st(){nt&&(!1===E.hidden&&C.requestAnimationFrame?C.requestAnimationFrame(st):C.setTimeout(st,S.fx.interval),S.fx.tick())}function ut(){return C.setTimeout(function(){tt=void 0}),tt=Date.now()}function lt(e,t){var n,r=0,i={height:e};for(t=t?1:0;r<4;r+=2-t)i["margin"+(n=ne[r])]=i["padding"+n]=e;return t&&(i.opacity=i.width=e),i}function ct(e,t,n){for(var r,i=(ft.tweeners[t]||[]).concat(ft.tweeners["*"]),o=0,a=i.length;o<a;o++)if(r=i[o].call(n,t,e))return r}function ft(o,e,t){var n,a,r=0,i=ft.prefilters.length,s=S.Deferred().always(function(){delete u.elem}),u=function(){if(a)return!1;for(var e=tt||ut(),t=Math.max(0,l.startTime+l.duration-e),n=1-(t/l.duration||0),r=0,i=l.tweens.length;r<i;r++)l.tweens[r].run(n);return s.notifyWith(o,[l,n,t]),n<1&&i?t:(i||s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l]),!1)},l=s.promise({elem:o,props:S.extend({},e),opts:S.extend(!0,{specialEasing:{},easing:S.easing._default},t),originalProperties:e,originalOptions:t,startTime:tt||ut(),duration:t.duration,tweens:[],createTween:function(e,t){var n=S.Tween(o,l.opts,e,t,l.opts.specialEasing[e]||l.opts.easing);return l.tweens.push(n),n},stop:function(e){var t=0,n=e?l.tweens.length:0;if(a)return this;for(a=!0;t<n;t++)l.tweens[t].run(1);return e?(s.notifyWith(o,[l,1,0]),s.resolveWith(o,[l,e])):s.rejectWith(o,[l,e]),this}}),c=l.props;for(!function(e,t){var n,r,i,o,a;for(n in e)if(i=t[r=X(n)],o=e[n],Array.isArray(o)&&(i=o[1],o=e[n]=o[0]),n!==r&&(e[r]=o,delete e[n]),(a=S.cssHooks[r])&&"expand"in a)for(n in o=a.expand(o),delete e[r],o)n in e||(e[n]=o[n],t[n]=i);else t[r]=i}(c,l.opts.specialEasing);r<i;r++)if(n=ft.prefilters[r].call(l,o,c,l.opts))return m(n.stop)&&(S._queueHooks(l.elem,l.opts.queue).stop=n.stop.bind(n)),n;return S.map(c,ct,l),m(l.opts.start)&&l.opts.start.call(o,l),l.progress(l.opts.progress).done(l.opts.done,l.opts.complete).fail(l.opts.fail).always(l.opts.always),S.fx.timer(S.extend(u,{elem:o,anim:l,queue:l.opts.queue})),l}S.Animation=S.extend(ft,{tweeners:{"*":[function(e,t){var n=this.createTween(e,t);return se(n.elem,e,te.exec(t),n),n}]},tweener:function(e,t){m(e)?(t=e,e=["*"]):e=e.match(P);for(var n,r=0,i=e.length;r<i;r++)n=e[r],ft.tweeners[n]=ft.tweeners[n]||[],ft.tweeners[n].unshift(t)},prefilters:[function(e,t,n){var r,i,o,a,s,u,l,c,f="width"in t||"height"in t,p=this,d={},h=e.style,g=e.nodeType&&ae(e),v=Y.get(e,"fxshow");for(r in n.queue||(null==(a=S._queueHooks(e,"fx")).unqueued&&(a.unqueued=0,s=a.empty.fire,a.empty.fire=function(){a.unqueued||s()}),a.unqueued++,p.always(function(){p.always(function(){a.unqueued--,S.queue(e,"fx").length||a.empty.fire()})})),t)if(i=t[r],ot.test(i)){if(delete t[r],o=o||"toggle"===i,i===(g?"hide":"show")){if("show"!==i||!v||void 0===v[r])continue;g=!0}d[r]=v&&v[r]||S.style(e,r)}if((u=!S.isEmptyObject(t))||!S.isEmptyObject(d))for(r in f&&1===e.nodeType&&(n.overflow=[h.overflow,h.overflowX,h.overflowY],null==(l=v&&v.display)&&(l=Y.get(e,"display")),"none"===(c=S.css(e,"display"))&&(l?c=l:(le([e],!0),l=e.style.display||l,c=S.css(e,"display"),le([e]))),("inline"===c||"inline-block"===c&&null!=l)&&"none"===S.css(e,"float")&&(u||(p.done(function(){h.display=l}),null==l&&(c=h.display,l="none"===c?"":c)),h.display="inline-block")),n.overflow&&(h.overflow="hidden",p.always(function(){h.overflow=n.overflow[0],h.overflowX=n.overflow[1],h.overflowY=n.overflow[2]})),u=!1,d)u||(v?"hidden"in v&&(g=v.hidden):v=Y.access(e,"fxshow",{display:l}),o&&(v.hidden=!g),g&&le([e],!0),p.done(function(){for(r in g||le([e]),Y.remove(e,"fxshow"),d)S.style(e,r,d[r])})),u=ct(g?v[r]:0,r,p),r in v||(v[r]=u.start,g&&(u.end=u.start,u.start=0))}],prefilter:function(e,t){t?ft.prefilters.unshift(e):ft.prefilters.push(e)}}),S.speed=function(e,t,n){var r=e&&"object"==typeof e?S.extend({},e):{complete:n||!n&&t||m(e)&&e,duration:e,easing:n&&t||t&&!m(t)&&t};return S.fx.off?r.duration=0:"number"!=typeof r.duration&&(r.duration in S.fx.speeds?r.duration=S.fx.speeds[r.duration]:r.duration=S.fx.speeds._default),null!=r.queue&&!0!==r.queue||(r.queue="fx"),r.old=r.complete,r.complete=function(){m(r.old)&&r.old.call(this),r.queue&&S.dequeue(this,r.queue)},r},S.fn.extend({fadeTo:function(e,t,n,r){return this.filter(ae).css("opacity",0).show().end().animate({opacity:t},e,n,r)},animate:function(t,e,n,r){var i=S.isEmptyObject(t),o=S.speed(e,n,r),a=function(){var e=ft(this,S.extend({},t),o);(i||Y.get(this,"finish"))&&e.stop(!0)};return a.finish=a,i||!1===o.queue?this.each(a):this.queue(o.queue,a)},stop:function(i,e,o){var a=function(e){var t=e.stop;delete e.stop,t(o)};return"string"!=typeof i&&(o=e,e=i,i=void 0),e&&this.queue(i||"fx",[]),this.each(function(){var e=!0,t=null!=i&&i+"queueHooks",n=S.timers,r=Y.get(this);if(t)r[t]&&r[t].stop&&a(r[t]);else for(t in r)r[t]&&r[t].stop&&at.test(t)&&a(r[t]);for(t=n.length;t--;)n[t].elem!==this||null!=i&&n[t].queue!==i||(n[t].anim.stop(o),e=!1,n.splice(t,1));!e&&o||S.dequeue(this,i)})},finish:function(a){return!1!==a&&(a=a||"fx"),this.each(function(){var e,t=Y.get(this),n=t[a+"queue"],r=t[a+"queueHooks"],i=S.timers,o=n?n.length:0;for(t.finish=!0,S.queue(this,a,[]),r&&r.stop&&r.stop.call(this,!0),e=i.length;e--;)i[e].elem===this&&i[e].queue===a&&(i[e].anim.stop(!0),i.splice(e,1));for(e=0;e<o;e++)n[e]&&n[e].finish&&n[e].finish.call(this);delete t.finish})}}),S.each(["toggle","show","hide"],function(e,r){var i=S.fn[r];S.fn[r]=function(e,t,n){return null==e||"boolean"==typeof e?i.apply(this,arguments):this.animate(lt(r,!0),e,t,n)}}),S.each({slideDown:lt("show"),slideUp:lt("hide"),slideToggle:lt("toggle"),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"},fadeToggle:{opacity:"toggle"}},function(e,r){S.fn[e]=function(e,t,n){return this.animate(r,e,t,n)}}),S.timers=[],S.fx.tick=function(){var e,t=0,n=S.timers;for(tt=Date.now();t<n.length;t++)(e=n[t])()||n[t]!==e||n.splice(t--,1);n.length||S.fx.stop(),tt=void 0},S.fx.timer=function(e){S.timers.push(e),S.fx.start()},S.fx.interval=13,S.fx.start=function(){nt||(nt=!0,st())},S.fx.stop=function(){nt=null},S.fx.speeds={slow:600,fast:200,_default:400},S.fn.delay=function(r,e){return r=S.fx&&S.fx.speeds[r]||r,e=e||"fx",this.queue(e,function(e,t){var n=C.setTimeout(e,r);t.stop=function(){C.clearTimeout(n)}})},rt=E.createElement("input"),it=E.createElement("select").appendChild(E.createElement("option")),rt.type="checkbox",y.checkOn=""!==rt.value,y.optSelected=it.selected,(rt=E.createElement("input")).value="t",rt.type="radio",y.radioValue="t"===rt.value;var pt,dt=S.expr.attrHandle;S.fn.extend({attr:function(e,t){return $(this,S.attr,e,t,1<arguments.length)},removeAttr:function(e){return this.each(function(){S.removeAttr(this,e)})}}),S.extend({attr:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return"undefined"==typeof e.getAttribute?S.prop(e,t,n):(1===o&&S.isXMLDoc(e)||(i=S.attrHooks[t.toLowerCase()]||(S.expr.match.bool.test(t)?pt:void 0)),void 0!==n?null===n?void S.removeAttr(e,t):i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:(e.setAttribute(t,n+""),n):i&&"get"in i&&null!==(r=i.get(e,t))?r:null==(r=S.find.attr(e,t))?void 0:r)},attrHooks:{type:{set:function(e,t){if(!y.radioValue&&"radio"===t&&A(e,"input")){var n=e.value;return e.setAttribute("type",t),n&&(e.value=n),t}}}},removeAttr:function(e,t){var n,r=0,i=t&&t.match(P);if(i&&1===e.nodeType)while(n=i[r++])e.removeAttribute(n)}}),pt={set:function(e,t,n){return!1===t?S.removeAttr(e,n):e.setAttribute(n,n),n}},S.each(S.expr.match.bool.source.match(/\w+/g),function(e,t){var a=dt[t]||S.find.attr;dt[t]=function(e,t,n){var r,i,o=t.toLowerCase();return n||(i=dt[o],dt[o]=r,r=null!=a(e,t,n)?o:null,dt[o]=i),r}});var ht=/^(?:input|select|textarea|button)$/i,gt=/^(?:a|area)$/i;function vt(e){return(e.match(P)||[]).join(" ")}function yt(e){return e.getAttribute&&e.getAttribute("class")||""}function mt(e){return Array.isArray(e)?e:"string"==typeof e&&e.match(P)||[]}S.fn.extend({prop:function(e,t){return $(this,S.prop,e,t,1<arguments.length)},removeProp:function(e){return this.each(function(){delete this[S.propFix[e]||e]})}}),S.extend({prop:function(e,t,n){var r,i,o=e.nodeType;if(3!==o&&8!==o&&2!==o)return 1===o&&S.isXMLDoc(e)||(t=S.propFix[t]||t,i=S.propHooks[t]),void 0!==n?i&&"set"in i&&void 0!==(r=i.set(e,n,t))?r:e[t]=n:i&&"get"in i&&null!==(r=i.get(e,t))?r:e[t]},propHooks:{tabIndex:{get:function(e){var t=S.find.attr(e,"tabindex");return t?parseInt(t,10):ht.test(e.nodeName)||gt.test(e.nodeName)&&e.href?0:-1}}},propFix:{"for":"htmlFor","class":"className"}}),y.optSelected||(S.propHooks.selected={get:function(e){var t=e.parentNode;return t&&t.parentNode&&t.parentNode.selectedIndex,null},set:function(e){var t=e.parentNode;t&&(t.selectedIndex,t.parentNode&&t.parentNode.selectedIndex)}}),S.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){S.propFix[this.toLowerCase()]=this}),S.fn.extend({addClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).addClass(t.call(this,e,yt(this)))});if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=e[a++])r.indexOf(" "+o+" ")<0&&(r+=o+" ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},removeClass:function(t){var e,n,r,i,o,a,s,u=0;if(m(t))return this.each(function(e){S(this).removeClass(t.call(this,e,yt(this)))});if(!arguments.length)return this.attr("class","");if((e=mt(t)).length)while(n=this[u++])if(i=yt(n),r=1===n.nodeType&&" "+vt(i)+" "){a=0;while(o=e[a++])while(-1<r.indexOf(" "+o+" "))r=r.replace(" "+o+" "," ");i!==(s=vt(r))&&n.setAttribute("class",s)}return this},toggleClass:function(i,t){var o=typeof i,a="string"===o||Array.isArray(i);return"boolean"==typeof t&&a?t?this.addClass(i):this.removeClass(i):m(i)?this.each(function(e){S(this).toggleClass(i.call(this,e,yt(this),t),t)}):this.each(function(){var e,t,n,r;if(a){t=0,n=S(this),r=mt(i);while(e=r[t++])n.hasClass(e)?n.removeClass(e):n.addClass(e)}else void 0!==i&&"boolean"!==o||((e=yt(this))&&Y.set(this,"__className__",e),this.setAttribute&&this.setAttribute("class",e||!1===i?"":Y.get(this,"__className__")||""))})},hasClass:function(e){var t,n,r=0;t=" "+e+" ";while(n=this[r++])if(1===n.nodeType&&-1<(" "+vt(yt(n))+" ").indexOf(t))return!0;return!1}});var xt=/\r/g;S.fn.extend({val:function(n){var r,e,i,t=this[0];return arguments.length?(i=m(n),this.each(function(e){var t;1===this.nodeType&&(null==(t=i?n.call(this,e,S(this).val()):n)?t="":"number"==typeof t?t+="":Array.isArray(t)&&(t=S.map(t,function(e){return null==e?"":e+""})),(r=S.valHooks[this.type]||S.valHooks[this.nodeName.toLowerCase()])&&"set"in r&&void 0!==r.set(this,t,"value")||(this.value=t))})):t?(r=S.valHooks[t.type]||S.valHooks[t.nodeName.toLowerCase()])&&"get"in r&&void 0!==(e=r.get(t,"value"))?e:"string"==typeof(e=t.value)?e.replace(xt,""):null==e?"":e:void 0}}),S.extend({valHooks:{option:{get:function(e){var t=S.find.attr(e,"value");return null!=t?t:vt(S.text(e))}},select:{get:function(e){var t,n,r,i=e.options,o=e.selectedIndex,a="select-one"===e.type,s=a?null:[],u=a?o+1:i.length;for(r=o<0?u:a?o:0;r<u;r++)if(((n=i[r]).selected||r===o)&&!n.disabled&&(!n.parentNode.disabled||!A(n.parentNode,"optgroup"))){if(t=S(n).val(),a)return t;s.push(t)}return s},set:function(e,t){var n,r,i=e.options,o=S.makeArray(t),a=i.length;while(a--)((r=i[a]).selected=-1<S.inArray(S.valHooks.option.get(r),o))&&(n=!0);return n||(e.selectedIndex=-1),o}}}}),S.each(["radio","checkbox"],function(){S.valHooks[this]={set:function(e,t){if(Array.isArray(t))return e.checked=-1<S.inArray(S(e).val(),t)}},y.checkOn||(S.valHooks[this].get=function(e){return null===e.getAttribute("value")?"on":e.value})}),y.focusin="onfocusin"in C;var bt=/^(?:focusinfocus|focusoutblur)$/,wt=function(e){e.stopPropagation()};S.extend(S.event,{trigger:function(e,t,n,r){var i,o,a,s,u,l,c,f,p=[n||E],d=v.call(e,"type")?e.type:e,h=v.call(e,"namespace")?e.namespace.split("."):[];if(o=f=a=n=n||E,3!==n.nodeType&&8!==n.nodeType&&!bt.test(d+S.event.triggered)&&(-1<d.indexOf(".")&&(d=(h=d.split(".")).shift(),h.sort()),u=d.indexOf(":")<0&&"on"+d,(e=e[S.expando]?e:new S.Event(d,"object"==typeof e&&e)).isTrigger=r?2:3,e.namespace=h.join("."),e.rnamespace=e.namespace?new RegExp("(^|\\.)"+h.join("\\.(?:.*\\.|)")+"(\\.|$)"):null,e.result=void 0,e.target||(e.target=n),t=null==t?[e]:S.makeArray(t,[e]),c=S.event.special[d]||{},r||!c.trigger||!1!==c.trigger.apply(n,t))){if(!r&&!c.noBubble&&!x(n)){for(s=c.delegateType||d,bt.test(s+d)||(o=o.parentNode);o;o=o.parentNode)p.push(o),a=o;a===(n.ownerDocument||E)&&p.push(a.defaultView||a.parentWindow||C)}i=0;while((o=p[i++])&&!e.isPropagationStopped())f=o,e.type=1<i?s:c.bindType||d,(l=(Y.get(o,"events")||Object.create(null))[e.type]&&Y.get(o,"handle"))&&l.apply(o,t),(l=u&&o[u])&&l.apply&&V(o)&&(e.result=l.apply(o,t),!1===e.result&&e.preventDefault());return e.type=d,r||e.isDefaultPrevented()||c._default&&!1!==c._default.apply(p.pop(),t)||!V(n)||u&&m(n[d])&&!x(n)&&((a=n[u])&&(n[u]=null),S.event.triggered=d,e.isPropagationStopped()&&f.addEventListener(d,wt),n[d](),e.isPropagationStopped()&&f.removeEventListener(d,wt),S.event.triggered=void 0,a&&(n[u]=a)),e.result}},simulate:function(e,t,n){var r=S.extend(new S.Event,n,{type:e,isSimulated:!0});S.event.trigger(r,null,t)}}),S.fn.extend({trigger:function(e,t){return this.each(function(){S.event.trigger(e,t,this)})},triggerHandler:function(e,t){var n=this[0];if(n)return S.event.trigger(e,t,n,!0)}}),y.focusin||S.each({focus:"focusin",blur:"focusout"},function(n,r){var i=function(e){S.event.simulate(r,e.target,S.event.fix(e))};S.event.special[r]={setup:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r);t||e.addEventListener(n,i,!0),Y.access(e,r,(t||0)+1)},teardown:function(){var e=this.ownerDocument||this.document||this,t=Y.access(e,r)-1;t?Y.access(e,r,t):(e.removeEventListener(n,i,!0),Y.remove(e,r))}}});var Tt=C.location,Ct={guid:Date.now()},Et=/\?/;S.parseXML=function(e){var t;if(!e||"string"!=typeof e)return null;try{t=(new C.DOMParser).parseFromString(e,"text/xml")}catch(e){t=void 0}return t&&!t.getElementsByTagName("parsererror").length||S.error("Invalid XML: "+e),t};var St=/\[\]$/,kt=/\r?\n/g,At=/^(?:submit|button|image|reset|file)$/i,Nt=/^(?:input|select|textarea|keygen)/i;function Dt(n,e,r,i){var t;if(Array.isArray(e))S.each(e,function(e,t){r||St.test(n)?i(n,t):Dt(n+"["+("object"==typeof t&&null!=t?e:"")+"]",t,r,i)});else if(r||"object"!==w(e))i(n,e);else for(t in e)Dt(n+"["+t+"]",e[t],r,i)}S.param=function(e,t){var n,r=[],i=function(e,t){var n=m(t)?t():t;r[r.length]=encodeURIComponent(e)+"="+encodeURIComponent(null==n?"":n)};if(null==e)return"";if(Array.isArray(e)||e.jquery&&!S.isPlainObject(e))S.each(e,function(){i(this.name,this.value)});else for(n in e)Dt(n,e[n],t,i);return r.join("&")},S.fn.extend({serialize:function(){return S.param(this.serializeArray())},serializeArray:function(){return this.map(function(){var e=S.prop(this,"elements");return e?S.makeArray(e):this}).filter(function(){var e=this.type;return this.name&&!S(this).is(":disabled")&&Nt.test(this.nodeName)&&!At.test(e)&&(this.checked||!pe.test(e))}).map(function(e,t){var n=S(this).val();return null==n?null:Array.isArray(n)?S.map(n,function(e){return{name:t.name,value:e.replace(kt,"\r\n")}}):{name:t.name,value:n.replace(kt,"\r\n")}}).get()}});var jt=/%20/g,qt=/#.*$/,Lt=/([?&])_=[^&]*/,Ht=/^(.*?):[ \t]*([^\r\n]*)$/gm,Ot=/^(?:GET|HEAD)$/,Pt=/^\/\//,Rt={},Mt={},It="*/".concat("*"),Wt=E.createElement("a");function Ft(o){return function(e,t){"string"!=typeof e&&(t=e,e="*");var n,r=0,i=e.toLowerCase().match(P)||[];if(m(t))while(n=i[r++])"+"===n[0]?(n=n.slice(1)||"*",(o[n]=o[n]||[]).unshift(t)):(o[n]=o[n]||[]).push(t)}}function Bt(t,i,o,a){var s={},u=t===Mt;function l(e){var r;return s[e]=!0,S.each(t[e]||[],function(e,t){var n=t(i,o,a);return"string"!=typeof n||u||s[n]?u?!(r=n):void 0:(i.dataTypes.unshift(n),l(n),!1)}),r}return l(i.dataTypes[0])||!s["*"]&&l("*")}function $t(e,t){var n,r,i=S.ajaxSettings.flatOptions||{};for(n in t)void 0!==t[n]&&((i[n]?e:r||(r={}))[n]=t[n]);return r&&S.extend(!0,e,r),e}Wt.href=Tt.href,S.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:Tt.href,type:"GET",isLocal:/^(?:about|app|app-storage|.+-extension|file|res|widget):$/.test(Tt.protocol),global:!0,processData:!0,async:!0,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":It,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":!0,"text json":JSON.parse,"text xml":S.parseXML},flatOptions:{url:!0,context:!0}},ajaxSetup:function(e,t){return t?$t($t(e,S.ajaxSettings),t):$t(S.ajaxSettings,e)},ajaxPrefilter:Ft(Rt),ajaxTransport:Ft(Mt),ajax:function(e,t){"object"==typeof e&&(t=e,e=void 0),t=t||{};var c,f,p,n,d,r,h,g,i,o,v=S.ajaxSetup({},t),y=v.context||v,m=v.context&&(y.nodeType||y.jquery)?S(y):S.event,x=S.Deferred(),b=S.Callbacks("once memory"),w=v.statusCode||{},a={},s={},u="canceled",T={readyState:0,getResponseHeader:function(e){var t;if(h){if(!n){n={};while(t=Ht.exec(p))n[t[1].toLowerCase()+" "]=(n[t[1].toLowerCase()+" "]||[]).concat(t[2])}t=n[e.toLowerCase()+" "]}return null==t?null:t.join(", ")},getAllResponseHeaders:function(){return h?p:null},setRequestHeader:function(e,t){return null==h&&(e=s[e.toLowerCase()]=s[e.toLowerCase()]||e,a[e]=t),this},overrideMimeType:function(e){return null==h&&(v.mimeType=e),this},statusCode:function(e){var t;if(e)if(h)T.always(e[T.status]);else for(t in e)w[t]=[w[t],e[t]];return this},abort:function(e){var t=e||u;return c&&c.abort(t),l(0,t),this}};if(x.promise(T),v.url=((e||v.url||Tt.href)+"").replace(Pt,Tt.protocol+"//"),v.type=t.method||t.type||v.method||v.type,v.dataTypes=(v.dataType||"*").toLowerCase().match(P)||[""],null==v.crossDomain){r=E.createElement("a");try{r.href=v.url,r.href=r.href,v.crossDomain=Wt.protocol+"//"+Wt.host!=r.protocol+"//"+r.host}catch(e){v.crossDomain=!0}}if(v.data&&v.processData&&"string"!=typeof v.data&&(v.data=S.param(v.data,v.traditional)),Bt(Rt,v,t,T),h)return T;for(i in(g=S.event&&v.global)&&0==S.active++&&S.event.trigger("ajaxStart"),v.type=v.type.toUpperCase(),v.hasContent=!Ot.test(v.type),f=v.url.replace(qt,""),v.hasContent?v.data&&v.processData&&0===(v.contentType||"").indexOf("application/x-www-form-urlencoded")&&(v.data=v.data.replace(jt,"+")):(o=v.url.slice(f.length),v.data&&(v.processData||"string"==typeof v.data)&&(f+=(Et.test(f)?"&":"?")+v.data,delete v.data),!1===v.cache&&(f=f.replace(Lt,"$1"),o=(Et.test(f)?"&":"?")+"_="+Ct.guid+++o),v.url=f+o),v.ifModified&&(S.lastModified[f]&&T.setRequestHeader("If-Modified-Since",S.lastModified[f]),S.etag[f]&&T.setRequestHeader("If-None-Match",S.etag[f])),(v.data&&v.hasContent&&!1!==v.contentType||t.contentType)&&T.setRequestHeader("Content-Type",v.contentType),T.setRequestHeader("Accept",v.dataTypes[0]&&v.accepts[v.dataTypes[0]]?v.accepts[v.dataTypes[0]]+("*"!==v.dataTypes[0]?", "+It+"; q=0.01":""):v.accepts["*"]),v.headers)T.setRequestHeader(i,v.headers[i]);if(v.beforeSend&&(!1===v.beforeSend.call(y,T,v)||h))return T.abort();if(u="abort",b.add(v.complete),T.done(v.success),T.fail(v.error),c=Bt(Mt,v,t,T)){if(T.readyState=1,g&&m.trigger("ajaxSend",[T,v]),h)return T;v.async&&0<v.timeout&&(d=C.setTimeout(function(){T.abort("timeout")},v.timeout));try{h=!1,c.send(a,l)}catch(e){if(h)throw e;l(-1,e)}}else l(-1,"No Transport");function l(e,t,n,r){var i,o,a,s,u,l=t;h||(h=!0,d&&C.clearTimeout(d),c=void 0,p=r||"",T.readyState=0<e?4:0,i=200<=e&&e<300||304===e,n&&(s=function(e,t,n){var r,i,o,a,s=e.contents,u=e.dataTypes;while("*"===u[0])u.shift(),void 0===r&&(r=e.mimeType||t.getResponseHeader("Content-Type"));if(r)for(i in s)if(s[i]&&s[i].test(r)){u.unshift(i);break}if(u[0]in n)o=u[0];else{for(i in n){if(!u[0]||e.converters[i+" "+u[0]]){o=i;break}a||(a=i)}o=o||a}if(o)return o!==u[0]&&u.unshift(o),n[o]}(v,T,n)),!i&&-1<S.inArray("script",v.dataTypes)&&(v.converters["text script"]=function(){}),s=function(e,t,n,r){var i,o,a,s,u,l={},c=e.dataTypes.slice();if(c[1])for(a in e.converters)l[a.toLowerCase()]=e.converters[a];o=c.shift();while(o)if(e.responseFields[o]&&(n[e.responseFields[o]]=t),!u&&r&&e.dataFilter&&(t=e.dataFilter(t,e.dataType)),u=o,o=c.shift())if("*"===o)o=u;else if("*"!==u&&u!==o){if(!(a=l[u+" "+o]||l["* "+o]))for(i in l)if((s=i.split(" "))[1]===o&&(a=l[u+" "+s[0]]||l["* "+s[0]])){!0===a?a=l[i]:!0!==l[i]&&(o=s[0],c.unshift(s[1]));break}if(!0!==a)if(a&&e["throws"])t=a(t);else try{t=a(t)}catch(e){return{state:"parsererror",error:a?e:"No conversion from "+u+" to "+o}}}return{state:"success",data:t}}(v,s,T,i),i?(v.ifModified&&((u=T.getResponseHeader("Last-Modified"))&&(S.lastModified[f]=u),(u=T.getResponseHeader("etag"))&&(S.etag[f]=u)),204===e||"HEAD"===v.type?l="nocontent":304===e?l="notmodified":(l=s.state,o=s.data,i=!(a=s.error))):(a=l,!e&&l||(l="error",e<0&&(e=0))),T.status=e,T.statusText=(t||l)+"",i?x.resolveWith(y,[o,l,T]):x.rejectWith(y,[T,l,a]),T.statusCode(w),w=void 0,g&&m.trigger(i?"ajaxSuccess":"ajaxError",[T,v,i?o:a]),b.fireWith(y,[T,l]),g&&(m.trigger("ajaxComplete",[T,v]),--S.active||S.event.trigger("ajaxStop")))}return T},getJSON:function(e,t,n){return S.get(e,t,n,"json")},getScript:function(e,t){return S.get(e,void 0,t,"script")}}),S.each(["get","post"],function(e,i){S[i]=function(e,t,n,r){return m(t)&&(r=r||n,n=t,t=void 0),S.ajax(S.extend({url:e,type:i,dataType:r,data:t,success:n},S.isPlainObject(e)&&e))}}),S.ajaxPrefilter(function(e){var t;for(t in e.headers)"content-type"===t.toLowerCase()&&(e.contentType=e.headers[t]||"")}),S._evalUrl=function(e,t,n){return S.ajax({url:e,type:"GET",dataType:"script",cache:!0,async:!1,global:!1,converters:{"text script":function(){}},dataFilter:function(e){S.globalEval(e,t,n)}})},S.fn.extend({wrapAll:function(e){var t;return this[0]&&(m(e)&&(e=e.call(this[0])),t=S(e,this[0].ownerDocument).eq(0).clone(!0),this[0].parentNode&&t.insertBefore(this[0]),t.map(function(){var e=this;while(e.firstElementChild)e=e.firstElementChild;return e}).append(this)),this},wrapInner:function(n){return m(n)?this.each(function(e){S(this).wrapInner(n.call(this,e))}):this.each(function(){var e=S(this),t=e.contents();t.length?t.wrapAll(n):e.append(n)})},wrap:function(t){var n=m(t);return this.each(function(e){S(this).wrapAll(n?t.call(this,e):t)})},unwrap:function(e){return this.parent(e).not("body").each(function(){S(this).replaceWith(this.childNodes)}),this}}),S.expr.pseudos.hidden=function(e){return!S.expr.pseudos.visible(e)},S.expr.pseudos.visible=function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)},S.ajaxSettings.xhr=function(){try{return new C.XMLHttpRequest}catch(e){}};var _t={0:200,1223:204},zt=S.ajaxSettings.xhr();y.cors=!!zt&&"withCredentials"in zt,y.ajax=zt=!!zt,S.ajaxTransport(function(i){var o,a;if(y.cors||zt&&!i.crossDomain)return{send:function(e,t){var n,r=i.xhr();if(r.open(i.type,i.url,i.async,i.username,i.password),i.xhrFields)for(n in i.xhrFields)r[n]=i.xhrFields[n];for(n in i.mimeType&&r.overrideMimeType&&r.overrideMimeType(i.mimeType),i.crossDomain||e["X-Requested-With"]||(e["X-Requested-With"]="XMLHttpRequest"),e)r.setRequestHeader(n,e[n]);o=function(e){return function(){o&&(o=a=r.onload=r.onerror=r.onabort=r.ontimeout=r.onreadystatechange=null,"abort"===e?r.abort():"error"===e?"number"!=typeof r.status?t(0,"error"):t(r.status,r.statusText):t(_t[r.status]||r.status,r.statusText,"text"!==(r.responseType||"text")||"string"!=typeof r.responseText?{binary:r.response}:{text:r.responseText},r.getAllResponseHeaders()))}},r.onload=o(),a=r.onerror=r.ontimeout=o("error"),void 0!==r.onabort?r.onabort=a:r.onreadystatechange=function(){4===r.readyState&&C.setTimeout(function(){o&&a()})},o=o("abort");try{r.send(i.hasContent&&i.data||null)}catch(e){if(o)throw e}},abort:function(){o&&o()}}}),S.ajaxPrefilter(function(e){e.crossDomain&&(e.contents.script=!1)}),S.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(e){return S.globalEval(e),e}}}),S.ajaxPrefilter("script",function(e){void 0===e.cache&&(e.cache=!1),e.crossDomain&&(e.type="GET")}),S.ajaxTransport("script",function(n){var r,i;if(n.crossDomain||n.scriptAttrs)return{send:function(e,t){r=S("<script>").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="<form></form><form></form>",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1<s&&(r=vt(e.slice(s)),e=e.slice(0,s)),m(t)?(n=t,t=void 0):t&&"object"==typeof t&&(i="POST"),0<a.length&&S.ajax({url:e,type:i||"GET",dataType:"html",data:t}).done(function(e){o=arguments,a.html(r?S("<div>").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0<arguments.length?this.on(n,null,e,t):this.trigger(n)}});var Gt=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;S.proxy=function(e,t){var n,r,i;if("string"==typeof t&&(n=e[t],t=e,e=n),m(e))return r=s.call(arguments,2),(i=function(){return e.apply(t||this,r.concat(s.call(arguments)))}).guid=e.guid=e.guid||S.guid++,i},S.holdReady=function(e){e?S.readyWait++:S.ready(!0)},S.isArray=Array.isArray,S.parseJSON=JSON.parse,S.nodeName=A,S.isFunction=m,S.isWindow=x,S.camelCase=X,S.type=w,S.now=Date.now,S.isNumeric=function(e){var t=S.type(e);return("number"===t||"string"===t)&&!isNaN(e-parseFloat(e))},S.trim=function(e){return null==e?"":(e+"").replace(Gt,"")}, true&&!(__WEBPACK_AMD_DEFINE_ARRAY__ = [], __WEBPACK_AMD_DEFINE_RESULT__ = (function(){return S}).apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));var Yt=C.jQuery,Qt=C.$;return S.noConflict=function(e){return C.$===S&&(C.$=Qt),e&&C.jQuery===S&&(C.jQuery=Yt),S},"undefined"==typeof e&&(C.jQuery=C.$=S),S});


/***/ }),

/***/ 4716:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// UNUSED EXPORTS: default

;// CONCATENATED MODULE: ./adblock-betafish/localFilesIndex.js
function getAvailableFiles() {
return {
jquery: {
"jquery-1.10.2.min.js": 93107,
"jquery-1.11.0.min.js": 96381,
"jquery-1.11.1.min.js": 95786,
"jquery-1.11.2.min.js": 95931,
"jquery-1.11.3.min.js": 95957,
"jquery-1.12.4.min.js": 97163,
"jquery-1.3.2.min.js": 57254,
"jquery-1.4.2.min.js": 72174,
"jquery-1.7.1.min.js": 93868,
"jquery-1.7.2.min.js": 94840,
"jquery-1.8.2.min.js": 93435,
"jquery-1.8.3.min.js": 93636,
"jquery-1.9.1.min.js": 92629,
"jquery-2.1.1.min.js": 84245,
"jquery-2.1.3.min.js": 84320,
"jquery-2.1.4.min.js": 84345,
"jquery-2.2.4.min.js": 85578,
"jquery-3.1.1.min.js": 86709,
"jquery-3.2.1.min.js": 86659,
},
};
}
 
/* harmony default export */ const localFilesIndex = (getAvailableFiles);
 

// EXTERNAL MODULE: ./adblock-betafish/prefs/background/index.js + 1 modules
var background = __webpack_require__(1648);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/localcdn.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, adblockIsPaused */

// This module is conditional imported only into a Chrome build via the
// build config file in ..build\config\chrome.mjs





const LocalCDN = (function getLocalCDN() {
  const urlsMatchPattern = ['http://*/*', 'https://*/*'];
  const hostRegex = /ajax\.googleapis\.com|ajax\.aspnetcdn\.com|ajax\.microsoft\.com|cdnjs\.cloudflare\.com|code\.jquery\.com|cdn\.jsdelivr\.net|yastatic\.net|yandex\.st|libs\.baidu\.com|lib\.sinaapp\.com|upcdn\.b0\.upaiyun\.com/;
  const pathRegex = { jquery: /jquery[/-](\d*\.\d*\.\d*)/ };
  const libraryPaths = { jquery: { prefix: 'jquery-', postfix: '.min.js' } };
  const headersToRemove = ['Cookie', 'Origin', 'Referer'];
  const redirectCountKey = 'redirectCount';
  const dataCountKey = 'redirectDataCount';
  const missedVersionsKey = 'missedVersions';
  let localFiles = {};
  let libraries = [];
  let versionArray = {};

  // Gets a stored value from chrome.storage if available, and parses it. Otherwise,
  // if the value isn't currently stored or if the parse fails, returns a default
  // value.
  // Param: keyName: the key under which the value is stored
  //        defaultValue: the value to be returned if the stored value cannot be
  //                      retrieved
  const getStoredValue = function (keyName, defaultValue) {
    return new Promise((resolve) => {
      (0,bg_functions/* chromeStorageGetHelper */.nX)(keyName).then((response) => {
        let storedValue = null;
        try {
          storedValue = JSON.parse(response);
        } catch (err) {
          storedValue = defaultValue;
        } finally {
          if (!storedValue) {
            storedValue = defaultValue;
          }
        }
        resolve(storedValue);
      });
    });
  };

  // Populates the version array based on the files available locally
  // Pre: localFiles and libraries must be populated first
  const populateVersionArray = function () {
    const libraryVersions = {};
    // go through each libarary
    for (let i = 0; i < libraries.length; i++) {
      // check for path info
      if (libraryPaths[libraries[i]]) {
        // get the filenames
        const filenames = Object.getOwnPropertyNames(localFiles[libraries[i]]);
        libraryVersions[libraries[i]] = [];
        for (let j = 0; j < filenames.length; j++) {
          // extract the version from the filesname
          let version = filenames[j].replace(libraryPaths[libraries[i]].prefix, '');
          version = version.replace(libraryPaths[libraries[i]].postfix, '');
          libraryVersions[libraries[i]].push(version);
        }
      }
    }

    return libraryVersions;
  };

  // Completes necessary set up for the LocalCDN
  // Post:  localFiles, libraries, and versionArray are populated based on
  //        available local files
  const setUp = function () {
    localFiles = localFilesIndex();
    libraries = Object.getOwnPropertyNames(localFiles);
    versionArray = populateVersionArray();
  };

  // Increments the redirect count by one.
  // The redirect count is loaded from and saved to storage.
  const incrementRedirectCount = function () {
    getStoredValue(redirectCountKey, 0).then((count) => {
      // increment
      let storedRedirectCount = count;
      storedRedirectCount += 1;

      // store updated count
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(redirectCountKey, JSON.stringify(storedRedirectCount));
    });
  };

  // Adds the size of the specified file to the data count for that library.
  // The data count is loaded from and saved to storage.
  // Param: targetLibrary: the library that the file belongs to
  //        fileName: the file to be added to the data count
  const addToDataCount = function (targetLibrary, fileName) {
    getStoredValue(dataCountKey, 0).then((count) => {
      // add file size to data count
      let storedDataCount = count;
      storedDataCount += localFiles[targetLibrary][fileName];

      // store updated count
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(dataCountKey, JSON.stringify(storedDataCount));
    });
  };

  // Adds the specified version of the specified library to the missed versions
  // object, if it hasn't already been added. Otherwise increments the count for
  // that version.
  // The missed versions object is loaded from and saved to storage.
  // Param: targetLibrary: the library that the missing version belongs to
  //        version: the missing version to be added
  const addMissedVersion = function (targetLibrary, version) {
    getStoredValue(missedVersionsKey, {}).then((storedMissedVersions) => {
      // add new missed version
      const missedVersions = storedMissedVersions;
      if (!missedVersions[targetLibrary]) {
        missedVersions[targetLibrary] = {};
      }
      if (missedVersions[targetLibrary][version] > 0) {
        missedVersions[targetLibrary][version] += 1;
      } else {
        missedVersions[targetLibrary][version] = 1;
      }

      // store updated missed versions
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(missedVersionsKey, JSON.stringify(missedVersions));
    });
  };

  // Handles a webRequest.onBeforeRequest event.
  // Redirects any requests for locally available files from a matching host,
  // if AdBlock is not paused. Otherwise allows request to continue as normal.
  // Records any redirects, bytes of data redirected, and missing versions of
  // supported libararies.
  // Param: details: holds information about the request, including the URL.
  const libRequestHandler = function (details) {
    // respect pause
    if (!adblockIsPaused()) {
      let targetLibrary = null;
      const requestUrl = (0,bg_functions/* parseUri */.he)(details.url);

      // check if the url contains a library keyword
      for (let i = 0; i < libraries.length; i++) {
        if (requestUrl.pathname.indexOf(libraries[i]) !== -1) {
          targetLibrary = libraries[i];
        }
      }

      // check the request host
      if (targetLibrary !== null && hostRegex.test(requestUrl.host)) {
        // check the path
        const matches = pathRegex[targetLibrary].exec(requestUrl.pathname);
        if (matches) {
          const version = matches[1];

          // check if we have the version locally
          if (versionArray[targetLibrary].indexOf(version) !== -1) {
            const libraryPrefix = libraryPaths[targetLibrary].prefix;
            const libraryPostfix = libraryPaths[targetLibrary].postfix;
            const fileName = libraryPrefix + version + libraryPostfix;
            const localPath = `localLib/${targetLibrary}/${fileName}`;
            incrementRedirectCount();
            addToDataCount(targetLibrary, fileName);
            return { redirectUrl: browser.runtime.getURL(localPath) };
          }
          addMissedVersion(targetLibrary, version);
        }
      }
    }

    return { cancel: false };
  };

  // Handles a webrequest.onBeforeSendHeaders event.
  // Strips the cookie, origin, and referer headers (if present) from any requests for
  // a supported libarary from a matching host, if AdBlock is not paused. Otherwise
  // allows request to continue as normal.
  // Param: details: holds information about the request, including the URL and request
  //                 headers
  const stripMetadataHandler = function (details) {
    // respect pause
    if (!adblockIsPaused()) {
      const requestUrl = (0,bg_functions/* parseUri */.he)(details.url);
      let match = false;

      // check if the url contains a library keyword
      for (let k = 0; k < libraries.length; k++) {
        if (requestUrl.pathname.indexOf(libraries[k]) !== -1) {
          match = true;
        }
      }

      // check for a matching host
      if (match && hostRegex.test(requestUrl.host)) {
        // strip the headers to remove, if present
        for (let i = 0; i < details.requestHeaders.length; i++) {
          const aHeader = details.requestHeaders[i].name;
          if (headersToRemove.includes(aHeader)) {
            details.requestHeaders.splice(i -= 1, 1);
          }
        }
      }
    }

    return { requestHeaders: details.requestHeaders };
  };

  // Sets redirect count, data count, and missed versions back to default
  // (0 for redirect count and data count, and an empty object for missed
  // versions)
  const resetCollectedData = function () {
    (0,bg_functions/* chromeStorageSetHelper */.rJ)(redirectCountKey, '0');
    (0,bg_functions/* chromeStorageSetHelper */.rJ)(dataCountKey, '0');
    (0,bg_functions/* chromeStorageSetHelper */.rJ)(missedVersionsKey, '{}');
  };

  return {
    migrateStoredData() {
      return Promise.all([(0,bg_functions/* migrateData */.ww)(redirectCountKey),
        (0,bg_functions/* migrateData */.ww)(dataCountKey),
        (0,bg_functions/* migrateData */.ww)(missedVersionsKey)]);
    },
    setUp,
    // Starts the LocalCDN listeners
    start() {
      setUp();
      browser.webRequest.onBeforeRequest.addListener(libRequestHandler, { urls: urlsMatchPattern }, ['blocking']);
      browser.webRequest.onBeforeSendHeaders.addListener(stripMetadataHandler, { urls: urlsMatchPattern }, ['blocking', 'requestHeaders']);
    },
    // Stops the LocalCDN listeners and reset data
    end() {
      browser.webRequest.onBeforeRequest.removeListener(libRequestHandler);
      browser.webRequest.onBeforeSendHeaders.removeListener(stripMetadataHandler);
      resetCollectedData();
    },
    // Gets the redirect count as a number of redirects
    getRedirectCount() {
      return getStoredValue(redirectCountKey, 0);
    },
    // Gets the data count as a number of bytes
    getDataCount() {
      return getStoredValue(dataCountKey, 0);
    },
    // Gets the missed versions object, which includes a count of how many
    // times the missed version has been requested
    getMissedVersions() {
      return getStoredValue(missedVersionsKey, undefined);
    },
  };
}());

/* harmony default export */ const localcdn = ((/* unused pure expression or super */ null && (LocalCDN)));

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  LocalCDN,
});

background/* settings.onload */.Xd.onload().then(() => {
  if ((0,background/* getSettings */.Gw)().local_cdn) {
    LocalCDN.migrateStoredData().then(() => {
      LocalCDN.start();
    });
  }
});


/***/ }),

/***/ 4988:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _prefs_background__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1648);
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(7337);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, adblockIsPaused, replacedCounts */





const LocalDataCollection = (function getLocalDataCollection() {
  const easyPrivacyURL = 'https://easylist-downloads.adblockplus.org/easyprivacy.txt';
  const FIFTEEN_MINS = 15;
  const EXT_STATS_KEY = 'ext_stats_key';
  const STATS_ALARM_NAME = 'statsalarm';
  const STATS_STORAGE_KEY = 'ab:stats.storage.key';
  const REPORTING_OPTIONS = {
    filterType: 'blocking',
    includeElementHiding: false,
  };

  // Setup memory cache
  let dataCollectionCache = {};
  dataCollectionCache.domains = {};

  const initializeDomainIfNeeded = function (domain) {
    if (!(domain in dataCollectionCache.domains)) {
      dataCollectionCache.domains[domain] = {};
      dataCollectionCache.domains[domain].ads = 0;
      dataCollectionCache.domains[domain].trackers = 0;
      dataCollectionCache.domains[domain].adsReplaced = 0;
    }
  };

  const addFilterToCache = function (details, filter) {
    const validFilterText = filter && filter.text && (typeof filter.text === 'string');
    if (details.tabId > 0 && validFilterText && validFilterText && details && details.url) {
      browser.tabs.get(details.tabId).then(async (tab) => {
        if (tab.incognito) {
          return;
        }
        const theURL = new URL(details.url);
        const domain = theURL.hostname;
        initializeDomainIfNeeded(domain);
        const { text } = filter;
        let isAd = true;
        const subscriptions = await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__.subscriptions.getForFilter(text);
        subscriptions.forEach((sub) => {
          if (!sub.disabled && sub.url && sub.url === easyPrivacyURL) {
            isAd = false;
          }
        });
        if (isAd) {
          dataCollectionCache.domains[domain].ads += 1;
        } else {
          dataCollectionCache.domains[domain].trackers += 1;
        }
        (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__/* .chromeStorageSetHelper */ .rJ)(STATS_STORAGE_KEY, dataCollectionCache);
      });
    }
  };

  const filterListener = function ({ request, filter }) {
    if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection && !adblockIsPaused()) {
      addFilterToCache(request, filter);
    } else if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection) {
      LocalDataCollection.end();
    }
  };

  const adReplacedListener = function (tabId, url) {
    if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection && !adblockIsPaused()) {
      const domain = new URL(url).hostname;
      initializeDomainIfNeeded(domain);
      dataCollectionCache.domains[domain].adsReplaced += 1;
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__/* .chromeStorageSetHelper */ .rJ)(STATS_STORAGE_KEY, dataCollectionCache);
    } else if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection) {
      LocalDataCollection.end();
    }
  };


  const clearCache = function () {
    dataCollectionCache = {};
    dataCollectionCache.domains = {};
    browser.storage.local.remove(STATS_STORAGE_KEY);
  };

  const saveCacheData = function () {
    return new Promise(async (resolve) => {
      if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection && !(0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__/* .isEmptyObject */ .Qr)(dataCollectionCache.domains)) {
        const hourSnapShot = JSON.parse(JSON.stringify({
          v: '1',
          doms: dataCollectionCache.domains,
        }));
        browser.storage.local.get(EXT_STATS_KEY).then((hourlyResponse) => {
          const savedData = hourlyResponse[EXT_STATS_KEY] || { };
          savedData[Date.now().toString()] = hourSnapShot;
          (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__/* .chromeStorageSetHelper */ .rJ)(EXT_STATS_KEY, savedData, resolve);
          clearCache();
        });
      } else {
        if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection) {
          browser.alarms.clear(STATS_ALARM_NAME);
        }
        resolve();
      }
    });
  };

  const loadCache = async function () {
    const response = await browser.storage.local.get(STATS_STORAGE_KEY);
    if (response[STATS_STORAGE_KEY]) {
      dataCollectionCache = response[STATS_STORAGE_KEY];
    }
  };

  const initialize = function () {
    browser.alarms.onAlarm.addListener(async (alarm) => {
      // Not our alarm, nothing to do
      if (!alarm && alarm.name !== STATS_ALARM_NAME) {
        return;
      }
      await _prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .settings.onload */ .Xd.onload();
      // If we're collecting data and the alarm has fired, process the memory cache
      if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection) {
        await loadCache();
        saveCacheData();
      } else {
        browser.alarms.clear(STATS_ALARM_NAME);
      }
    });
    // If enabled at startup, enable periodic processing of memory cache
    _prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .settings.onload */ .Xd.onload().then(async () => {
      if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .getSettings */ .Gw)().local_data_collection) {
        return;
      }
      await loadCache();
      browser.alarms.create(STATS_ALARM_NAME, { periodInMinutes: FIFTEEN_MINS });
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__.reporting.onBlockableItem.addListener(filterListener, REPORTING_OPTIONS);
      replacedCounts.adReplacedNotifier.on('adReplaced', adReplacedListener);
    });
  };
  initialize();

  const returnObj = {};
  returnObj.EXT_STATS_KEY = EXT_STATS_KEY;

  returnObj.start = function returnObjStart() {
    return new Promise((resolve) => {
      dataCollectionCache.domains = {};
      (0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .setSetting */ .Lt)('local_data_collection', true, () => {
        initialize();
        resolve();
      });
    });
  };

  returnObj.end = function returnObjEnd() {
    return new Promise((resolve) => {
      browser.alarms.clear(STATS_ALARM_NAME);
      clearCache();
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__.reporting.onBlockableItem.removeListener(filterListener, REPORTING_OPTIONS);
      replacedCounts.adReplacedNotifier.off('adReplaced', adReplacedListener);
      (0,_prefs_background__WEBPACK_IMPORTED_MODULE_1__/* .setSetting */ .Lt)('local_data_collection', false, resolve);
    });
  };
  returnObj.clearCache = clearCache;
  returnObj.getCache = function returnObjGetCache() {
    return dataCollectionCache;
  };
  returnObj.saveCacheData = saveCacheData;
  returnObj.easyPrivacyURL = easyPrivacyURL;
  returnObj.exportRawStats = async function returnObjFilterStats() {
    const hourlyResponse = await browser.storage.local.get(EXT_STATS_KEY);
    return Promise.resolve(hourlyResponse[EXT_STATS_KEY] || { });
  };
  returnObj.getRawStatsSize = async function returnObjFilterStatsSize() {
    const rawStats = await LocalDataCollection.exportRawStats();
    return Promise.resolve((JSON.stringify(rawStats).length));
  };
  // Note: the following function is used for testing purposes
  // Import filter list statistics which will be converted to the format needed / used
  // by the 'stats' tab.
  // Inputs: filterStatsArray: array of stringified JSON filter list statistics data
  //         from the DataCollection V2 messages.
  // Returns: a Promise, resolved when complete
  returnObj.importFilterStats = function returnObjFilterStats(filterStatsArray) {
    return new Promise((resolve) => {
      let parsedfilterStats = {};
      try {
        parsedfilterStats = JSON.parse(filterStatsArray);
      } catch (e) {
        // eslint-disable-next-line no-console
        console.log(e);
        resolve(`error : ${e.toString()}`);
        return;
      }
      browser.storage.local.get(EXT_STATS_KEY).then((hourlyResponse) => {
        const savedData = hourlyResponse[EXT_STATS_KEY] || { };
        for (let inx = 0; inx < parsedfilterStats.length; inx++) {
          const dupDataCache = parsedfilterStats[inx];
          // only process new data
          // don't overwrite existing data
          if (!savedData[Date.parse(dupDataCache.timeOfLastPush)]) {
            const hourSnapShot = {};
            const initializeDomainDataObject = function (domain) {
              hourSnapShot[domain] = {};
              hourSnapShot[domain].ads = 0;
              hourSnapShot[domain].trackers = 0;
              hourSnapShot[domain].adsReplaced = 0;
              if (dupDataCache.domains[domain] && typeof dupDataCache.domains[domain].adsReplaced === 'number') {
                hourSnapShot[domain].adsReplaced = dupDataCache.domains[domain].adsReplaced;
              }
            };
            for (const domain in dupDataCache.domains) {
              initializeDomainDataObject(domain);
            }
            const processDomainByFilterType = function (filter, domains, filterRequestType) {
              for (const domain in domains) {
                if (!hourSnapShot[domain]) {
                  initializeDomainDataObject(domain);
                }
                if (dupDataCache.filters[filter].subscriptions
                    && dupDataCache.filters[filter].subscriptions.length
                    && dupDataCache.filters[filter].subscriptions.includes(easyPrivacyURL)) {
                  hourSnapShot[domain].trackers
                    += dupDataCache.filters[filter][filterRequestType][domain].hits;
                } else {
                  hourSnapShot[domain].ads
                    += dupDataCache.filters[filter][filterRequestType][domain].hits;
                }
              }
            };
            for (const filter in dupDataCache.filters) {
              processDomainByFilterType(filter, dupDataCache.filters[filter].firstParty, 'firstParty');
              processDomainByFilterType(filter, dupDataCache.filters[filter].thirdParty, 'thirdParty');
            }
            savedData[Date.parse(dupDataCache.timeOfLastPush)] = JSON.parse(JSON.stringify({
              v: '1',
              doms: hourSnapShot,
            }));
          }
        }// end for loop
        (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_2__/* .chromeStorageSetHelper */ .rJ)(EXT_STATS_KEY, savedData);
        resolve(' success! ');
      });
    });
  };
  return returnObj;
}());

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (LocalDataCollection);


/***/ }),

/***/ 6798:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/types.js
var types = __webpack_require__(6684);
// EXTERNAL MODULE: ./adblock-betafish/prefs/background/index.js + 1 modules
var background = __webpack_require__(1648);
// EXTERNAL MODULE: ./adblock-betafish/subscriptionadapter.js + 1 modules
var subscriptionadapter = __webpack_require__(1974);
// EXTERNAL MODULE: ./adblock-betafish/datacollection.v2.js
var datacollection_v2 = __webpack_require__(5953);
// EXTERNAL MODULE: ./adblock-betafish/servermessages.js
var servermessages = __webpack_require__(2559);
// EXTERNAL MODULE: ./adblock-betafish/localdatacollection.js
var localdatacollection = __webpack_require__(4988);
;// CONCATENATED MODULE: ./adblock-betafish/excludefilter.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, parseFilter, chromeStorageSetHelper */

// Module for removing individual filters from filter lists
// An 'advance' feature, used on the Customize tab, titled "disabled filters"



const ExcludeFilter = (function excludeFilter() {
  const excludeFiltersKey = 'exclude_filters';
  // Removes the valid filters from any / all filter lists and
  // saves the valid entries
  // Note:  any invalid filters are ignored
  // Inputs: filters:string the new filters.
  const setExcludeFilters = async function (filtersToExclude) {
    const response = await browser.storage.local.get(excludeFiltersKey);
    const currentExcludeFilters = response[excludeFiltersKey];
    let promises = [];
    if (currentExcludeFilters) {
      const currentExcludeArr = currentExcludeFilters.split('\n');
      for (let i = 0; i < currentExcludeArr.length; i++) {
        const filter = currentExcludeArr[i];
        if (filter.length > 0) {
          const result = ewe_api.filters.validate(filter);
          if (!result) {
            promises.push(ewe_api.filters.enable([filter]));
          }
        }
      }
    }
    await Promise.all(promises);
    promises = [];
    const excludeFilters = filtersToExclude.trim();
    const excludeFiltersArray = excludeFilters.split('\n');
    const validExcludeFiltersArray = [];
    for (let i = 0; i < excludeFiltersArray.length; i++) {
      let filter = excludeFiltersArray[i];
      filter = filter.trim();
      if (filter.length > 0) {
        const result = ewe_api.filters.validate(filter);
        if (!result) {
          validExcludeFiltersArray.push(filter);
          promises.push(ewe_api.filters.disable([filter]));
        }
      }
    }
    await Promise.all(promises);
    if (validExcludeFiltersArray.length) {
      chromeStorageSetHelper(excludeFiltersKey, validExcludeFiltersArray.join('\n'));
    } else {
      browser.storage.local.remove(excludeFiltersKey);
    }
  };

  function excludeFilterChangeListener() {
    browser.storage.local.get(excludeFiltersKey).then((response) => {
      if (response[excludeFiltersKey]) {
        setExcludeFilters(response[excludeFiltersKey]);
      }
    });
  }

  // At startup, add a listener to so that the exclude filters
  // can be removed if the filter lists are updated
  ewe_api.subscriptions.onAdded.addListener(excludeFilterChangeListener);
  ewe_api.subscriptions.onChanged.addListener(excludeFilterChangeListener);
  ewe_api.subscriptions.onRemoved.addListener(excludeFilterChangeListener);

  return {
    setExcludeFilters,
  };
}());
/* harmony default export */ const excludefilter = (ExcludeFilter);

// EXTERNAL MODULE: ./adblock-betafish/messaging/messagevalidator.js
var messagevalidator = __webpack_require__(7185);
// EXTERNAL MODULE: ./adblock-betafish/alias/icon.js
var icon = __webpack_require__(3398);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/messaging/message-responder.js
/* For ESLint: List any global identifiers used in this file below */
/* global browser, isTrustedSender, tryToUnwhitelist, getUserFilters,
   createDomainAllowlistFilter, addCustomFilter, countCache, checkUpdateProgress,
   adblockIsPaused, pageIsWhitelisted, adblockIsDomainPaused, getCurrentTabInfo,
   openTab, updateFilterLists, isTrustedSenderDomain, updateButtonUIAndContextMenus,
   getDebugInfo, addYTChannelListeners, removeYTChannelListeners, openYTManagedSubPage,
   addTwitchAllowlistListeners, removeTwitchAllowlistListeners, abpPrefPropertyNames,
   pausedFilterText1, pausedFilterText2, updateCustomFilterCountMap, LocalCDN
*/















const processMessageResponse = (sendResponse, responseData) => {
  sendResponse({});
  return Promise.resolve(responseData);
};

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  processMessageResponse,
});

const uiPorts = new Map();
const messageTypes = new Map([
  ['settings', 'settings.respond'],
]);


function sendMessage(type, action, ...args) {
  if (uiPorts.size === 0) {
    return;
  }

  for (const [uiPort, filters] of uiPorts) {
    const actions = filters.get(type);
    if (actions && actions.indexOf(action) !== -1) {
      uiPort.postMessage({
        type: messageTypes.get(type),
        action,
        args,
      });
    }
  }
}

function getListener(type, action) {
  return (...args) => {
    sendMessage(type, action, ...args);
  };
}

function listen(type, filters, newFilter) {
  switch (type) {
    case 'settings':
      filters.set('settings', newFilter);
      break;
    default:
    // do nothing
  }
}

function onConnect(uiPort) {
  if (!isTrustedSender(uiPort.sender)) {
    return;
  }

  if (uiPort.name !== 'settings') {
    return;
  }

  const filters = new Map();
  uiPorts.set(uiPort, filters);

  uiPort.onDisconnect.addListener(() => {
    uiPorts.delete(uiPort);
  });

  uiPort.onMessage.addListener((message) => {
    const [type, action] = message.type.split('.', 2);
    if (action === 'listen') {
      listen(type, filters, message.filter, message,
        uiPort.sender && uiPort.sender.tab && uiPort.sender.tab.id);
    }
  });
}
browser.runtime.onConnect.addListener(onConnect);

/**
 * Process messages and events related to the 'Settings' object
 *
 */
background/* settings.onload */.Xd.onload().then(() => {
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (!isTrustedSender(sender)) {
      return;
    }
    const { command } = message;
    switch (command) {
      case 'setSetting':
        (0,background/* setSetting */.Lt)(message.name, message.isEnabled);
        sendResponse({});
        break;
      case 'isValidTheme':
        return processMessageResponse(sendResponse, (0,background/* isValidTheme */.uR)(message.name));
      case 'getABPPrefPropertyNames':
        return processMessageResponse(sendResponse, abpPrefPropertyNames);
      default:
    }
  });
  background/* settingsNotifier.on */.Pg.on('settings.changed', getListener('settings', 'changed'));
});

/**
 * Process messages from Popup menu and other UI components
 *
 */
/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (!isTrustedSender(sender)) {
    return;
  }
  const { command } = message;
  switch (command) {
    case 'pageIsWhitelisted':
      sendResponse(pageIsWhitelisted(JSON.parse(message.page)));
      break;
    case 'adblockIsPaused': {
      const isPaused = adblockIsPaused(message.newValue);
      sendResponse(isPaused);
      return Promise.resolve(isPaused);
    }
    case 'adblockIsDomainPaused': {
      const isDomainPaused = adblockIsDomainPaused(message.activeTab, message.newValue);
      sendResponse(isDomainPaused);
      return Promise.resolve(isDomainPaused);
    }
    case 'getPausedFilterText':
      return processMessageResponse(sendResponse, { pausedFilterText1, pausedFilterText2 });
    case 'getCurrentTabInfo':
      sendResponse({});
      return getCurrentTabInfo(false, message.tabId).then(results => results);
    case 'updateCustomFilterCountMap':
      updateCustomFilterCountMap(message.countMap);
      sendResponse({});
      return;
    case 'updateFilterLists':
      updateFilterLists();
      sendResponse({});
      return;
    case 'checkUpdateProgress':
      sendResponse(checkUpdateProgress());
      return;
    case 'getCustomFilterCount':
      sendResponse({ response: countCache.getCustomFilterCount(message.host) });
      return;
    case 'subscriptions.has':
      return processMessageResponse(sendResponse, ewe_api.subscriptions.has(message.url));
    case 'createDomainAllowlistFilter':
      sendResponse({});
      return createDomainAllowlistFilter(message.url, message.origin).then(results => results);
    case 'getUserFilters':
      sendResponse({ response: getUserFilters() });
      return;
    case 'tryToUnwhitelist':
      sendResponse({});
      return tryToUnwhitelist(message.url, message.id).then(results => results);
    case 'getDebugInfo':
      sendResponse({});
      return getDebugInfo();
    case 'showIconBadgeCTA':
      sendResponse({});
      (0,icon/* showIconBadgeCTA */.QO)(message.value);
      return;
    case 'getNewBadgeTextReason':
      sendResponse({ reason: (0,icon/* getNewBadgeTextReason */.vo)() });
      return;
    case 'updateButtonUIAndContextMenus':
      updateButtonUIAndContextMenus();
      sendResponse({});
      break;
    default:
  }
});

async function addCustomFilterMessageValidation(message) {
  if (await messagevalidator/* default.validateMessage */.Z.validateMessage(message)) {
    return addCustomFilter(message.filterTextToAdd, message.origin).then(results => results);
  }
}

/**
 * Process the 'addCustomFilter' message the wizards, which requires verifing the
 * `addCustomFilterRandomName` property on the message matches what is current set on the global
 * name space
 *
 */
/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message) => {
  if (
    message.command === 'addCustomFilter'
    && message.filterTextToAdd
  ) {
    return addCustomFilterMessageValidation(message);
  }
});

/**
 * Process messages that are sent from a content script
 *
 */
//
/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (isTrustedSenderDomain(sender) || isTrustedSender(sender)) {
    const { command } = message;
    switch (command) {
      case 'subscribe':
        subscriptionadapter/* default.subscribe */.Z.subscribe({ id: message.id });
        sendResponse({});
        break;
      case 'unsubscribe':
        subscriptionadapter/* default.unsubscribe */.Z.unsubscribe({ adblockId: message.adblockId });
        sendResponse({});
        break;
      case 'getIdFromURL':
        sendResponse({});
        return processMessageResponse(sendResponse,
          subscriptionadapter/* default.getIdFromURL */.Z.getIdFromURL(message.url));
      case 'isLanguageSpecific':
        sendResponse({});
        return processMessageResponse(sendResponse,
          subscriptionadapter/* default.isLanguageSpecific */.Z.isLanguageSpecific(message.adblockId));
      case 'getSubscriptionsMinusText':
        sendResponse({});
        return processMessageResponse(sendResponse,
          subscriptionadapter/* default.getSubscriptionsMinusText */.Z.getSubscriptionsMinusText());
      case 'getAllSubscriptionsMinusText':
        sendResponse({});
        return processMessageResponse(sendResponse,
          subscriptionadapter/* default.getAllSubscriptionsMinusText */.Z.getAllSubscriptionsMinusText());
      case 'recordGeneralMessage':
        servermessages/* default.recordGeneralMessage */.Z.recordGeneralMessage(message.msg, undefined, message.additionalParams);
        sendResponse({});
        break;
      default:
    }
  }
});

/**
 * Process messages that are sent from a content script & trusted senders
 *
 */
//
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  const { command } = message;
  switch (command) {
    case 'getSettings':
      sendResponse((0,background/* getSettings */.Gw)());
      break;
    case 'openTab':
      openTab(message.urlToOpen);
      sendResponse({});
      break;
    default:
  }
});

/**
 * Process messages for the LocalCDN
 *
 */
/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (!isTrustedSender(sender)) {
    return;
  }
  const { command } = message;
  switch (command) {
    case 'LocalCDN.start':
      LocalCDN.start();
      sendResponse({});
      break;
    case 'LocalCDN.end':
      LocalCDN.end();
      sendResponse({});
      break;
    case 'LocalCDN.isAvailable':
      return processMessageResponse(sendResponse, (typeof LocalCDN === 'object'));
    default:
  }
});

/**
 * Process messages for the DataCollectionV2
 *
 */
/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (!isTrustedSender(sender)) {
    return;
  }
  const { command } = message;
  switch (command) {
    case 'DataCollectionV2.start':
      return processMessageResponse(sendResponse, datacollection_v2/* default.start */.Z.start());
    case 'DataCollectionV2.end':
      return processMessageResponse(sendResponse, datacollection_v2/* default.end */.Z.end());
    default:
  }
});

/**
 * Process messages for the  Exclude Filters, Local Data Collection,
 * Server Messages, YT Channel & Twitch Channel Listeners
 *
 */
/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (!isTrustedSender(sender)) {
    return;
  }
  const { command } = message;
  switch (command) {
    case 'addYTChannelListeners':
      addYTChannelListeners();
      sendResponse({});
      break;
    case 'removeYTChannelListeners':
      removeYTChannelListeners();
      sendResponse({});
      break;
    case 'openYTManagedSubPage':
      openYTManagedSubPage();
      sendResponse({});
      break;
    case 'addTwitchAllowlistListeners':
      addTwitchAllowlistListeners();
      sendResponse({});
      break;
    case 'removeTwitchAllowlistListeners':
      removeTwitchAllowlistListeners();
      sendResponse({});
      break;
    case 'recordAnonymousErrorMessage':
      servermessages/* default.recordAnonymousErrorMessage */.Z.recordAnonymousErrorMessage(message.msg, undefined, message.additionalParams);
      sendResponse({});
      break;
    case 'LocalDataCollection.clearCache':
      localdatacollection/* default.clearCache */.Z.clearCache();
      sendResponse({});
      break;
    case 'LocalDataCollection.end':
      return processMessageResponse(sendResponse, localdatacollection/* default.end */.Z.end());
    case 'LocalDataCollection.start':
      return processMessageResponse(sendResponse, localdatacollection/* default.start */.Z.start());
    case 'LocalDataCollection.saveCacheData':
      sendResponse({});
      return localdatacollection/* default.saveCacheData */.Z.saveCacheData();
    case 'LocalDataCollection.easyPrivacyURL':
      return processMessageResponse(sendResponse, localdatacollection/* default.easyPrivacyURL */.Z.easyPrivacyURL);
    case 'LocalDataCollection.EXT_STATS_KEY':
      return processMessageResponse(sendResponse, localdatacollection/* default.EXT_STATS_KEY */.Z.EXT_STATS_KEY);
    case 'ExcludeFilter.setExcludeFilters':
      excludefilter.setExcludeFilters(message.filters);
      sendResponse({});
      break;
    default:
  }
});

function parseFilter(text) {
  const filterText = text.trim() || null;
  let error = null;

  if (filterText) {
    if (filterText[0] === '[') {
      error = { type: 'unexpected_filter_list_header' };
    } else {
      const filterError = ewe_api.filters.validate(filterText);
      if (filterError) {
        error = (0,types/* toPlainFilterError */.U_)(filterError);
      }
    }
  }

  return [filterText, error];
}

function filtersValidate(text) {
  const filters = [];
  const errors = [];

  const lines = text.split('\n');
  for (let i = 0; i < lines.length; i++) {
    const [filter, error] = parseFilter(lines[i]);

    if (error) {
      error.filter = filter;
      // We don't treat filter headers like invalid filters,
      // instead we simply ignore them and don't show any errors
      // in order to allow pasting complete filter lists.
      // If there are no filters, we do treat it as an invalid filter
      // to inform users about it and to give them a chance to edit it.
      if (error.type === 'unexpected_filter_list_header'
        && lines.length > 1) {
        /* eslint-disable no-continue */
        continue;
      }
      errors.push(error);
    } else if (filter) {
      filters.push(filter);
    }
  }

  return [filters, errors];
}

async function filtersAdd(text, origin) {
  const filters = [];
  const lines = text.split('\n');
  for (let i = 0; i < lines.length; i++) {
    const [filter, error] = parseFilter(lines[i]);

    if (error) {
      return error;
    }

    if (filter) {
      filters.push(filter);
    }
  }
  try {
    await ewe_api.filters.add(filters, (0,bg_functions/* createFilterMetaData */.Yv)(origin));
  } catch (error) {
    return error;
  }
}


/* eslint-disable consistent-return */
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (!isTrustedSender(sender)) {
    return;
  }
  const { command } = message;
  switch (command) {
    case 'filters.validate': {
      const [, validationErrors] = filtersValidate(message.text);
      return processMessageResponse(sendResponse, validationErrors);
    }
    case 'filters.add': {
      sendResponse({});
      return filtersAdd(message.text, message.origin);
    }
    case 'filters.remove':
      ewe_api.filters.remove(message.filters);
      sendResponse({});
      break;
    default:
  }
});


/***/ }),

/***/ 7185:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _alias_storage_session__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4051);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */



const sessionStorageKey = 'ab:CustomFilterRandomName';
const sessionKey = 'ab:randomtext';

const sessionStorage = new _alias_storage_session__WEBPACK_IMPORTED_MODULE_0__/* .SessionStorage */ .x(sessionStorageKey);

/* eslint-disable-next-line no-unused-vars */
class MessageValidator {
  generateNewRandomText = () => {
    this.randomtext = `ab-${Math.random().toString(36).substring(2)}`;
    sessionStorage.set(sessionKey, this.randomtext);
    return this.randomtext;
  };

  validateMessage = async (message) => {
    const data = await sessionStorage.get(sessionKey);
    this.randomtext = data;
    return Promise.resolve(message && (message.addCustomFilterRandomName === this.randomtext));
  };
}
const messageValidator = new MessageValidator();
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (messageValidator);


/***/ }),

/***/ 4983:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2509);
/* harmony import */ var _picreplacement_channels__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5633);
/* harmony import */ var _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3283);
/* harmony import */ var _prefs_background__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1648);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_4__);
/* For ESLint: List any global identifiers used in this file below */
/* global browser, isTrustedSender, openTab,
   processMessageResponse */







/**
 * Process events related to the Premium object - License, Channels, and Sync-Service
 *
 */
const uiPorts = new Map();
const messageTypes = new Map([
  ['license', 'license.respond'],
  ['channels', 'channels.respond'],
  ['sync', 'sync.respond'],
]);


function sendMessage(type, action, ...args) {
  if (uiPorts.size === 0) {
    return;
  }
  for (const [uiPort, filters] of uiPorts) {
    const actions = filters.get(type);
    if (actions && actions.indexOf(action) !== -1) {
      uiPort.postMessage({
        type: messageTypes.get(type),
        action,
        args,
      });
    }
  }
}

function getListener(type, action) {
  return (...args) => {
    sendMessage(type, action, ...args);
  };
}

function listen(type, filters, newFilter) {
  switch (type) {
    case 'license':
      filters.set('license', newFilter);
      break;
    case 'channels':
      filters.set('channels', newFilter);
      break;
    case 'sync':
      filters.set('sync', newFilter);
      break;
    default:
    // do nothing
  }
}

function onConnect(uiPort) {
  if (!isTrustedSender(uiPort.sender)) {
    return;
  }

  if (uiPort.name !== 'premium') {
    return;
  }

  const filters = new Map();
  uiPorts.set(uiPort, filters);

  uiPort.onDisconnect.addListener(() => {
    uiPorts.delete(uiPort);
  });

  uiPort.onMessage.addListener((message) => {
    const [type, action] = message.type.split('.', 2);
    if (action === 'listen') {
      listen(type, filters, message.filter, message,
        uiPort.sender && uiPort.sender.tab && uiPort.sender.tab.id);
    }
  });
}
browser.runtime.onConnect.addListener(onConnect);

const injectScript = async function (scriptFileName, tabId, frameId) {
  try {
    if (browser.scripting) {
      await browser.scripting.executeScript({
        target: { tabId, frameIds: [frameId] },
        files: [scriptFileName],
      });
    } else {
      await browser.tabs.executeScript(tabId, { file: scriptFileName, frameId, runAt: 'document_start' });
    }
  } catch (error) {
    /* eslint-disable-next-line no-console */
    console.error(error);
  }
};

/**
 * Process complex messages related to the 'License' object
 *
 */
_picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.ready */ .Cz.ready().then(() => {
  browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.message === 'load_my_adblock') {
      if (
        sender.url && sender.url.startsWith('http')
        && _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense()
        && (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().picreplacement
      ) {
        void injectScript('adblock-picreplacement.js', sender.tab.id, sender.frameId);
      }
      if (
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense()
        && sender.url
        && sender.url.startsWith('http')
        && _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_4__.subscriptions.has('https://cdn.adblockcdn.com/filters/distraction-control.txt')
        && _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_4__.filters.getAllowingFilters(sender.tab.id).length === 0
      ) {
        void injectScript('adblock-picreplacement-push-notification-wrapper-cs.js', sender.tab.id, sender.frameId);
      }
      sendResponse({});
    }
  });

  /**
   * Process general messages related to the 'License' object
   *
   */
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (!isTrustedSender(sender)) {
      return;
    }
    const { command } = message;
    switch (command) {
      case 'setBlacklistCTAStatus':
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.shouldShowBlacklistCTA */ .Cz.shouldShowBlacklistCTA(message.isEnabled);
        sendResponse({});
        break;
      case 'setWhitelistCTAStatus':
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.shouldShowWhitelistCTA */ .Cz.shouldShowWhitelistCTA(message.isEnabled);
        sendResponse({});
        break;
      case 'cleanUpSevenDayAlarm':
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.cleanUpSevenDayAlarm */ .Cz.cleanUpSevenDayAlarm();
        sendResponse({});
        break;
      case 'updatePeriodically':
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.updatePeriodically */ .Cz.updatePeriodically();
        sendResponse({});
        break;
      case 'isActiveLicense':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense());
      case 'shouldShowMyAdBlockEnrollment':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.shouldShowMyAdBlockEnrollment */ .Cz.shouldShowMyAdBlockEnrollment());
      default:
    }
  });

  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    const { command } = message;
    switch (command) {
      case 'openPremiumPayURL':
        openTab(_picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.MAB_CONFIG.payURL */ .Cz.MAB_CONFIG.payURL);
        sendResponse({});
        break;
      case 'payment_success':
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.activate */ .Cz.activate();
        sendResponse({ ack: true });
        break;
      default:
    }
  });

  /**
   * Process the message related to getting the 'License' object
   *
   */
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((request, sender, sendResponse) => {
    if (request.command === 'getLicenseConfig') {
      sendResponse({});
      const response = {
        getFormattedActiveSinceDate: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.getFormattedActiveSinceDate */ .Cz.getFormattedActiveSinceDate(),
        MAB_CONFIG: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.MAB_CONFIG */ .Cz.MAB_CONFIG,
        shouldShowMyAdBlockEnrollment: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.shouldShowMyAdBlockEnrollment */ .Cz.shouldShowMyAdBlockEnrollment(),
        shouldShowPremiumCTA: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.shouldShowPremiumCTA */ .Cz.shouldShowPremiumCTA(),
        isActiveLicense: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense(),
        isLicenseCodeValid: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isLicenseCodeValid */ .Cz.isLicenseCodeValid(),
        pageReloadedOnSettingChangeKey: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.pageReloadedOnSettingChangeKey */ .Cz.pageReloadedOnSettingChangeKey,
        userClosedSyncCTAKey: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.userClosedSyncCTAKey */ .Cz.userClosedSyncCTAKey,
        userSawSyncCTAKey: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.userSawSyncCTAKey */ .Cz.userSawSyncCTAKey,
        themesForCTA: _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.userSawSyncCTAKey */ .Cz.userSawSyncCTAKey,
      };
      Object.assign(response, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.get */ .Cz.get());
      return Promise.resolve(response);
    }
  });

  /**
   * Process the messages related to Channels object
   *
   */
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (!isTrustedSender(sender)) {
      return;
    }
    const { command } = message;
    switch (command) {
      case 'channels.getGuide':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.getGuide */ .ZW.getGuide());
      case 'channels.isAnyEnabled':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.isAnyEnabled */ .ZW.isAnyEnabled());
      case 'channels.isCustomChannelEnabled':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.isCustomChannelEnabled */ .ZW.isCustomChannelEnabled());
      case 'channels.initializeListeners':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.initializeListeners */ .ZW.initializeListeners());
      case 'channels.setEnabled':
        return processMessageResponse(sendResponse,
          _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.setEnabled */ .ZW.setEnabled(message.channelId, message.enabled));
      case 'channels.getIdByName':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.getIdByName */ .ZW.getIdByName(message.name));
      case 'channels.disableAllChannels':
        return processMessageResponse(sendResponse, _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.disableAllChannels */ .ZW.disableAllChannels());
      default:
    }
  });

  /**
   * Process the `getrandomlisting` &
   * 'channels.recordOneAdReplaced' message from the Image Swap content script
   *
   */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.command === 'channels.getrandomlisting') {
      if (!!_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_4__.filters.getAllowingFilters(sender.tab.id).length || !_picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense()) {
        sendResponse({ disabledOnPage: true });
        return;
      }
      const result = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.randomListing */ .ZW.randomListing(message.opts);
      if (result) {
        sendResponse(result);
        return;
      }
      sendResponse({ disabledOnPage: true });
    } else if (message.command === 'channels.recordOneAdReplaced') {
      sendResponse({});
      if (_picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense()) {
        _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .replacedCounts.recordOneAdReplaced */ .lg.recordOneAdReplaced(sender.tab.id);
      }
    }
  });

  /**
   * Process the messages related to Custom channel object
   *
   */
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (!isTrustedSender(sender)) {
      return;
    }
    const { command } = message;
    switch (command) {
      case 'customchannel.isMaximumAllowedImages': {
        const customChannelId = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.getIdByName */ .ZW.getIdByName('CustomChannel');
        const customChannel = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.channelGuide */ .ZW.channelGuide[customChannelId].channel;
        return processMessageResponse(sendResponse, customChannel.isMaximumAllowedImages());
      }
      case 'customchannel.getListings': {
        const customChannelId = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.getIdByName */ .ZW.getIdByName('CustomChannel');
        const customChannel = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.channelGuide */ .ZW.channelGuide[customChannelId].channel;
        return processMessageResponse(sendResponse, customChannel.getListings());
      }
      case 'customchannel.addCustomImage': {
        const customChannelId = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.getIdByName */ .ZW.getIdByName('CustomChannel');
        const customChannel = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.channelGuide */ .ZW.channelGuide[customChannelId].channel;
        return processMessageResponse(sendResponse,
          customChannel.addCustomImage(message.imageInfo));
      }
      case 'customchannel.removeListingByURL': {
        const customChannelId = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.getIdByName */ .ZW.getIdByName('CustomChannel');
        const customChannel = _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .channels.channelGuide */ .ZW.channelGuide[customChannelId].channel;
        return processMessageResponse(sendResponse,
          customChannel.removeListingByURL(message.url));
      }
      default:
    }
  });

  /**
   * Process the messages related to Sync Service object
   *
   */
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (!isTrustedSender(sender)) {
      return;
    }
    const { command } = message;
    switch (command) {
      case 'resetLastGetStatusCode':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].resetLastGetStatusCode();
        sendResponse({});
        break;
      case 'resetLastGetErrorResponse':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].resetLastGetErrorResponse();
        sendResponse({});
        break;
      case 'resetLastPostStatusCode':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].resetLastPostStatusCode();
        sendResponse({});
        break;
      case 'resetAllSyncErrors':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].resetAllSyncErrors();
        sendResponse({});
        break;
      case 'SyncService.enableSync':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].enableSync(message.initialGet);
        sendResponse({});
        break;
      case 'SyncService.disableSync':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].disableSync(message.removeName);
        sendResponse({});
        break;
      case 'SyncService.getLastPostStatusCode':
        return processMessageResponse(sendResponse, _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].getLastPostStatusCode());
      case 'SyncService.getLastGetStatusCode':
        return processMessageResponse(sendResponse, _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].getLastGetStatusCode());
      case 'SyncService.getAllExtensionNames':
        return processMessageResponse(sendResponse, _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].getAllExtensionNames());
      case 'SyncService.getCurrentExtensionName':
        return processMessageResponse(sendResponse, _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].getCurrentExtensionName());
      case 'SyncService.processUserSyncRequest':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].processUserSyncRequest();
        sendResponse({});
        break;
      case 'SyncService.removeExtensionName':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].removeExtensionName(message.dataDeviceName, message.dataExtensionGUID);
        sendResponse({});
        break;
      case 'SyncService.setCurrentExtensionName':
        _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].setCurrentExtensionName(message.name);
        sendResponse({});
        break;
      default:
    }
  });

  _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.licenseNotifier.on */ .Cz.licenseNotifier.on('license.updating', getListener('license', 'updating'));
  _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.licenseNotifier.on */ .Cz.licenseNotifier.on('license.updated', getListener('license', 'updated'));
  _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.licenseNotifier.on */ .Cz.licenseNotifier.on('license.updated.error', getListener('license', 'updated.error'));
  _picreplacement_check__WEBPACK_IMPORTED_MODULE_0__/* .License.licenseNotifier.on */ .Cz.licenseNotifier.on('license.expired', getListener('license', 'expired'));

  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('sync.data.receieved', getListener('sync', 'sync.data.receieved'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('sync.data.getting', getListener('sync', 'sync.data.getting'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('sync.data.error.initial.fail', getListener('sync', 'sync.data.error.initial.fail'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('sync.data.getting.error', getListener('sync', 'sync.data.getting.error'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.names.downloading', getListener('sync', 'extension.names.downloading'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.names.downloaded', getListener('sync', 'extension.names.downloaded'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.names.downloading.error', getListener('sync', 'extension.names.ownloading.error'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.name.updating', getListener('sync', 'extension.name.updating'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.name.updated', getListener('sync', 'extension.name.updated'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.name.updated.error', getListener('sync', 'extension.name.updated.error'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.name.remove', getListener('sync', 'extension.name.remove'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.name.removed', getListener('sync', 'extension.name.removed'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('extension.name.remove.error', getListener('sync', 'extension.name.remove.error'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('post.data.sending', getListener('sync', 'post.data.sending'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('post.data.sent', getListener('sync', 'post.data.sent'));
  _picreplacement_sync_service__WEBPACK_IMPORTED_MODULE_2__["default"].syncNotifier.on('post.data.sent.error', getListener('sync', 'post.data.sent.error'));

  _picreplacement_channels__WEBPACK_IMPORTED_MODULE_1__/* .channelsNotifier.on */ .l.on('channels.changed', getListener('channels', 'changed'));
});


/***/ }),

/***/ 3473:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var prefs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4428);
/* harmony import */ var _telemetry_background__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5441);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* global browser */
/* eslint-disable import/prefer-default-export */





/**
 * The domain where pages are hosted on.
 */
const pageDomain = 'https://getadblock.com';

/**
 * A map of relative paths for pages.
 */
const pagePath = {
  installed: '/installed/',
};

/**
 * Opens a page in a new tab.
 *
 * @param {string} path The relative path to the page to open
 * @param {object} [queryParams] Optional query params to attach
 */
function openPage(path, queryParams) {
  let url = `${pageDomain}${path}`;
  if (queryParams) {
    url = `${url}?${new URLSearchParams(queryParams).toString()}`;
  }
  browser.tabs.create({ url });
}

/**
 * Opens the '/installed' page in a new tab.
 */
function openInstalledPage() {
  _telemetry_background__WEBPACK_IMPORTED_MODULE_1__/* .TELEMETRY.untilLoaded */ .C.untilLoaded((userID) => {
    openPage(pagePath.installed, {
      u: userID,
      lg: browser.i18n.getUILanguage(),
    });
  });
}

/**
 * Initializes the notifications module.
 */
function start() {
  browser.runtime.onInstalled.addListener(async (details) => {
    await prefs__WEBPACK_IMPORTED_MODULE_0__/* .Prefs.untilLoaded */ .B.untilLoaded;
    if (details.reason === 'install' && !prefs__WEBPACK_IMPORTED_MODULE_0__/* .Prefs.suppress_first_run_page */ .B.suppress_first_run_page) {
      openInstalledPage();
    }
  });
}

start();


/***/ }),

/***/ 4214:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _check__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(2509);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, log */



/**
 * Algorithm used to verify authenticity of sender
 */
const algorithm = {
  name: 'RSASSA-PKCS1-v1_5',
  modulusLength: 4096,
  publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
  hash: { name: 'SHA-512' },
};
/**
 * Time (in milliseconds) from now for which we consider signatures to be valid
 * based on their associated timestamps
 */
const signatureExpiration = 60 * 60 * 1000;

/**
 * Converts base64 string into array buffer
 *
 * @param {string} str - base64 string
 *
 * @returns {Uint8Array} array buffer
 */
function base64ToArrayBuffer(str) {
  const decodedData = atob(str);
  return Uint8Array.from(decodedData, c => c.charCodeAt(0));
}

/**
 * Encodes request data to sign for verifying authenticity of sender
 *
 * @param {string} domain - Sender domain
 * @param {number} timestamp - Timestamp of current date and time
 *
 * @returns {Uint8Array} Encoded request data
 */
function getAllowData(domain, timestamp) {
  const str = `${domain},${timestamp}`;
  return new TextEncoder().encode(str);
}

/**
 * Generates public key from string for verifying signatures
 *
 * @param {string} key - public key string
 *
 * @returns {Promise<CryptoKey>} public key
 */
async function getKey(key) {
  const abKey = base64ToArrayBuffer(key);
  const importedKey = await crypto.subtle.importKey(
    'spki',
    abKey,
    algorithm,
    false,
    ['verify'],
  );
  return importedKey;
}

/**
 * Handles incoming "users.isPaying" messages
 *
 * @param {Object} message - "users.isPaying" message
 * @param {Object} sender - Message sender
 *
 * @returns {Promise<string|null>} requested payload
 */
async function handleUsersIsPayingMessage(message, sender) {
  // Check Premium state
  if (!_check__WEBPACK_IMPORTED_MODULE_0__/* .License.isActiveLicense */ .Cz.isActiveLicense()) {
    log('user not active');
    return null;
  }

  // Verify timestamp
  const { signature, timestamp } = message;
  /* eslint-disable-next-line no-use-before-define */
  const validTimestamp = verifyTimestamp(timestamp);
  if (!validTimestamp) {
    log('invalid Timestamp', timestamp);
    return null;
  }

  // Verify signature
  const domain = new URL(sender.url).hostname;
  /* eslint-disable-next-line no-use-before-define */
  const validSignature = await verifySignature(domain, timestamp, signature);
  if (!validSignature) {
    log('invalid signature');
    return null;
  }

  // Retrieve payload
  const payload = _check__WEBPACK_IMPORTED_MODULE_0__/* .License.getBypassPayload */ .Cz.getBypassPayload();
  if (!payload) {
    log('no bypass mode payload');
    return null;
  }

  return payload;
}

/**
 * Checks whether signature matches data and any of the known public keys
 * that are authorized to use the bypass API
 *
 * @param {string} domain - Sender domain
 * @param {number} timestamp - Timestamp of current date and time
 * @param {string} signature - Signature for provided domain and timestamp
 *
 * @returns {Promise<boolean>} whether signature matches data and any authorized public key
 */
async function verifySignature(domain, timestamp, signature) {
  if (typeof signature !== 'string') {
    return false;
  }

  const data = getAllowData(domain, timestamp);
  const abSignature = base64ToArrayBuffer(signature);

  const promisedValidations = _check__WEBPACK_IMPORTED_MODULE_0__/* .License.MAB_CONFIG.bypassAuthorizedKeys.map */ .Cz.MAB_CONFIG.bypassAuthorizedKeys.map(
    /* eslint-disable-next-line no-use-before-define */
    key => verifySignatureWithKey(data, abSignature, key),
  );
  const validations = await Promise.all(promisedValidations);
  return validations.some(isValid => isValid);
}

/**
 * Checks whether signature matches data and public key
 *
 * @param {Uint8Array} data - Encoded data
 * @param {Uint8Array} signature - Signature for encoded data
 * @param {string} pubKey - Public key
 *
 * @returns {Promise<boolean>} whether signature matches data and public key
 */
async function verifySignatureWithKey(data, signature, pubKey) {
  return crypto.subtle.verify(
    algorithm,
    await getKey(pubKey),
    signature,
    data,
  );
}

/**
 * Checks whether timestamp is valid
 *
 * @param {number} timestamp - Timestamp
 *
 * @returns {boolean} whether timestamp is valid
 */
function verifyTimestamp(timestamp) {
  if (typeof timestamp !== 'number' || Number.isNaN(timestamp)) {
    log('timestamp is not number', timestamp);
    return false;
  }

  const timeDiff = Date.now() - timestamp;
  return timeDiff < signatureExpiration;
}

/**
 * Initializes module
 */
function start() {
  /* eslint-disable consistent-return */
  browser.runtime.onMessage.addListener((message, sender) => {
    if (message.command !== 'users.isPaying') {
      return;
    }

    return handleUsersIsPayingMessage(message, sender);
  });
  /* eslint-enable consistent-return */
}

start();


/***/ }),

/***/ 5633:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "E": () => (/* binding */ Channels),
  "l": () => (/* binding */ channelsNotifier)
});

// EXTERNAL MODULE: ./node_modules/adblockpluscore/lib/contentTypes.js
var contentTypes = __webpack_require__(3194);
// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/events.js
var events = __webpack_require__(9876);
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/image-sizes-map.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

const imageSizesMap = new Map([
  ['NONE', 0],
  ['wide', 1],
  ['tall', 2],
  ['skinnywide', 4],
  ['skinnytall', 8],
  ['big', 16],
  ['small', 32],
]);


const WIDE = imageSizesMap.get('wide');
const TALL = imageSizesMap.get('tall');
const BIG = imageSizesMap.get('big');
const SMALL = imageSizesMap.get('small');
const SKINNYWIDE = imageSizesMap.get('skinnywide');
const SKINNYTALL = imageSizesMap.get('skinnytall');

// EXTERNAL MODULE: ./adblock-betafish/subscriptionadapter.js + 1 modules
var subscriptionadapter = __webpack_require__(1974);
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/listing.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */


// Inputs: width:int, height:int, url:url, title:string, attributionUrl:url
class Listing {
  constructor(data) {
    this.width = data.width;
    this.height = data.height;
    this.url = data.url;
    this.title = data.title;
    this.attributionUrl = data.attributionUrl;
    this.channelName = data.channelName;
    if (data.name) {
      this.name = data.name;
    }
    if (data.thumbURL) {
      this.thumbURL = data.thumbURL;
    }
    if (data.userLink) {
      this.userLink = data.userLink;
    }
    if (data.anySize) {
      this.anySize = data.anySize;
    }
    if (data.type) {
      this.type = data.type;
    }
    if (data.ratio) {
      this.ratio = data.ratio;
    }
    if (data.customImage) {
      this.customImage = data.customImage;
    }
  }
}
/* harmony default export */ const listing = (Listing);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */




// Base class representing a channel of photos.
// Concrete constructors must accept a single argument, because Channels.add()
// relies on that.
class Channel {
  constructor() {
    this.listings = [];
  }

  getListings() {
    return this.listings.slice(0); // shallow copy
  }

  static listingFactory(widthParam, heightParam, url, title, channelName) {
    let width = widthParam;
    let height = heightParam;
    const type = Channel.calculateType(width, height);

    if (typeof width === 'number') {
      width = `${width}`;
    }
    if (typeof height === 'number') {
      height = `${height}`;
    }
    return new listing({
      width,
      height,
      url,
      attributionUrl: url,
      type,
      ratio: Math.max(width, height) / Math.min(width, height),
      title,
      channelName, // message.json key for channel name
    });
  }

  // Update the channel's listings and trigger an 'updated' event.
  refresh() {
    const that = this;
    this.getLatestListings((listings) => {
      that.listings = listings;
    });
  }

  // Load all photos so that they're in the cache.
  static prefetch() {
    // current - noop, since all of the URLs are hard coded.
  }

  static getLatestListings() {
    throw new Error('Implemented by subclass. Call callback with up-to-date listings.');
  }

  static calculateType(w, h) {
    let width = w;
    let height = h;

    if (typeof width === 'string') {
      width = parseInt(width, 10);
    }
    if (typeof height === 'string') {
      height = parseInt(height, 10);
    }
    let type = '';
    const ratio = Math.max(width, height) / Math.min(width, height);
    if (ratio >= 1.5 && ratio < 7) {
      type = (width > height ? imageSizesMap.get('wide') : imageSizesMap.get('tall'));
    } else if (ratio > 7) {
      type = (width > height ? imageSizesMap.get('skinnywide') : imageSizesMap.get('skinnytall'));
    } else {
      type = ((width > 125 || height > 125) ? imageSizesMap.get('big') : imageSizesMap.get('small'));
    }
    return type;
  }
}
/* harmony default export */ const channel = (Channel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/custom-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser */

// Channel containing user imported images
// Subclass of Channel.




class CustomChannel extends channel {
  constructor() {
    super();
    this.listings = [];
    this.CUSTOM_META_KEY = 'customMetaData';
    const that = this;

    // load the meta data Array from storage
    browser.storage.local.get(this.CUSTOM_META_KEY).then((customImageMetaData) => {
      const savedCustomImageMetaData = customImageMetaData;
      if (!savedCustomImageMetaData[this.CUSTOM_META_KEY]) {
        savedCustomImageMetaData[this.CUSTOM_META_KEY] = [];
      }
      const customMetaData = savedCustomImageMetaData[this.CUSTOM_META_KEY];
      for (let inx = 0; inx < customMetaData.length; inx++) {
        const listingData = customMetaData[inx];
        if (
          listingData
          && listingData.url
          && listingData.width
          && listingData.height
          && listingData.title
        ) {
          const theNewListing = CustomChannel.createListing(listingData.width,
            listingData.height, listingData.url, listingData.title);
          that.listings.push(theNewListing);
        }
      }
    });
  }

  static createListing(theWidth, theHeight, theURL, theName) {
    let width = theWidth;
    let height = theHeight;
    const url = theURL;
    const type = channel.calculateType(width, height);

    if (typeof width === 'number') {
      width = `${width}`;
    }
    if (typeof height === 'number') {
      height = `${height}`;
    }
    return new listing({
      width,
      height,
      url,
      attributionUrl: url,
      type,
      ratio: Math.max(width, height) / Math.min(width, height),
      title: `This is an image from your PC! : ${theName}`,
      channelName: 'custom_channel_name', // message.json key for channel name
      customImage: true,
    });
  }

  // to run - channels.channelGuide[channels.getIdByName("CustomChannel")].channel.deleteAll()
  deleteAll() {
    const customImagesArray = this.listings;
    for (let inx = 0; inx < customImagesArray.length; inx++) {
      if (customImagesArray[inx] && customImagesArray[inx].url) {
        browser.storage.local.remove(customImagesArray[inx].url);
      }
    }
    browser.storage.local.remove(this.CUSTOM_META_KEY).then(() => {
      this.listings = [];
    });
  }

  getLatestListings(callback) {
    callback(this.listings);
  }

  isMaximumAllowedImages() {
    return (this.listings.length >= 9);
  }

  saveListings() {
    const that = this;
    return new Promise((resolve, reject) => {
      const persistedMetaImageObj = {};
      persistedMetaImageObj[that.CUSTOM_META_KEY] = that.listings;
      browser.storage.local.set(persistedMetaImageObj).then(() => {
        if (browser.runtime.lastError) {
          reject(browser.runtime.lastError);
        }
        resolve(true);
      });
    });
  }

  removeListingByURL(theURLToRemove) {
    for (let inx = 0; inx < this.listings.length; inx++) {
      const theListing = this.listings[inx];
      if (theListing && theListing.url === theURLToRemove) {
        this.listings.splice(inx, 1);
      }
    }
    const that = this;
    return new Promise((resolve, reject) => {
      that.saveListings().then((response) => {
        if (response) {
          browser.storage.local.remove(theURLToRemove).then(() => {
            if (browser.runtime.lastError) {
              reject(browser.runtime.lastError);
            }
            resolve(true);
          });
        } else {
          resolve(response);
        }
      });
    });
  }

  async addCustomImage(imageInfo) {
    const theNewListing = CustomChannel.createListing(imageInfo.width,
      imageInfo.height, imageInfo.listingURL, imageInfo.name);
    this.listings.push(theNewListing);
    const response = await this.saveListings().catch(() => Promise.reject());
    if (response) {
      return Promise.resolve(imageInfo.listingURL);
    }
    return Promise.reject();
  }

  getBytesInUseForEachImage() {
    if (typeof browser.storage.local.getBytesInUse !== 'function') {
      return Promise.resolve(0);
    }
    const customImagesArray = this.getListings();
    const promises = [];
    for (let inx = 0; inx < customImagesArray.length; inx++) {
      const thePromise = new Promise((resolve) => {
        if (customImagesArray[inx] && customImagesArray[inx].url) {
          browser.storage.local.getBytesInUse(customImagesArray[inx].url).then((biu) => {
            resolve(biu);
          });
        }
      });
      promises.push(thePromise);
    }
    return Promise.all(promises);
  }

  getTotalBytesInUse() {
    if (typeof browser.storage.local.getBytesInUse !== 'function') {
      return Promise.resolve(0);
    }
    return new Promise((resolve) => {
      this.getBytesInUseForEachImage().then((results) => {
        let sum = 0;
        let numResults = results.length;
        while (numResults > 0) {
          numResults -= 1;
          sum += results[numResults];
        }
        resolve(sum);
      });
    });
  }
}
/* harmony default export */ const custom_channel = (CustomChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/cats.json
const cats_namespaceObject = JSON.parse('[{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/12--x628/cat-7784.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/12--x628/cat-animal-animal-portrait-pet.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/12--x628/cat-feline-cute-domestic.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/12--x628/cat-kitten-rozkosne-little.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/12--x628/domestic-cat-cat-adidas-relaxed.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/12--x628/eyes-cats-cat-couch.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/24--x1256/cat-7784.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/24--x1256/cat-animal-animal-portrait-pet.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/24--x1256/cat-feline-cute-domestic.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/24--x1256/cat-kitten-rozkosne-little.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/24--x1256/domestic-cat-cat-adidas-relaxed.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x628/24--x1256/eyes-cats-cat-couch.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-7784.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-82072.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-animal-animal-portrait-pet.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-animal-cute-pet-39500.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-balcony-surprised-look-80363.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-british-shorthair-mieze-blue-eye-162174.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-british-shorthair-thoroughbred-adidas-162064.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-close-animal-cat-face-162309.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-eyes-view-face-66292.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-feline-cute-domestic.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-feline-furry-pet-53446.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-feline-kitty-kitten-39380.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-home-animal-cat-s-eyes-46208.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-kitten-rozkosne-little.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-pet-eyes-animal-50566.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-pet-furry-face-162319.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-portrait-eyes-animal-162216.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-portrait-kitten-cute-128884.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-relax-chill-out-camacho-70844.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-tiger-getiegert-feel-at-home-160722.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/domestic-cat-cat-adidas-relaxed.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/eyes-cats-cat-couch.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-105587.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-106131.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-116835.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-135859.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-142615.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-171216.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-172420.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-173909.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-192384.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-207166.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208845.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208860.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208878.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208880.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208906.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208907.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208954.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208971.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-208998.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-209117.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-209800.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-210081.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-214657.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-220826.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-220876.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-220951.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-220970.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-220983.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-236630.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-236633.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-244848.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-247007.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-248254.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-248289.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-248304.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-257423.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-271889.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-272124.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-289345.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-289381.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-290263.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-327014.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-349388.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-372651.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-372657.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-416088.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-416138.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-416208.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-437886.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-461872.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-549237.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-576802.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-583250.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-596590.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-599492.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-605048.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-622549.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-65536.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-674568.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-674577 (1).jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-674577.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-679855.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-680437.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-683205.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-689042.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-709482.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-720684.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-731553.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-731637.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-733105.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-736528.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-745241.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-749212.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-751050.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-89951.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-92174.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-94434.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-95328.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-close-animal-cat-face-1623-9.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/cat-feline-kitty-kitten-3938-.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-1-5587.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-17242-.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-1739-9.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-2-886-.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-2-8878.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-58325-.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-6832-5.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-7-9482.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/3--x25-/pexels-photo-751-5-.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-7784.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-82072.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-animal-animal-portrait-pet.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-animal-cute-pet-39500.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-balcony-surprised-look-80363.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-british-shorthair-mieze-blue-eye-162174.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-british-shorthair-thoroughbred-adidas-162064.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-close-animal-cat-face-162309.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-eyes-view-face-66292.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-feline-cute-domestic.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-feline-furry-pet-53446.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-feline-kitty-kitten-39380.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-home-animal-cat-s-eyes-46208.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-kitten-rozkosne-little.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-pet-eyes-animal-50566.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-pet-furry-face-162319.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-portrait-eyes-animal-162216.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-portrait-kitten-cute-128884.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-relax-chill-out-camacho-70844.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/cat-tiger-getiegert-feel-at-home-160722.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/domestic-cat-cat-adidas-relaxed.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/eyes-cats-cat-couch.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-105587.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-106131.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-116835.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-135859.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-142615.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-171216.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-172420.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-173909.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-192384.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-207166.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208845.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208860.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208878.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208880.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208906.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208907.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208954.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208971.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-208998.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-209117.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-209800.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-210081.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-214657.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-220826.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-220876.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-220951.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-220970.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-220983.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-236630.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-236633.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-244848.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-247007.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-248254.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-248289.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-248304.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-257423.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-271889.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-272124.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-289345.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-289381.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-290263.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-327014.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-349388.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-372651.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-372657.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-416088.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-416138.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-416208.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-437886.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-461872.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-549237.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-576802.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-583250.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-596590.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-599492.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-605048.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-622549.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-65536.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-674568.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-674577 (1).jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-674577.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-679855.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-680437.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-683205.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-689042.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-709482.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-720684.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-731553.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-731637.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-733105.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-736528.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-745241.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-749212.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-751050.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-89951.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-92174.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-94434.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-95328.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-1-6131.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-2-89-6.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-2-9117.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-22-983.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-23663-.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-4162-8.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-5768-2.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-68-437.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/6--x5--/pexels-photo-7331-5.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/_6--x5--/pexels-photo-116835.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/_6--x5--/pexels-photo-59659-.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/_6--x5--/pexels-photo-7331-5.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x25-/_6--x5--/pexels-photo-94434.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/3--x6--/cat-7784.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/3--x6--/cat-animal-animal-portrait-pet.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/3--x6--/cat-feline-cute-domestic.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/3--x6--/cat-kitten-rozkosne-little.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/3--x6--/domestic-cat-cat-adidas-relaxed.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/3--x6--/eyes-cats-cat-couch.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/6--x12--/cat-7784.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/6--x12--/cat-animal-animal-portrait-pet.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/6--x12--/cat-feline-cute-domestic.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/6--x12--/cat-kitten-rozkosne-little.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/6--x12--/domestic-cat-cat-adidas-relaxed.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/3--x6--/6--x12--/eyes-cats-cat-couch.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/336x28-/cat-7784.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/336x28-/cat-animal-animal-portrait-pet.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/336x28-/cat-feline-cute-domestic.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/336x28-/cat-kitten-rozkosne-little.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/336x28-/domestic-cat-cat-adidas-relaxed.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/336x28-/eyes-cats-cat-couch.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/672x56-/cat-7784.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/672x56-/cat-animal-animal-portrait-pet.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/672x56-/cat-feline-cute-domestic.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/672x56-/cat-kitten-rozkosne-little.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/672x56-/domestic-cat-cat-adidas-relaxed.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Cats/336x28-/672x56-/eyes-cats-cat-couch.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/cat_468x6-_01.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/cat_468x6-_02.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/cat_468x6-_03.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/cat_468x6-_04.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/cat_468x6-_05.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/-2.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/-3.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/-4.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/-5.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/468x6-/cat_468x6-_-3.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/cat_936x120_01.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/cat_936x120_02.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/cat_936x120_03.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/cat_936x120_04.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/cat_936x120_05.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/cat_936x12-_-1.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Cats/468x6-/936x12-/-4.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_1200x50_01.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_1200x50_02.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_1200x50_03.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_1200x50_04.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_1200x50_05.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/-1.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/-2.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/-3.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_12--x5-_-3.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/12--x5-/cat_12--x5-_-5.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_2400x100_01.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_2400x100_02.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_2400x100_03.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_2400x100_04.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_2400x100_05.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/-1.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/-2.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_24--x1--_-2.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Cats/12--x5-/24--x1--/cat_24--x1--_-4.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/ad_1090x43_01.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/ad_1090x43_02.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/ad_1090x43_03.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/ad_1090x43_04.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/ad_1090x43_05.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/-3.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/-4.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/1-9-x43/ad_1-9-x43_-5.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_2180x86_01.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_2180x86_02.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_2180x86_03.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_2180x86_04.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_2180x86_05.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/-2.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/-3.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/-4.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/-5.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_218-x86_-1.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Cats/1-9-x43/218-x86/cat_218-x86_-3.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/cat_450x62_01.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/cat_450x62_02.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/cat_450x62_03.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/cat_450x62_04.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/cat_450x62_05.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/-1.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/45-x62/-2.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_900x124_01.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_900x124_02.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_900x124_03.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_900x124_04.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_900x124_05.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/-1.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/-2.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/-3.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/-4.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/-5.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_9--x124_-1.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_9--x124_-2.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_9--x124_-3.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_9--x124_-4.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Cats/45-x62/9--x124/cat_9--x124_-5.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/1440x90/cat_1440x90_01.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/1440x90/cat_1440x90_02.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/1440x90/cat_1440x90_03.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/1440x90/cat_1440x90_04.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/1440x90/cat_1440x90_05.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/2880x180/cat_2880x180_01.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/2880x180/cat_2880x180_02.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/2880x180/cat_2880x180_03.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/2880x180/cat_2880x180_04.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/2880x180/cat_2880x180_05.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/-1.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/-4.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/-5.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/cat_144-x9-_-1.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/cat_144-x9-_-2.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/cat_144-x9-_-3.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/cat_144-x9-_-4.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/144-x9-/cat_144-x9-_-5.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/-1.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/-2.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/-3.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/-4.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/-5.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/cat_288-x18-_-1.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/cat_288-x18-_-2.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/cat_288-x18-_-3.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/cat_288-x18-_-4.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/144-x9-/288-x18-/cat_288-x18-_-5.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x180_01.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x180_02.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x180_03.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x180_04.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x180_05.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_01.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_02.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_03.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_04.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_05.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_-3.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_-4.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_-6.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_-7.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_-8.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/1456x18-/cat_1456x18-_1-.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x90_01.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x90_02.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x90_03.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x90_04.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x90_05.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_01.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_02.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_03.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_04.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_05.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_-4.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/728x9-/728x9-/cat_728x9-_-1.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/34-x9-/Cats_34-x9-_01.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/34-x9-/Cats_34-x9-_02.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/34-x9-/Cats_34-x9-_03.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/34-x9-/Cats_34-x9-_04.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/34-x9-/Cats_34-x9-_05.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_01.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_02.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_03.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_04.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_05.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_-1.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_-2.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_-4.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_-5.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_-9.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_1-.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Cats/34-x9-/68-x18-/Cats_68-x18-_11.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/16-x6--/32-x12--/cat-kitten-rozkosne-little.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Cats/16-x6--/32-x12--/cat-7784.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/112-x1344/pexels-photo-437886.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/112-x1344/pexels-photo-2-8845.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/112-x1344/pexels-photo-21--81.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/112-x1344/pexels-photo-22-983.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/56-x672/pexels-photo-22-97-.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/56-x672/pexels-photo-416138.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/56-x672/pexels-photo-59659-.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/56-x672/pexels-photo-731553.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Cats/56-x672/56-x672/pexels-photo-89951.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/cat-7784.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/cat-82-72.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/cat-feline-cute-domestic.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/domestic-cat-cat-adidas-relaxed.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-1-5587.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-1-6131.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-142615.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-17242-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-1739-9.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-8845.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-886-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-888-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-89-6.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-89-7.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-9117.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2-98--.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-22-826.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-22-876.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-22-951.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-22-983.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-244848.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-2483-4.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-416138.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-549237.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-59659-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-599492.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-6-5-48.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-622549.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-674568.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-674577.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-679855.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-689-42.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-7-9482.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-7331-5.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-736528.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-745241.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/18-x68-/pexels-photo-749212.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/cat-7784.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/cat-82-72.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/cat-feline-cute-domestic.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/domestic-cat-cat-adidas-relaxed.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-1-5587.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-1-6131.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-142615.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-17242-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-1739-9.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-8845.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-886-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-888-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-89-6.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-89-7.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-9117.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2-98--.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-22-826.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-22-876.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-22-951.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-22-983.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-244848.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-2483-4.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-416138.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-549237.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-59659-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-599492.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-6-5-48.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-622549.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-674568.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-674577.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-679855.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-689-42.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-7-9482.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-7331-5.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-736528.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-745241.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Cats/18-x68-/36-x136-/pexels-photo-749212.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/cat-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global   */





// Channel containing hard coded cats loaded from disk.
// Subclass of Channel.
class CatsChannel extends channel {
  getLatestListings(callback) {
    for (const cat of cats_namespaceObject) {
      this.listings.push(channel.listingFactory(cat.width, cat.height, cat.url, 'This is a cat!', 'catchannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const cat_channel = (CatsChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/dogs.json
const dogs_namespaceObject = JSON.parse('[{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/animal-dog-golden-retriever-9716.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/animal-dog-pet-brown.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/bordeaux-mastiff-dog-animal.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/dalmatians-dog-animal-head.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/dog-brown-snout-fur.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/dog-cute-pet.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/dog-young-dog-small-dog-maltese.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/nature-animal-dog-pet.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/night-animal-dog-pet.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/night-garden-yellow-animal.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/wall-animal-dog-pet.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/animal-dog-golden-retriever-9716.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/animal-dog-pet-brown.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/bordeaux-mastiff-dog-animal.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/dalmatians-dog-animal-head.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/dog-brown-snout-fur.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/dog-cute-pet.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/dog-young-dog-small-dog-maltese.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/nature-animal-dog-pet.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/night-animal-dog-pet.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/night-garden-yellow-animal.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/wall-animal-dog-pet.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/animal-dog-golden-retriever-9716.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/animal-dog-pet-brown.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/bordeaux-mastiff-dog-animal.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/dalmatians-dog-animal-head.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/dog-brown-snout-fur.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/dog-cute-pet.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/dog-young-dog-small-dog-maltese.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/nature-animal-dog-pet.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/night-animal-dog-pet.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/night-garden-yellow-animal.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/wall-animal-dog-pet.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/animal-dog-golden-retriever-9716.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/animal-dog-pet-brown.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/bordeaux-mastiff-dog-animal.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/dalmatians-dog-animal-head.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/dog-brown-snout-fur.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/dog-cute-pet.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/dog-young-dog-small-dog-maltese.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/nature-animal-dog-pet.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/night-animal-dog-pet.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/night-garden-yellow-animal.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/wall-animal-dog-pet.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/animal-dog-golden-retriever-9716.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/animal-dog-pet-brown.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/bordeaux-mastiff-dog-animal.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/dalmatians-dog-animal-head.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/dog-brown-snout-fur.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/dog-cute-pet.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/dog-young-dog-small-dog-maltese.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/nature-animal-dog-pet.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/night-animal-dog-pet.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/night-garden-yellow-animal.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/wall-animal-dog-pet.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/animal-dog-golden-retriever-9716.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/animal-dog-pet-brown.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/bordeaux-mastiff-dog-animal.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/dalmatians-dog-animal-head.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/dog-brown-snout-fur.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/dog-cute-pet.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/dog-young-dog-small-dog-maltese.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/nature-animal-dog-pet.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/night-animal-dog-pet.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/night-garden-yellow-animal.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/wall-animal-dog-pet.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/animal-dog-golden-retriever-9716.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/animal-dog-pet-brown.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/bordeaux-mastiff-dog-animal.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/dalmatians-dog-animal-head.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/dog-brown-snout-fur.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/dog-cute-pet.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/dog-young-dog-small-dog-maltese.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/nature-animal-dog-pet.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/night-animal-dog-pet.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/night-garden-yellow-animal.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/wall-animal-dog-pet.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/animal-dog-golden-retriever-9716.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/animal-dog-pet-brown.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/bordeaux-mastiff-dog-animal.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/dalmatians-dog-animal-head.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/dog-brown-snout-fur.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/dog-cute-pet.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/dog-young-dog-small-dog-maltese.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/nature-animal-dog-pet.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/night-animal-dog-pet.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/night-garden-yellow-animal.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/wall-animal-dog-pet.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_01.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_02.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_03.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_04.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_05.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/-3.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/-4.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_-2.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/468x6-/dog_468x6-_-4.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x120_01.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x120_02.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x120_03.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x120_04.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x120_05.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/-1.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/-2.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/-3.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/-4.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/-5.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x12-_-1.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x12-_-2.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x12-_-4.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Dogs/468x6-/936x12-/dog_936x12-_-5.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/dog_450x62_01.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/dog_450x62_02.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/dog_450x62_03.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/dog_450x62_04.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/dog_450x62_05.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/-4.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/-5.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/45-x62/dog_45-x62_-1.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_900x124_01.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_900x124_02.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_900x124_03.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_900x124_04.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_900x124_05.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/-1.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/-3.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/-4.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/-5.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_9--x124_-1.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_9--x124_-2.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_9--x124_-3.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_9--x124_-4.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Dogs/45-x62/9--x124/dog_9--x124_-5.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1090x43_01.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1090x43_02.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1090x43_03.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1090x43_04.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1090x43_05.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/-2.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/-3.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1-9-x43_-1.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1-9-x43_-2.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/1-9-x43/dog_1-9-x43_-3.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_2180x86_01.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_2180x86_02.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_2180x86_03.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_2180x86_04.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_2180x86_05.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/-1.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/-2.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/-3.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/-5.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_218-x86_-2.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_218-x86_-3.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Dogs/1-9-x43/218-x86/dog_218-x86_-4.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_1200x50_01.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_1200x50_02.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_1200x50_03.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_1200x50_04.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_1200x50_05.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/-2.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_12--x5-_-2.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/12--x5-/dog_12--x5-_-3.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_2400x100_01.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_2400x100_02.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_2400x100_03.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_2400x100_04.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_2400x100_05.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/-3.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/-4.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_24--x1--_-1.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x5-/24--x1--/dog_24--x1--_-4.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/dog_1440x90_01.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/dog_1440x90_02.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/dog_1440x90_03.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/dog_1440x90_04.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/dog_1440x90_05.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/-5.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/144-x9-/dog_144-x9-_-2.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/dog_2880x180_01.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/dog_2880x180_02.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/dog_2880x180_03.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/dog_2880x180_04.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/dog_2880x180_05.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/-2.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/dog_288-x18-_-5.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/144-x9-/288-x18-/-5.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x180_01.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x180_02.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x180_03.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x180_04.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x180_05.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_01.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_02.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_03.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_04.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_05.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-1.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-2.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-3.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-4.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-5.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-6.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-7.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-8.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_-9.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_1-.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/1456x18-/Dog_1456x18-_11.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x90_01.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x90_02.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x90_03.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x90_04.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x90_05.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_01.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_02.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_03.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_04.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_05.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_-2.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/728x9-/728x9-/Dog_728x9-_-4.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_01.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_02.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_03.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_04.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_05.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_-1.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_-3.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_-4.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_-8.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_-9.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/34-x9-/Dogs_34-x9-_1-.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_01.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_02.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_03.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_04.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_05.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-1.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-2.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-4.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-5.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-6.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-7.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_-9.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_1-.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Dogs/34-x9-/68-x18-/Dogs_68-x18-_11.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/16-x6--/bordeaux-mastiff-dog-animal.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/16-x6--/dog-cute-pet.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/16-x6--/wall-animal-dog-pet.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/32-x12--/animal-dog-pet-brown.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/32-x12--/bordeaux-mastiff-dog-animal.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/32-x12--/dog-young-dog-small-dog-maltese.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/32-x12--/night-garden-yellow-animal.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/56-x672/pexels-photo-97863.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/56-x672/dog-animal-friend-pointer-16226-.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/56-x672/pexels-photo-594687.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/112-x1344/pexels-photo-113883.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/112-x1344/pexels-photo-434-9-.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/112-x1344/pexels-photo-46-186.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Dogs/56-x672/112-x1344/pexels-photo-58997.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/12--x628/pexels-photo-89249.png"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Dogs/12--x628/24--x1256/pexels-photo-89249.png"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/3--x25-/pexels-photo-89249.png"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x25-/6--x5--/pexels-photo-89249.png"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/3--x6--/pexels-photo-89249.png"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Dogs/3--x6--/6--x12--/pexels-photo-89249.png"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/336x28-/pexels-photo-89249.png"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Dogs/336x28-/672x56-/pexels-photo-89249.png"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Dogs/16-x6--/16-x6--/pexels-photo-89249.png"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/bordeaux-mastiff-dog-animal.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dalmatians-dog-animal-head.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dog-bernese-mountain-dog-berner-senner-dog-577-8.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dog-bulldog-white-tongue-4-986.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dog-cavalier-king-charles-spaniel-funny-pet-162193.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dog-hybrid-animal-lying-162349.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dog-young-dog-puppy-59965.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/dog-young-dog-small-dog-maltese.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/english-bulldog-bulldog-canine-dog-4-544.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/french-bulldog-summer-smile-joy-16-846.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/nature-animal-dog-pet.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/papillon-dog-animal-59969.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-13-763.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-134392.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-164446.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-169524.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-2358-5.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-247997.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-25757-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-257577.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-271824.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-356378.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-3749-8.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-412465.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-4162-4.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-452772.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-46-132.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-46-823.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-485294.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-532423.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-58997.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-594687.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-612813.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-61372.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-66687-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-688694.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-71-927.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-72-678.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-752383.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-8--33-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/pexels-photo-9238-.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/tibet-terrier-cute-pet-dog-162276.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/wall-animal-dog-pet.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/weimaraner-puppy-dog-snout-97-82.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/wildlife-photography-pet-photography-dog-animal-159541.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/18-x68-/wildlife-photography-pet-photography-dog-dog-runs-159492.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/bordeaux-mastiff-dog-animal.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dalmatians-dog-animal-head.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dog-bernese-mountain-dog-berner-senner-dog-577-8.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dog-bulldog-white-tongue-4-986.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dog-cavalier-king-charles-spaniel-funny-pet-162193.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dog-hybrid-animal-lying-162349.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dog-young-dog-puppy-59965.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/dog-young-dog-small-dog-maltese.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/english-bulldog-bulldog-canine-dog-4-544.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/french-bulldog-summer-smile-joy-16-846.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/nature-animal-dog-pet.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/papillon-dog-animal-59969.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-13-763.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-134392.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-164446.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-169524.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-2358-5.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-247997.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-25757-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-257577.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-271824.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-356378.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-3749-8.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-412465.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-4162-4.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-452772.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-46-132.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-46-823.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-485294.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-532423.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-58997.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-594687.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-612813.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-61372.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-66687-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-688694.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-71-927.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-72-678.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-752383.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-8--33-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/pexels-photo-9238-.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/tibet-terrier-cute-pet-dog-162276.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/wall-animal-dog-pet.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/weimaraner-puppy-dog-snout-97-82.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/wildlife-photography-pet-photography-dog-animal-159541.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Dogs/18-x68-/36-x136-/wildlife-photography-pet-photography-dog-dog-runs-159492.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/dog-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global */





// Channel containing hard coded dogs loaded from CDN
// Subclass of Channel.
class DogsChannel extends channel {
  getLatestListings(callback) {
    for (const dog of dogs_namespaceObject) {
      this.listings.push(channel.listingFactory(dog.width, dog.height, dog.url, 'This is a dog!', 'dogchannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const dog_channel = (DogsChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/landscapes.json
const landscapes_namespaceObject = JSON.parse('[{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/amazing-animal-beautiful-beautifull.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/amazing-beautiful-beauty-blue.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/antelope-canyon-lower-canyon-arizona.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/delicate-arch-night-stars-landscape.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/italian-landscape-mountains-nature.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/pexels-photo (1).jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/pexels-photo (2).jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/pexels-photo.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/road-sun-rays-path.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/sunrise-phu-quoc-island-ocean.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/sunset-field-poppy-sun-priroda.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/12--x628/switzerland-zermatt-mountains-snow.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/amazing-animal-beautiful-beautifull.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/amazing-beautiful-beauty-blue.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/antelope-canyon-lower-canyon-arizona.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/delicate-arch-night-stars-landscape.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/italian-landscape-mountains-nature.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/pexels-photo (1).jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/pexels-photo (2).jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/pexels-photo.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/road-sun-rays-path.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/sunrise-phu-quoc-island-ocean.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/sunset-field-poppy-sun-priroda.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x628/24--x1256/switzerland-zermatt-mountains-snow.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/amazing-animal-beautiful-beautifull.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/amazing-beautiful-beauty-blue.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/antelope-canyon-lower-canyon-arizona.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/delicate-arch-night-stars-landscape.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/italian-landscape-mountains-nature.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/pexels-photo (1).jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/pexels-photo (2).jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/pexels-photo.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/road-sun-rays-path.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/sunrise-phu-quoc-island-ocean.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/sunset-field-poppy-sun-priroda.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/3--x25-/switzerland-zermatt-mountains-snow.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/amazing-animal-beautiful-beautifull.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/amazing-beautiful-beauty-blue.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/antelope-canyon-lower-canyon-arizona.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/delicate-arch-night-stars-landscape.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/italian-landscape-mountains-nature.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/pexels-photo (1).jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/pexels-photo (2).jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/pexels-photo.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/road-sun-rays-path.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/sunrise-phu-quoc-island-ocean.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/sunset-field-poppy-sun-priroda.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x25-/6--x5--/switzerland-zermatt-mountains-snow.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/amazing-animal-beautiful-beautifull.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/amazing-beautiful-beauty-blue.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/antelope-canyon-lower-canyon-arizona.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/delicate-arch-night-stars-landscape.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/italian-landscape-mountains-nature.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/pexels-photo (1).jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/pexels-photo (2).jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/pexels-photo.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/road-sun-rays-path.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/sunrise-phu-quoc-island-ocean.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/sunset-field-poppy-sun-priroda.jpg"},{"width":300,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/3--x6--/switzerland-zermatt-mountains-snow.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/amazing-animal-beautiful-beautifull.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/amazing-beautiful-beauty-blue.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/antelope-canyon-lower-canyon-arizona.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/delicate-arch-night-stars-landscape.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/italian-landscape-mountains-nature.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/pexels-photo (1).jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/pexels-photo (2).jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/pexels-photo.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/road-sun-rays-path.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/sunrise-phu-quoc-island-ocean.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/sunset-field-poppy-sun-priroda.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/3--x6--/6--x12--/switzerland-zermatt-mountains-snow.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/amazing-animal-beautiful-beautifull.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/amazing-beautiful-beauty-blue.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/antelope-canyon-lower-canyon-arizona.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/delicate-arch-night-stars-landscape.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/italian-landscape-mountains-nature.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/pexels-photo (1).jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/pexels-photo (2).jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/pexels-photo.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/road-sun-rays-path.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/sunrise-phu-quoc-island-ocean.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/sunset-field-poppy-sun-priroda.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/336x28-/switzerland-zermatt-mountains-snow.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/amazing-animal-beautiful-beautifull.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/amazing-beautiful-beauty-blue.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/antelope-canyon-lower-canyon-arizona.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/delicate-arch-night-stars-landscape.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/italian-landscape-mountains-nature.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/pexels-photo (1).jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/pexels-photo (2).jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/pexels-photo.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/road-sun-rays-path.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/sunrise-phu-quoc-island-ocean.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/sunset-field-poppy-sun-priroda.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Landscapes/336x28-/672x56-/switzerland-zermatt-mountains-snow.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/landscape_1090x43_01.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/landscape_1090x43_02.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/landscape_1090x43_03.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/landscape_1090x43_04.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/landscape_1090x43_05.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/-2.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/1-9-x43/landscape_1-9-x43_-2.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_2180x86_01.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_2180x86_02.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_2180x86_03.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_2180x86_04.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_2180x86_05.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_218-x86_-1.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Landscapes/1-9-x43/218-x86/landscape_218-x86_-4.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/landscape_450x62_01.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/landscape_450x62_02.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/landscape_450x62_03.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/landscape_450x62_04.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/landscape_450x62_05.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/-3.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/-4.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/-5.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/45-x62/landscape_45-x62_-5.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_900x124_01.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_900x124_02.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_900x124_03.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_900x124_04.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_900x124_05.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/-1.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/-2.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/-3.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/-4.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/-5.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_9--x124_-2.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_9--x124_-3.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Landscapes/45-x62/9--x124/landscape_9--x124_-4.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_1440x90_01.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_1440x90_02.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_1440x90_03.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_1440x90_04.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_1440x90_05.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/-1.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/-2.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/-3.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/-5.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_144-x9-_-1.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/144-x9-/landscape_144-x9-_-3.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_2880x180_01.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_2880x180_02.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_2880x180_03.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_2880x180_04.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_2880x180_05.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/-3.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_288-x18-_-2.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/144-x9-/288-x18-/landscape_288-x18-_-5.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_1200x50_01.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_1200x50_02.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_1200x50_03.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_1200x50_04.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_1200x50_05.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/-1.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/-2.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/-3.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/-4.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/-5.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_12--x5-_-2.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_12--x5-_-3.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_12--x5-_-4.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_12--x5-_-5.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/12--x5-/landscape_12--x5-_-1.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_2400x100_01.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_2400x100_02.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_2400x100_03.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_2400x100_04.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_2400x100_05.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/-1.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/-2.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/-3.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/-4.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/-5.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_24--x1--_-1.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_24--x1--_-2.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_24--x1--_-3.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_24--x1--_-4.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Landscapes/12--x5-/24--x1--/landscape_24--x1--_-5.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/landscape_468x6-_01.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/landscape_468x6-_02.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/landscape_468x6-_03.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/landscape_468x6-_04.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/landscape_468x6-_05.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/-4.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/468x6-/landscape_468x6-_-4.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/landscape_936x120_01.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/landscape_936x120_02.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/landscape_936x120_03.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/landscape_936x120_04.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/landscape_936x120_05.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/-1.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Landscapes/468x6-/936x12-/landscape_936x12-_-3.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x180_01.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x180_02.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x180_03.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x180_04.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x180_05.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_01.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_02.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_03.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_04.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_05.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_-3.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_-4.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_-7.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_1-.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_11.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_12.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_15.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_17.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/1456x18-/Landscape_1456x18-_-2.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x90_01.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x90_02.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x90_03.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x90_04.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x90_05.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_01.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_02.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_03.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_04.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_05.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_-1.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_-4.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/728x9-/728x9-/Landscape_728x9-_-5.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_01.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_02.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_03.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_04.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_05.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_-2.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_-3.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_-4.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_1-.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/34-x9-/Landscape_34-x9-_11.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_01.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_02.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_03.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_04.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_05.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_-2.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_-3.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_-5.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_-6.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_-8.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_1-.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_11.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_12.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_14.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_15.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_16.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Landscapes/34-x9-/68-x18-/Landscape_68-x18-_17.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/amazing-animal-beautiful-beautifull.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/amazing-beautiful-beauty-blue.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/antelope-canyon-lower-canyon-arizona.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/delicate-arch-night-stars-landscape.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/italian-landscape-mountains-nature.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/pexels-photo (1).jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/pexels-photo (2).jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/road-sun-rays-path.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/sunset-field-poppy-sun-priroda.jpg"},{"width":160,"height":600,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/16-x6--/switzerland-zermatt-mountains-snow.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/amazing-beautiful-beauty-blue.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/antelope-canyon-lower-canyon-arizona.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/italian-landscape-mountains-nature.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/pexels-photo (1).jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/pexels-photo (2).jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/road-sun-rays-path.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/sunrise-phu-quoc-island-ocean.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Landscapes/16-x6--/32-x12--/switzerland-zermatt-mountains-snow.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/18-x68-/pexels-photo-414-83.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/18-x68-/pexels-photo-351448.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/amazing-animal-beautiful-beautifull.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/pexels-photo-164196.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/pexels-photo-189848.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/pexels-photo-21-186.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/pexels-photo-221148.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/pexels-photo-388-65.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Landscapes/18-x68-/36-x136-/pexels-photo-443446.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/112-x1344/pexels-photo-355241.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/112-x1344/pexels-photo-552791.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/112-x1344/switzerland-zermatt-mountains-snow.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/56-x672/boat-house-cottage-waters-lake-65225.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/56-x672/pexels-photo (1).jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/56-x672/pexels-photo-117843.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/56-x672/pexels-photo-221148.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Landscapes/56-x672/56-x672/yellowstone-national-park-sunset-twilight-dusk-158489.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/landscape-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */





// Channel containing hard coded Landscapes loaded from CDN.
// Subclass of Channel.
class LandscapesChannel extends channel {
  getLatestListings(callback) {
    for (const landscape of landscapes_namespaceObject) {
      this.listings.push(channel.listingFactory(landscape.width, landscape.height, landscape.url, 'This is a landscape!', 'landscapechannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const landscape_channel = (LandscapesChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/birds.json
const birds_namespaceObject = JSON.parse('[{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_000.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_001.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_002.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_003.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_004.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_005.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_006.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_007.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_008.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_009.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_010.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_011.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_012.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_013.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_014.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_015.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_016.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_017.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Birds/18-x68-/file_018.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_000.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_001.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_002.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_003.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_004.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_005.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_006.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_007.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_008.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_009.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_010.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_011.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_012.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_013.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_014.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_015.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_016.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_017.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_018.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_019.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_020.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_021.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_022.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_023.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_024.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_025.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_026.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_027.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_028.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_029.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_030.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_031.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_032.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_033.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_034.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_035.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_036.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_037.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_038.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_039.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_040.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_041.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_042.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_043.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_044.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_045.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_046.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_047.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_048.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_049.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_050.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_051.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_052.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_053.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_054.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_055.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_056.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_057.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_058.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_059.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_060.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_061.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_062.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_063.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_064.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_065.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_066.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_067.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_068.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_069.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_070.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_071.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_072.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_073.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_074.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_075.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_076.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_077.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_078.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_079.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_080.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_081.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_082.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_083.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_084.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_085.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_086.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_087.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_088.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_089.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_090.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_091.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_092.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_093.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_094.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_095.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_096.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_097.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/24--x1256/file_098.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_000.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_001.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_002.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_003.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_004.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_005.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_006.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_007.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_008.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_009.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_010.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_011.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_012.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_013.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_014.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_015.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_016.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_017.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_018.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_019.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_020.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_021.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_022.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_023.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_024.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_025.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_026.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_027.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_028.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_029.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_030.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_031.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_032.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_033.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_034.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_035.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_036.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_037.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_038.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_039.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_040.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_041.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_042.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_043.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_044.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_045.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_046.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_047.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_048.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_049.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_050.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_051.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_052.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_053.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_054.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_055.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_056.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_057.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_058.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_059.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_060.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_061.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_062.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_063.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_064.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_065.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_066.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_067.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_068.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_069.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_070.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_071.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_072.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_073.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_074.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_075.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_076.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_077.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_078.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_079.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_080.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_081.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_082.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_083.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_084.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_085.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_086.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_087.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_088.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_089.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_090.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_091.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_092.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_093.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_094.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_095.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_096.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_097.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Birds/3--x25-/file_098.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_000.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_001.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_002.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_003.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_004.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_005.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_006.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_007.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_008.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_009.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_010.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_011.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_012.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_013.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_014.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_015.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_016.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_017.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_018.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_019.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_020.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_021.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_022.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_023.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_024.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_025.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_026.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_027.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_028.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_029.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_030.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_031.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_032.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_033.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_034.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_035.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_036.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_037.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_038.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_039.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_040.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_041.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_042.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_043.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_044.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_045.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_046.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_047.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_048.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_049.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_050.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_051.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_052.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_053.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_054.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_055.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_056.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_057.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_058.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_059.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_060.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_061.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_062.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_063.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_064.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_065.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_066.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_067.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_068.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_069.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_070.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_071.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_072.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_073.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_074.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_075.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_076.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_077.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_078.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_079.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_080.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_081.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_082.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_083.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_084.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_085.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_086.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_087.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_088.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_089.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_090.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_091.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_092.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_093.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_094.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_095.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_096.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_097.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Birds/336x28-/file_098.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_000.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_001.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_002.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_003.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_004.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_005.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_006.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_007.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_008.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_009.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_010.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_011.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_012.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_013.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_014.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_015.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_016.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_017.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_018.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_019.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_020.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_021.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_022.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_023.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Birds/36-x136-/file_024.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_000.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_001.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_002.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_003.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_004.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_005.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_006.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_007.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_008.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_009.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_010.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_011.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_012.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_013.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_014.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_015.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_016.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_017.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_018.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_019.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_020.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_021.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_022.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_023.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_024.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_025.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_026.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_027.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_028.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_029.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_030.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_031.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_032.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_033.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_034.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_035.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_036.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_037.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_038.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_039.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_040.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_041.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_042.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_043.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_044.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_045.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_046.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_047.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_048.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_049.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_050.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_051.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_052.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_053.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_054.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_055.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_056.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_057.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_058.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_059.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_060.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_061.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_062.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_063.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_064.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_065.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_066.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_067.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_068.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_069.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Birds/6--x5--/file_070.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Birds/random/file_000.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Birds/random/file_001.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Birds/random/file_002.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Birds/random/file_003.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Birds/random/file_004.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Birds/random/file_005.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/birds-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */





// Channel containing hard coded birds loaded from disk.
// Subclass of Channel.
class BirdChannel extends channel {
  getLatestListings(callback) {
    for (const bird of birds_namespaceObject) {
      this.listings.push(channel.listingFactory(bird.width, bird.height, bird.url, 'This is a bird!', 'birdchannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const birds_channel = (BirdChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/food.json
const food_namespaceObject = JSON.parse('[{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_000.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_001.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_002.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_003.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_004.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_005.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_006.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_007.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_008.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_009.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_010.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_011.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_012.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_013.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_014.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_015.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_016.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_017.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_018.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_019.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_020.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_021.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_022.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_023.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_024.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_025.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_026.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_027.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_028.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_029.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_030.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_031.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_032.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_033.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_034.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_035.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_036.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_037.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_038.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_039.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_040.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_041.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_042.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_043.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_044.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_045.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_046.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_047.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_048.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_049.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_050.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_051.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_052.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_053.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_054.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_055.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_056.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_057.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_058.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_059.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_060.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_061.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_062.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_063.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_064.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_065.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_066.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_067.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_068.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_069.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_070.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_071.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_072.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_073.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_074.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_075.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_076.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_077.jpg"},{"width":"180","height":" 680","url":"https://cdn.adblockcdn.com/pix/Food/18-x68-/file_078.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_000.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_001.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_002.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_003.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_004.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_005.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_006.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_007.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_008.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_009.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_010.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_011.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_012.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_013.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_014.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_015.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_016.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_017.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_018.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_019.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_020.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_021.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_022.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_023.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_024.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_025.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_026.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_027.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_028.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_029.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_030.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_031.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_032.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_033.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_034.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_035.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_036.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_037.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_038.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_039.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_040.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_041.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_042.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_043.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_044.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_045.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_046.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_047.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_048.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_049.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_050.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_051.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_052.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_053.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_054.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_055.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_056.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_057.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_058.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_059.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_060.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_061.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_062.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_063.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_064.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_065.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_066.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_067.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_068.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_069.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_070.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_071.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_072.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_073.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_074.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_075.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_076.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_077.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_078.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_079.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_080.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_081.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_082.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_083.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_084.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_085.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_086.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_087.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_088.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_089.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_090.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_091.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_092.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_093.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_094.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_095.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_096.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_097.jpg"},{"width":"2400","height":" 1256","url":"https://cdn.adblockcdn.com/pix/Food/24--x1256/file_098.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_000.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_001.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_002.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_003.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_004.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_005.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_006.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_007.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_008.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_009.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_010.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_011.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_012.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_013.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_014.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_015.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_016.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_017.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_018.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_019.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_020.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_021.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_022.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_023.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_024.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_025.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_026.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_027.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_028.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_029.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_030.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_031.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_032.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_033.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_034.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_035.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_036.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_037.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_038.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_039.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_040.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_041.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_042.jpg"},{"width":"300","height":" 250","url":"https://cdn.adblockcdn.com/pix/Food/3--x25-/file_043.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_000.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_001.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_002.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_003.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_004.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_005.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_006.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_007.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_008.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_009.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_010.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_011.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_012.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_013.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_014.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_015.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_016.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_017.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_018.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_019.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_020.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_021.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_022.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_023.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_024.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_025.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_026.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_027.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_028.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_029.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_030.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_031.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_032.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_033.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_034.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_035.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_036.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_037.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_038.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_039.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_040.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_041.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_042.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_043.jpg"},{"width":"336","height":" 280","url":"https://cdn.adblockcdn.com/pix/Food/336x28-/file_044.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_000.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_001.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_002.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_003.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_004.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_005.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_006.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_007.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_008.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_009.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_010.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_011.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_012.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_013.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_014.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_015.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_016.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_017.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_018.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_019.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_020.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_021.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_022.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_023.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_024.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_025.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_026.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_027.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_028.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_029.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_030.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_031.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_032.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_033.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_034.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_035.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_036.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_037.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_038.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_039.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_040.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_041.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_042.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_043.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_044.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_045.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_046.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_047.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_048.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_049.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_050.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_051.jpg"},{"width":"360","height":" 1360","url":"https://cdn.adblockcdn.com/pix/Food/36-x136-/file_052.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_000.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_001.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_002.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_003.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_004.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_005.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_006.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_007.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_008.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_009.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_010.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_011.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_012.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_013.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_014.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_015.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_016.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_017.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_018.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_019.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_020.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_021.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_022.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_023.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_024.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_025.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_026.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_027.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_028.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_029.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_030.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_031.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_032.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_033.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_034.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_035.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_036.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_037.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_038.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_039.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_040.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_041.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_042.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_043.jpg"},{"width":"600","height":" 500","url":"https://cdn.adblockcdn.com/pix/Food/6--x5--/file_044.jpg"},{"width":"1120","height":" 1344","url":"https://cdn.adblockcdn.com/pix/Food/random/112-x1344.jpg"},{"width":"1200","height":" 678","url":"https://cdn.adblockcdn.com/pix/Food/random/12--x678.jpg"},{"width":"320","height":" 1200","url":"https://cdn.adblockcdn.com/pix/Food/random/32-x12--.jpg"},{"width":"570","height":" 672","url":"https://cdn.adblockcdn.com/pix/Food/random/57-x672.jpg"},{"width":"600","height":" 1200","url":"https://cdn.adblockcdn.com/pix/Food/random/6--x12--.jpg"},{"width":"672 560","height":"https://cdn.adblockcdn.com/pix/Food/random/672x56-.jpg","url":""},{"width":"680","height":" 180","url":"https://cdn.adblockcdn.com/pix/Food/random/68-x18-.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/food-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global */





// Channel containing hard coded cats loaded from disk.
// Subclass of Channel.
class FoodChannel extends channel {
  getLatestListings(callback) {
    for (const food of food_namespaceObject) {
      this.listings.push(channel.listingFactory(food.width, food.height, food.url, 'This is food!', 'foodchannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const food_channel = (FoodChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/goats.json
const goats_namespaceObject = JSON.parse('[{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_000.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_001.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_002.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_003.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_004.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_005.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_006.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_007.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_008.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Goats/18-x68-/file_009.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_000.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_001.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_002.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_003.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_004.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_005.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_006.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_007.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_008.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_009.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_010.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_011.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_012.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_013.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_014.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_015.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_016.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_017.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_018.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_019.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_020.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_021.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_022.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_023.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Goats/24--x1256/file_024.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_000.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_001.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_002.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_003.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_004.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_005.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_006.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_007.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_008.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_009.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_010.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_011.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_012.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_013.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_014.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_015.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_016.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_017.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_018.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_019.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_020.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_021.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_022.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_023.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Goats/3--x25-/file_024.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_000.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_001.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_002.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_003.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_004.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_005.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_006.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_007.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_008.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_009.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_010.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_011.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_012.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_013.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_014.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_015.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_016.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_017.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_018.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_019.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_020.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_021.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_022.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_023.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Goats/336x28-/file_024.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_000.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_001.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_002.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_003.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_004.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_005.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_006.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_007.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_008.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Goats/36-x136-/file_009.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_000.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_001.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_002.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_003.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_004.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_005.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_006.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_007.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_008.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_009.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_010.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_011.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_012.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_013.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_014.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_015.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_016.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_017.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_018.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_019.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_020.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_021.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Goats/6--x5--/file_022.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Goats/file_000.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Goats/file_001.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Goats/file_002.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Goats/file_003.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Goats/file_004.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Goats/file_005.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Goats/file_006.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Goats/file_007.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Goats/file_008.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Goats/file_009.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/goat-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */





// Channel containing hard coded cats loaded from disk.
// Subclass of Channel.
class GoatsChannel extends channel {
  getLatestListings(callback) {
    for (const goat of goats_namespaceObject) {
      this.listings.push(channel.listingFactory(goat.width, goat.height, goat.url, 'This is a goat!', 'goatchannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const goat_channel = (GoatsChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/data/ocean.json
const ocean_namespaceObject = JSON.parse('[{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_000.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_001.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_002.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_003.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_004.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_005.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_006.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_007.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_008.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_009.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_010.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_011.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_012.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_013.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_014.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_015.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_016.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_017.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_018.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_019.jpg"},{"width":180,"height":680,"url":"https://cdn.adblockcdn.com/pix/Oceans/18-x68-/file_020.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_000.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_001.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_002.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_003.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_004.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_005.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_006.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_007.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_008.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_009.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_010.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_011.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_012.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_013.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_014.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_015.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_016.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_017.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_018.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_019.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_020.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_021.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_022.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_023.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_024.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_025.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_026.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_027.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_028.jpg"},{"width":2400,"height":1256,"url":"https://cdn.adblockcdn.com/pix/Oceans/24--x1256/file_029.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_000.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_001.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_002.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_003.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_004.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_005.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_006.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_007.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_008.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_009.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_010.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_011.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_012.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_013.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_014.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_015.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_016.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_017.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_018.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_019.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_020.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_021.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_022.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_023.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_024.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_025.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_026.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_027.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_028.jpg"},{"width":300,"height":250,"url":"https://cdn.adblockcdn.com/pix/Oceans/3--x25-/file_029.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_000.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_001.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_002.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_003.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_004.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_005.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_006.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_007.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_008.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_009.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_010.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_011.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_012.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_013.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_014.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_015.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_016.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_017.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_018.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_019.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_020.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_021.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_022.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_023.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_024.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_025.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_026.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_027.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_028.jpg"},{"width":336,"height":280,"url":"https://cdn.adblockcdn.com/pix/Oceans/336x28-/file_029.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_000.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_001.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_002.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_003.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_004.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_005.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_006.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_007.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_008.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_009.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_010.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_011.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_012.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_013.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_014.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_015.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_016.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_017.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_018.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_019.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_020.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_021.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_022.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_023.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_024.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_025.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_026.jpg"},{"width":360,"height":1360,"url":"https://cdn.adblockcdn.com/pix/Oceans/36-x136-/file_027.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_000.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_001.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_002.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_003.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_004.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_005.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_006.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_007.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_008.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_009.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_010.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_011.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_012.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_013.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_014.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_015.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_016.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_017.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_018.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_019.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_020.jpg"},{"width":600,"height":500,"url":"https://cdn.adblockcdn.com/pix/Oceans/6--x5--/file_021.jpg"},{"width":1200,"height":628,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_000.jpg"},{"width":600,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_001.jpg"},{"width":672,"height":560,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_002.jpg"},{"width":468,"height":60,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_003.jpg"},{"width":936,"height":120,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_004.jpg"},{"width":1200,"height":50,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_005.jpg"},{"width":2400,"height":100,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_006.jpg"},{"width":1090,"height":43,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_007.jpg"},{"width":2180,"height":86,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_008.jpg"},{"width":450,"height":62,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_009.jpg"},{"width":900,"height":124,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_010.jpg"},{"width":1440,"height":90,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_011.jpg"},{"width":2880,"height":180,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_012.jpg"},{"width":1456,"height":180,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_013.jpg"},{"width":728,"height":90,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_014.jpg"},{"width":340,"height":90,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_015.jpg"},{"width":680,"height":180,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_016.jpg"},{"width":320,"height":1200,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_017.jpg"},{"width":1120,"height":1344,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_018.jpg"},{"width":560,"height":672,"url":"https://cdn.adblockcdn.com/pix/Oceans/random/file_019.jpg"}]');
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/ocean-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global */





// Channel containing hard coded cats loaded from disk.
// Subclass of Channel.
class OceanChannel extends channel {
  getLatestListings(callback) {
    for (const ocean of ocean_namespaceObject) {
      this.listings.push(channel.listingFactory(ocean.width, ocean.height, ocean.url, 'This is a ocean!', 'oceanchannelswitchlabel'));
    }
    callback(this.listings);
  }
}
/* harmony default export */ const ocean_channel = (OceanChannel);

;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/unknown-channel.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global  */



// Empty Channel
// Subclass of Channel.
//
// Allows the Sync process to create an new named Channel
// when the sync process recieves a request with a unknown channel name
class UnknownChannel extends channel {
  // eslint-disable-next-line class-methods-use-this
  getLatestListings(callback) {
    callback([]);
  }
}
/* harmony default export */ const unknown_channel = (UnknownChannel);

// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/picreplacement/channels.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global settings, getSettings, setSetting, ,
   browser, , , ext */

















const resourceTypes = new Map();
for (const type in contentTypes/* contentTypes */.Tr) {
  resourceTypes.set(type.toLowerCase(), contentTypes/* contentTypes */.Tr[type]);
}
resourceTypes.set('sub_frame', contentTypes/* contentTypes.SUBDOCUMENT */.Tr.SUBDOCUMENT);
resourceTypes.set('beacon', contentTypes/* contentTypes.PING */.Tr.PING);
resourceTypes.set('imageset', contentTypes/* contentTypes.IMAGE */.Tr.IMAGE);
resourceTypes.set('object_subrequest', contentTypes/* contentTypes.OBJECT */.Tr.OBJECT);
resourceTypes.set('main_frame', contentTypes/* contentTypes.DOCUMENT */.Tr.DOCUMENT);

const typeSelectors = new Map([
  [contentTypes/* contentTypes.IMAGE */.Tr.IMAGE, 'img,input'],
  [contentTypes/* contentTypes.MEDIA */.Tr.MEDIA, 'audio,video'],
  [contentTypes/* contentTypes.SUBDOCUMENT */.Tr.SUBDOCUMENT, 'frame,iframe,object,embed'],
  [contentTypes/* contentTypes.OBJECT */.Tr.OBJECT, 'object,embed'],
]);

const REPORTING_OPTIONS = {
  filterType: 'blocking',
  includeElementHiding: false,
};

const channelsKey = 'channels';

const subscription1 = subscriptionadapter/* default.getUrlFromId */.Z.getUrlFromId('antisocial');
const subscription2 = subscriptionadapter/* default.getUrlFromId */.Z.getUrlFromId('annoyances');

const channelObjects = {
  CustomChannel: custom_channel,
  CatsChannel: cat_channel,
  DogsChannel: dog_channel,
  LandscapesChannel: landscape_channel,
  BirdChannel: birds_channel,
  FoodChannel: food_channel,
  GoatsChannel: goat_channel,
  OceanChannel: ocean_channel,
  UnknownChannel: unknown_channel,
};

const channelsNotifier = new events/* EventEmitter */.v();

// Contains and provides access to all the photo channels.
class Channels {
  constructor(license) {
    this.license = license;
    this.channelGuide = undefined; // maps channel ids to channels and metadata
    this.loadFromStorage();
    this.initializeListeners();
  }

  // Inputs:
  //   name:string - a Channel class name.
  //   param:object - the single ctor parameter to the Channel class.
  //   enabled:bool - true if this channel is to be used for pictures.
  // Returns:
  //   id of newly created channel, or undefined if the channel already existed.
  add(data) {
    let Klass = channelObjects[data.name];
    if (!Klass) {
      Klass = channelObjects.UnknownChannel;
    }
    const dataParam = JSON.stringify(data.param);
    for (const id in this.channelGuide) {
      const c = this.channelGuide[id];
      if (c.name === data.name && JSON.stringify(c.param) === dataParam) {
        return undefined;
      }
    }
    const id = Math.floor(Math.random() * Date.now());
    const channel = new Klass(data.param);
    this.channelGuide[id] = {
      name: data.name,
      param: data.param,
      enabled: data.enabled,
      channel,
    };
    this.saveToStorage();
    channel.refresh();
    return id;
  }

  remove(channelId) {
    delete this.channelGuide[channelId];
    this.saveToStorage();
  }

  // Return read-only map from each channel ID to
  // { name, param, enabled }.
  getGuide() {
    const results = {};
    for (const id in this.channelGuide) {
      const c = this.channelGuide[id];
      results[id] = {
        name: c.name,
        param: c.param,
        enabled: c.enabled,
      };
    }

    return results;
  }

  // Return id for channel name
  getIdByName(name) {
    for (const id in this.channelGuide) {
      if (this.channelGuide[id].name === name) {
        return id;
      }
    }
    return undefined;
  }

  isCustomChannel(id) {
    return (this.getIdByName('CustomChannel') === id);
  }

  isCustomChannelEnabled() {
    return (this.channelGuide[this.getIdByName('CustomChannel')].enabled);
  }

  getListings(id) {
    return this.channelGuide[id].channel.getListings();
  }

  setEnabled(id, enabled) {
    const originalValue = this.channelGuide[id].enabled;
    this.channelGuide[id].enabled = enabled;
    this.saveToStorage();
    if (originalValue !== enabled) {
      channelsNotifier.emit('channels.changed', id, enabled, originalValue);
    }
  }

  refreshAllEnabled() {
    for (const id in this.channelGuide) {
      const data = this.channelGuide[id];
      if (data.enabled) {
        data.channel.refresh();
      }
    }
  }

  isAnyEnabled() {
    for (const id in this.channelGuide) {
      const channel = this.channelGuide[id];
      if (channel.enabled) {
        return true;
      }
    }
    return false;
  }

  disableAllChannels() {
    for (const id in this.channelGuide) {
      if (this.channelGuide[id].enabled) {
        this.channelGuide[id].enabled = false;
        channelsNotifier.emit('channels.changed', id, false, true);
      }
    }
  }

  // Returns a random Listing from all enabled channels or from channel
  // |channelId| if specified, trying to match the ratio of |width| and
  // |height| decently.  Returns undefined if there are no enabled channels.
  randomListing(opts) {
    if (!getSettings().picreplacement) {
      return undefined;
    }
    // if the element to be replace is 'fixed' in position, it may make for bad pic
    // replacement element.
    if (opts.position === 'fixed') {
      for (const sub of subscriptionadapter/* default.getSubscriptionsMinusText */.Z.getSubscriptionsMinusText()) {
        if (sub.url === subscription1 || sub.url === subscription2) {
          return undefined;
        }
      }
    }

    const heightLowRange = opts.height;
    const widthLowRange = opts.width;
    const heightHighRange = (opts.height * 1.25);
    const widthHighRange = (opts.width * 1.25);
    const typeMatchListings = [];
    const rangeLimitedListings = [];
    let targetRatio = Math.max(opts.width, opts.height) / Math.min(opts.width, opts.height);

    for (const id in this.channelGuide) {
      const data = this.channelGuide[id];
      if (opts.channelId === id || (data.enabled && !opts.channelId)) {
        data.channel.getListings().forEach((element) => {
          if (
            (opts.type === WIDE || opts.type === SKINNYWIDE)
            && (element.type !== SKINNYTALL)
            && (element.width <= widthHighRange)
            && (element.height >= heightLowRange)
            && (element.height <= heightHighRange)
          ) {
            rangeLimitedListings.push(element);
          } else if (
            (opts.type === TALL || opts.type === SKINNYTALL)
            && (element.type !== SKINNYWIDE)
            && (element.width >= widthLowRange)
            && (element.width <= widthHighRange)
            && (element.height <= heightHighRange)
          ) {
            rangeLimitedListings.push(element);
          } else if (
            (opts.type !== WIDE)
            && (opts.type !== TALL)
            && (opts.type !== SKINNYTALL)
            && (opts.type !== SKINNYWIDE)
            && (element.width >= widthLowRange)
            && (element.width <= widthHighRange)
            && (element.height >= heightLowRange)
            && (element.height <= heightHighRange)
          ) {
            rangeLimitedListings.push(element);
          }
          if (
            opts.type === element.type
            && element.width >= widthLowRange
            && element.height >= heightLowRange
          ) {
            typeMatchListings.push(element);
          }
        });
      }
    }
    let exactTypeMatchListings = [];
    if (rangeLimitedListings.length > 0) {
      const randomIndex = Math.floor(Math.random() * rangeLimitedListings.length);
      const theListing = Object.assign({}, rangeLimitedListings[randomIndex]);
      theListing.listingHeight = theListing.height;
      theListing.listingWidth = theListing.width;
      if (opts.height !== theListing.height && opts.width !== theListing.width) {
        theListing.height = (theListing.height * opts.width) / theListing.width;
        theListing.width = opts.width;
      }
      return theListing;
    }
    let bestMatchRatio = 0;
    targetRatio = Math.max(opts.width, opts.height) / Math.min(opts.width, opts.height);
    typeMatchListings.forEach((listing) => {
      if (Math.abs(listing.ratio - targetRatio) < Math.abs(bestMatchRatio - targetRatio)) {
        exactTypeMatchListings = []; // remove previous matches
        exactTypeMatchListings.push(listing);
        bestMatchRatio = listing.ratio;
      } else if (listing.ratio === bestMatchRatio) {
        exactTypeMatchListings.push(listing);
      }
    });
    if (exactTypeMatchListings.length > 0) {
      const randomIndex = Math.floor(Math.random() * exactTypeMatchListings.length);
      const theListing = Object.assign({}, exactTypeMatchListings[randomIndex]);
      theListing.listingHeight = theListing.height;
      theListing.listingWidth = theListing.width;
      return theListing;
    }

    return undefined;
  }

  // adds any new or missing channels (in a disabled state) to the users channel guide
  addNewChannels() {
    const channelNames = ['DogsChannel', 'CatsChannel', 'LandscapesChannel', 'OceanChannel', 'GoatsChannel', 'BirdChannel', 'FoodChannel', 'CustomChannel'];
    for (const name of channelNames) {
      if (!this.getIdByName(name)) {
        this.add({
          name,
          param: undefined,
          enabled: false,
        });
      }
    }
  }

  loadFromStorage() {
    (0,bg_functions/* migrateData */.ww)(channelsKey, true).then(() => {
      (0,bg_functions/* chromeStorageGetHelper */.nX)(channelsKey).then((response) => {
        this.channelGuide = {};
        const savedData = response || [];
        for (let i = 0; i < savedData.length; i++) {
          this.add(savedData[i]);
        }
        this.addNewChannels();
      });
    });
  }

  saveToStorage() {
    const toStore = [];
    const guide = this.getGuide();
    for (const id in guide) {
      toStore.push(guide[id]);
    }
    (0,bg_functions/* chromeStorageSetHelper */.rJ)(channelsKey, toStore);
  }

  static getContentType(details) {
    return resourceTypes.get(details.type) || contentTypes/* contentTypes.OTHER */.Tr.OTHER;
  }

  static getFrameId(details) {
    return details.type === 'sub_frame' ? details.parentFrameId
      : details.frameId;
  }

  // Ignore EasyPrivacy rules, since they can cause issue with odd image swaps
  static async shouldUseFilter(filter) {
    if (!filter) {
      return false;
    }
    const subscriptions = await ewe_api.subscriptions.getForFilter(filter);
    const isEasyPrivacy = subscriptions.filter(subscription => subscription.title === 'EasyPrivacy');
    return (isEasyPrivacy && isEasyPrivacy.length === 0);
  }

  async filterListener({ request, filter }) {
    if (getSettings().picreplacement && this.license.isActiveLicense()) {
      const shouldUseFilter = await Channels.shouldUseFilter(filter);
      if (!shouldUseFilter) {
        return;
      }
      if (request
          && request.tabId
          && filter
          && filter.type === 'elemhide'
          && filter.selector && filter.enabled) {
        const msgDetail = { hidingSelector: filter.selector, command: 'addSelector' };
        browser.tabs.sendMessage(request.tabId, msgDetail, { frameId: request.frameId });
      } else if (request
        && request.tabId
        && filter
        && filter.type === 'blocking'
        && filter.enabled) {
        const selector = typeSelectors.get(Channels.getContentType(request));
        const frameId = Channels.getFrameId(request);
        const msg = { selector, command: 'addBlockingSelector', url: request.url };
        browser.tabs.sendMessage(request.tabId, msg, { frameId });
      }
    } else if (!getSettings().picreplacement) {
      ewe_api.reporting.onBlockableItem.removeListener(this.filterListener, REPORTING_OPTIONS);
    }
  }


  initializeListeners() {
    this.license.ready().then(() => {
      settings.onload().then(() => {
        if (getSettings().picreplacement && this.license.isActiveLicense()) {
          ewe_api.reporting.onBlockableItem.removeListener(this.filterListener, REPORTING_OPTIONS);
          ewe_api.reporting.onBlockableItem.addListener(
            this.filterListener.bind(this), REPORTING_OPTIONS,
          );
        }
      });
    });
  }
}


/***/ }),

/***/ 2509:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Cz": () => (/* binding */ License),
/* harmony export */   "ZW": () => (/* binding */ channels),
/* harmony export */   "lg": () => (/* binding */ replacedCounts)
/* harmony export */ });
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(9876);
/* harmony import */ var _alias_storage_tab_session__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(440);
/* harmony import */ var _id_background_index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6703);
/* harmony import */ var _channels__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5633);
/* harmony import */ var _prefs_background__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1648);
/* harmony import */ var _alias_icon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(3398);
/* harmony import */ var _alias_subscriptionInit__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(704);
/* harmony import */ var _servermessages__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(2559);
/* harmony import */ var _subscriptionadapter__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(1974);
/* harmony import */ var _fetch_util__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(8171);
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(7337);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser */


// Yes, you could hack my code to not check the license.  But please don't.
// Paying for this extension supports the work on AdBlock.  Thanks very much.














const licenseNotifier = new _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_9__/* .EventEmitter */ .v();

const License = (function getLicense() {
  const isProd = true;
  const licenseStorageKey = 'license';
  const installTimestampStorageKey = 'install_timestamp';
  const userClosedSyncCTAKey = 'user_closed_sync_cta';
  const userSawSyncCTAKey = 'user_saw_sync_cta';
  const pageReloadedOnSettingChangeKey = 'page_reloaded_on_user_settings_change';
  const licenseAlarmName = 'licenseAlarm';
  const sevenDayAlarmName = 'sevenDayLicenseAlarm';

  let theLicense;
  const fiveMinutes = 300000;
  const initialized = false;
  let ajaxRetryCount = 0;
  let readyComplete;
  const licensePromise = new Promise(((resolve) => {
    readyComplete = resolve;
  }));
  const themesForCTA = [
    'solarized_theme', 'solarized_light_theme', 'watermelon_theme', 'sunshine_theme', 'ocean_theme',
  ];
  let currentThemeIndex = 0;
  const mabConfig = {
    prod: {
      licenseURL: 'https://myadblock-licensing.firebaseapp.com/license/',
      syncURL: 'https://myadblock.sync.getadblock.com/v1/sync',
      subscribeKey: 'sub-c-9eccffb2-8c6a-11e9-97ab-aa54ad4b08ec',
      payURL: 'https://getadblock.com/premium/enrollment/',
      subscriptionURL: 'https://getadblock.com/premium/manage-subscription/',
      bypassAuthorizedKeys: [
        // Production keys
        `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsCtBp9/0qCM5lp0lJVSx
      IAGgWZsX50xeJfBq6OkfsI+305Yj0igVfyVASOaC1fc2JRHD/uAOKk47SiPcBkiz
      mPHUt9ziOtAEkW7GrU6gaVOSwp26vUbSuvg9ouut5U2m8ULOyzp+WyU8nCzTPV5o
      AvCta04bK9or4UnyTRKyqADlNwz7WnH+0QiHYbgtfE/E3rowEoMEAC44C7OiawCm
      rnBXAkyBJnh1oEfUVI4LurxVl/zLo8MWfzErkaJy1FpsFR3F3L9ymKXpmxbhlDdX
      0rxjwnRD/2sCWW3SJOU26gfFgu/NI6LGxcWdPrucdkoOOOnNQjjDlhGYPTqqxugH
      /I5r+tAeUrrwKjmFcpMdxX7dfw1LoBoZCZnShZKlGKDqXf985Dc+3StbGWcxwNn9
      l9/Ho6YFA7fKpBKEED2V+SrDb4RCkScvOOiMOI1v5bwsLinUd/2yxRDrO25uwU7h
      r4LqmOguqjjLGF17d2WvG5D+LIQwgusxQd9Jk/n9PRdwtVGJhSDsDc8el2nKIqk9
      ofk3YJzAIbS9iHQ2LuHubuhzYjkxRLcdSbt1oONHCSHeecZn/OXwYeTvU7Po1KPW
      emi3XUpyjylUe9ONlw50lynwRw117bNHQDDHwKPoVW1cjoAtRsCnviFHPWTPjQKe
      A2LS9qa7eNdIonehrzG20cECAwEAAQ==`,
      ],
    },
    dev: {
      licenseURL: 'https://dev.myadblock.licensing.getadblock.com/license/',
      syncURL: 'https://dev.myadblock.sync.getadblock.com/v1/sync',
      subscribeKey: 'sub-c-9e0a7270-83e7-11e9-99de-d6d3b84c4a25',
      payURL: 'https://getadblock.com/premium/enrollment/?testmode=true',
      subscriptionURL: 'https://dev.getadblock.com/premium/manage-subscription/',
      bypassAuthorizedKeys: [
        // Development keys
        `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAlTA+1kMAzbuPzMv/FV5B
      BcnqJRb7BTtCTE3IKox2Jd6d5kgI4JUIR9Hrsh+BPU8DACOv5dmcTIiy8Ci5Ptlu
      99t09oOPfZQLTyBEL4wFrTgbJPftURKugs8fkU9ttR/FyCCtSzhFlGNrcQvTTUvr
      NLBpBGuIpCkz/k8hux+IqDxaStVlJaJnyfcLl4kD+ogWkjmzG7Ba8btfPlVEkGvh
      xgrlVafn5w94hIhF9XzByxDxFk9KE4+Bs317HmYjYVoH3av61WMqZY5NFHoucuZz
      r4vhwt3b7yFIQ3T/eqiysUUX5OrqBVK9aQos8mCDKjGp2hWYnP1Oi1BzfPKVyTju
      IZAtZdrIeazj5NDcH+dwRmYTfB0r/35Dd7SIUrNX1uIRHcKWvLFUtpsRW+/d1XHG
      ruWBaPExutIgcIIpSCHm1cHVYpgEzu8Vs5VyOw+AfqTL5kWNAchx1VeWD91r4cVh
      ZPZQbN/TfxHyxisYLRMD4pKfjV8hlsUvmuy+Bg49Ds+rpGVEvnDdijWIbVsSD9eN
      5IO768819feXbR56PPxQtMs/JaE77Uoauuj7Lw9vGx/27V24TCWNTtbnwRkBCxJz
      m7YeUksuKYg7SQp4SMzkwhGxRRu9xlF/yKnDVXF5/J483akIuhuv0TiJI51mYvrD
      uc6lr1LW6QmZf6Vv2+ur7hcCAwEAAQ==`,
        // Testing keys
        `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAqpV+M8A3hfi7JMut3Orr
      Sa6YEQutZ6F/FiaAmWPAlrG4IFA88HvqxRqbPz1niCWou7FqgsJ+v5+hhyrMFqM2
      JBBdaLHiDN1KNm7Ydx1j7NJJ+o/O22SN6kIU6k+VLg2B+Gj37s1qi8tIGWnrP+Ip
      jPMHDYSxLbQlIH/6CIiKVyMr7zaTej9rigGr33tqxM+RZtwo8eudEVcN3+DsUZ4j
      /jYx/hTvPze2r5xhB3faErhPSFLjZ9UIv0P9tPwO9m7PRQx9mrnh5QnS8NfEY2FY
      oFd+HiTsJS1QJi/ez9+5n1WCOTutc2lbxboCV3eJegBDObPDW1EhuVXOzGTEs5Sc
      Mb8NgE4iEoL9awIiGce+jS4Yj2olJAwGxv0rDJTycnDxx0SDvjTqEYFhuXk55vGd
      Dq7ClDvv8yiQ4CfCjZiLr9YbzO/kp2zf55wL+0SGmLKW6BLcUgGTciSHYMhPLv/N
      C5HtFlag5H7KGyimp/Q8eC9RnTskchyr1ShWyOoRMTsd45Htba5gfYjUWQxqhKiC
      SuFCooSX8/6zMynNOvD3A1p1+NhsKYzB+hnBeaFc/YKRyXVx1UJc8EZDc6jOYDoz
      1EB3nXfMQjtqmpqS5IbhzUxKDRC+kvRo7wa0TexhFMs6Vlg3+dAeemQujyljtJ7r
      PVMNXy0NnTuRNSK6V+Oz2JUCAwEAAQ==`,
        // Production keys
        `MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsCtBp9/0qCM5lp0lJVSx
      IAGgWZsX50xeJfBq6OkfsI+305Yj0igVfyVASOaC1fc2JRHD/uAOKk47SiPcBkiz
      mPHUt9ziOtAEkW7GrU6gaVOSwp26vUbSuvg9ouut5U2m8ULOyzp+WyU8nCzTPV5o
      AvCta04bK9or4UnyTRKyqADlNwz7WnH+0QiHYbgtfE/E3rowEoMEAC44C7OiawCm
      rnBXAkyBJnh1oEfUVI4LurxVl/zLo8MWfzErkaJy1FpsFR3F3L9ymKXpmxbhlDdX
      0rxjwnRD/2sCWW3SJOU26gfFgu/NI6LGxcWdPrucdkoOOOnNQjjDlhGYPTqqxugH
      /I5r+tAeUrrwKjmFcpMdxX7dfw1LoBoZCZnShZKlGKDqXf985Dc+3StbGWcxwNn9
      l9/Ho6YFA7fKpBKEED2V+SrDb4RCkScvOOiMOI1v5bwsLinUd/2yxRDrO25uwU7h
      r4LqmOguqjjLGF17d2WvG5D+LIQwgusxQd9Jk/n9PRdwtVGJhSDsDc8el2nKIqk9
      ofk3YJzAIbS9iHQ2LuHubuhzYjkxRLcdSbt1oONHCSHeecZn/OXwYeTvU7Po1KPW
      emi3XUpyjylUe9ONlw50lynwRw117bNHQDDHwKPoVW1cjoAtRsCnviFHPWTPjQKe
      A2LS9qa7eNdIonehrzG20cECAwEAAQ==`,
      ],
    },
  };
  (async () => {
    const userID = await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)();
    mabConfig.prod.payURL = `${mabConfig.prod.payURL}?u=${userID}`;
    mabConfig.dev.payURL = `${mabConfig.dev.payURL}&u=${userID}`;
  })();
  const MAB_CONFIG = isProd ? mabConfig.prod : mabConfig.dev;

  const sevenDayAlarmIdleListener = function (newState) {
    if (newState === 'active') {
      License.checkSevenDayAlarm();
    }
  };

  const removeSevenDayAlarmStateListener = function () {
    browser.idle.onStateChanged.removeListener(sevenDayAlarmIdleListener);
  };

  const addSevenDayAlarmStateListener = function () {
    removeSevenDayAlarmStateListener();
    browser.idle.onStateChanged.addListener(sevenDayAlarmIdleListener);
  };

  const cleanUpSevenDayAlarm = function () {
    removeSevenDayAlarmStateListener();
    browser.storage.local.remove(License.sevenDayAlarmName);
    browser.alarms.clear(License.sevenDayAlarmName);
  };

  const processSevenDayAlarm = function () {
    cleanUpSevenDayAlarm();
    (0,_alias_icon__WEBPACK_IMPORTED_MODULE_4__/* .showIconBadgeCTA */ .QO)(true, _alias_icon__WEBPACK_IMPORTED_MODULE_4__/* .NEW_BADGE_REASONS.SEVEN_DAY */ .ec.SEVEN_DAY);
  };

  browser.alarms.onAlarm.addListener((alarm) => {
    if (alarm && alarm.name === licenseAlarmName) {
      // At this point, no alarms exists, so
      // create an temporary alarm to avoid race condition issues
      browser.alarms.create(licenseAlarmName, { delayInMinutes: (24 * 60) });
      License.ready().then(() => {
        License.updatePeriodically();
      });
    }
    if (alarm && alarm.name === sevenDayAlarmName) {
      processSevenDayAlarm();
    }
  });

  // Check if the computer was woken up, and if there was a pending alarm
  // that should fired during the sleep, then
  // remove it, and fire the update ourselves.
  // see - https://bugs.chromium.org/p/chromium/issues/detail?id=471524
  browser.idle.onStateChanged.addListener((newState) => {
    if (newState === 'active') {
      browser.alarms.get(licenseAlarmName).then((alarm) => {
        if (alarm && Date.now() > alarm.scheduledTime) {
          browser.alarms.clear(licenseAlarmName).then(() => {
            License.updatePeriodically();
          });
        } else if (alarm) {
          // if the alarm should fire in the future,
          // re-add the license so it fires at the correct time
          const originalTime = alarm.scheduledTime;
          browser.alarms.clear(licenseAlarmName).then((wasCleared) => {
            if (wasCleared) {
              browser.alarms.create(licenseAlarmName, { when: originalTime });
            }
          });
        } else {
          License.updatePeriodically();
        }
      });
    }
  });

  // check the 7 alarm when the browser starts
  // or is woken up
  const checkSevenDayAlarm = function () {
    browser.alarms.get(License.sevenDayAlarmName).then((alarm) => {
      if (alarm && Date.now() > alarm.scheduledTime) {
        browser.alarms.clear(License.sevenDayAlarmName).then(() => {
          (0,_alias_icon__WEBPACK_IMPORTED_MODULE_4__/* .showIconBadgeCTA */ .QO)(true, _alias_icon__WEBPACK_IMPORTED_MODULE_4__/* .NEW_BADGE_REASONS.SEVEN_DAY */ .ec.SEVEN_DAY);
          removeSevenDayAlarmStateListener();
          browser.storage.local.remove(License.sevenDayAlarmName);
        });
      } else if (alarm) {
        // if the alarm should fire in the future,
        // re-add the license so it fires at the correct time
        const originalTime = alarm.scheduledTime;
        browser.alarms.clear(License.sevenDayAlarmName).then((wasCleared) => {
          if (wasCleared) {
            browser.alarms.create(License.sevenDayAlarmName, { when: originalTime });
            browser.storage.local.set({ [License.sevenDayAlarmName]: true });
            License.addSevenDayAlarmStateListener();
          }
        });
      } else {
        // since there's no alarm, we may need to show the 'new' text,
        // check if the temporary seven day alarm indicator is set, and
        // if the install date is 7 days or more than now
        browser.storage.local.get(License.sevenDayAlarmName).then((data) => {
          if (data && data[License.sevenDayAlarmName]) {
            browser.storage.local.get('blockage_stats').then((response) => {
              const { blockage_stats } = response;
              if (blockage_stats && blockage_stats.start) {
                const installDate = new Date(blockage_stats.start);
                const now = new Date();
                const oneDay = 24 * 60 * 60 * 1000; // hours*minutes*seconds*milliseconds
                const diffDays = Math.round((now - installDate) / oneDay);
                if (diffDays >= 7) {
                  (0,_alias_icon__WEBPACK_IMPORTED_MODULE_4__/* .showIconBadgeCTA */ .QO)(true, _alias_icon__WEBPACK_IMPORTED_MODULE_4__/* .NEW_BADGE_REASONS.SEVEN_DAY */ .ec.SEVEN_DAY);
                  removeSevenDayAlarmStateListener();
                  browser.storage.local.remove(License.sevenDayAlarmName);
                }
              }
            });
          }
        });
        removeSevenDayAlarmStateListener();
      }
    });
  };
  addSevenDayAlarmStateListener();

  /**
   * Provides payload to verify authenticity of Premium license data
   *
   * @returns {string} Encoded signed Premium license data
   */
  const getBypassPayload = function () {
    if (!License.isActiveLicense()) {
      return null;
    }
    return `${License.get().encodedData}.${License.get().signature}`;
  };

  // Load the license from persistent storage
  // Should only be called during startup / initialization
  const loadFromStorage = function (callback) {
    browser.storage.local.get(licenseStorageKey).then((response) => {
      theLicense = response[licenseStorageKey] || {};
      if (typeof callback === 'function') {
        callback();
      }
    });
  };
  const checkForManagedSettings = function () {
    return new Promise(((resolve) => {
      if ('managed' in browser.storage) {
        browser.storage.managed.get(null).then((items) => {
          for (const key in items) {
            if (key === 'suppress_premium_cta') {
              theLicense = License.get();
              theLicense[key] = items[key];
              License.set(theLicense);
            }
          }
          resolve();
        },
        // Opera and FF doesn't support browser.storage.managed, but instead of simply
        // removing the API, it gives an asynchronous error which we ignore here.
        () => {
          resolve();
        });
      } else {
        resolve();
      }
    }));
  };

  // Clean up / remove old, unused data in localStorage
  function cleanUpLocalStorage() {
    (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .storageSet */ .eV)(licenseStorageKey);
  }

  return {
    licenseStorageKey,
    userClosedSyncCTAKey,
    userSawSyncCTAKey,
    themesForCTA,
    pageReloadedOnSettingChangeKey,
    initialized,
    licenseAlarmName,
    sevenDayAlarmName,
    checkSevenDayAlarm,
    addSevenDayAlarmStateListener,
    removeSevenDayAlarmStateListener,
    cleanUpSevenDayAlarm,
    licenseTimer: undefined, // the license update timer token
    licenseNotifier,
    MAB_CONFIG,
    isProd,
    getBypassPayload,
    enrollUser() {
      loadFromStorage(() => {
        // only enroll users if they were not previously enrolled
        if (typeof theLicense.myadblock_enrollment === 'undefined') {
          theLicense.myadblock_enrollment = true;
          License.set(theLicense);
        }
      });
    },
    get() {
      return theLicense;
    },
    set(newLicense) {
      const licenseStatusBefore = theLicense.status;

      if (newLicense) {
        theLicense = newLicense;
        browser.storage.local.set({ license: theLicense });
      }

      if (licenseStatusBefore !== newLicense.status) {
        licenseNotifier.emit('license.status.changed');
      }
    },
    /**
     * Changes configuration to use development licensing server
     */
    setDevConfig() {
      License.MAB_CONFIG = mabConfig.dev;
    },
    initialize(callback) {
      loadFromStorage(() => {
        checkForManagedSettings().then(() => {
          if (typeof callback === 'function') {
            callback();
          }
          cleanUpLocalStorage();
          readyComplete();
        });
      });
    },
    getCurrentPopupMenuThemeCTA() {
      const theme = License.themesForCTA[currentThemeIndex];
      const lastThemeIndex = License.themesForCTA.length - 1;
      currentThemeIndex = lastThemeIndex === currentThemeIndex ? 0 : currentThemeIndex += 1;
      return theme || '';
    },
    // Get the latest license data from the server, and talk to the user if needed.
    async update() {
      const userID = await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)();
      licenseNotifier.emit('license.updating');
      const postDataObj = {};
      postDataObj.u = userID;
      postDataObj.cmd = 'license_check';
      const licenseStatusBefore = License.get().status;
      // license version
      postDataObj.v = '1';
      (0,_fetch_util__WEBPACK_IMPORTED_MODULE_10__/* ["default"] */ .Z)(License.MAB_CONFIG.licenseURL, postDataObj).then(async (response) => {
        if (response.ok) {
          const responseObj = await response.json();
          ajaxRetryCount = 0;
          const updatedLicense = responseObj;
          licenseNotifier.emit('license.updated', updatedLicense);
          if (!updatedLicense) {
            return;
          }
          // merge the updated license
          theLicense = { ...theLicense, ...updatedLicense };
          theLicense.licenseId = theLicense.code;
          License.set(theLicense);
          // now check to see if we need to do anything because of a status change
          if (
            licenseStatusBefore === 'active'
            && updatedLicense.status
            && updatedLicense.status === 'expired'
          ) {
            License.processExpiredLicense();
            _servermessages__WEBPACK_IMPORTED_MODULE_6__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('trial_license_expired');
          }
        } else {
          (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('license server error response', response.status, ajaxRetryCount);
          licenseNotifier.emit('license.updated.error', ajaxRetryCount);
          ajaxRetryCount += 1;
          if (ajaxRetryCount > 3) {
            (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('Retry Count exceeded, giving up', ajaxRetryCount);
            return;
          }
          const oneMinute = 1 * 60 * 1000;
          setTimeout(() => {
            License.updatePeriodically(`error${ajaxRetryCount}`);
          }, oneMinute);
        }
      })
        .catch((error) => {
          (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('license server returned error: ', error);
        });
    },
    processExpiredLicense() {
      theLicense = License.get();
      theLicense.myadblock_enrollment = true;
      License.set(theLicense);
      (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .setSetting */ .Lt)('picreplacement', false);
      licenseNotifier.emit('license.expired');
      if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .getSettings */ .Gw)().sync_settings) {
        // We have to import the "sync-service" module on demand,
        // as the "sync-service" module in turn requires this module.
        /* eslint-disable import/no-cycle */
        (Promise.resolve(/* import() */).then(__webpack_require__.bind(__webpack_require__, 3283))).disableSync();
      }
      (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .setSetting */ .Lt)('color_themes', { popup_menu: 'default_theme', options_page: 'default_theme' });
      _subscriptionadapter__WEBPACK_IMPORTED_MODULE_7__/* ["default"].unsubscribe */ .Z.unsubscribe({ adblockId: 'distraction-control' });
      browser.alarms.clear(licenseAlarmName);
    },
    ready() {
      return licensePromise;
    },
    updatePeriodically() {
      if (!License.isActiveLicense()) {
        return;
      }
      License.update();
      browser.storage.local.get(installTimestampStorageKey).then((response) => {
        let installTimestamp = response[installTimestampStorageKey];
        const originalInstallTimestamp = installTimestamp || Date.now();
        // If the installation timestamp is missing from storage,
        // save an updated version
        if (!(response[installTimestampStorageKey])) {
          installTimestamp = Date.now();
          browser.storage.local.set({ install_timestamp: installTimestamp });
        }
        const originalInstallDate = new Date(originalInstallTimestamp);
        let nextLicenseCheck = new Date();
        if (originalInstallDate.getHours() <= nextLicenseCheck.getHours()) {
          nextLicenseCheck.setDate(nextLicenseCheck.getDate() + 1);
        }
        nextLicenseCheck.setHours(originalInstallDate.getHours());
        nextLicenseCheck.setMinutes(originalInstallDate.getMinutes());
        // Add 5 minutes to the 'minutes' to make sure we've allowed enought time for '1' day
        nextLicenseCheck = new Date(nextLicenseCheck.getTime() + fiveMinutes);
        browser.alarms.create(licenseAlarmName, { when: nextLicenseCheck.getTime() });
      });
    },
    async getLicenseInstallationDate() {
      const response = await browser.storage.local.get(installTimestampStorageKey);
      const originalInstallTimestamp = response[installTimestampStorageKey];
      if (originalInstallTimestamp) {
        return (new Date(originalInstallTimestamp));
      }
      return undefined;
    },
    // activate the current license and configure the extension in licensed mode.
    // Call with an optional delay parameter (in milliseconds) if the first license
    // update should be delayed by a custom delay (default is 0 minutes).
    activate(delayMs) {
      let delay = delayMs;
      const currentLicense = License.get() || {};
      const newLicense = { ...currentLicense };
      newLicense.status = 'active';
      License.set(newLicense);
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .reloadOptionsPageTabs */ .qo)();
      if (typeof delay !== 'number') {
        delay = 0; // 0 minutes
      }
      if (!this.licenseTimer) {
        this.licenseTimer = setTimeout(() => {
          License.updatePeriodically();
        }, delay);
      }
      (0,_prefs_background__WEBPACK_IMPORTED_MODULE_3__/* .setSetting */ .Lt)('picreplacement', false);
    },
    getFormattedActiveSinceDate() {
      if (
        !License
        || !License.isActiveLicense()
        || !License.get()
        || !License.get().createdAtUTC
        || !Number.isInteger(License.get().createdAtUTC)
      ) {
        return null;
      }
      const dateFormat = { year: 'numeric', month: 'long' };
      let formattedDate = null;
      try {
        const createdAtUTC = parseInt(License.get().createdAtUTC, 10);
        formattedDate = new Date(createdAtUTC).toLocaleDateString(undefined, dateFormat);
      } catch (e) {
        return null;
      }
      return formattedDate;
    },
    isActiveLicense() {
      return License && License.get() && License.get().status === 'active';
    },
    isLicenseCodeValid() {
      return License && License.get().code && typeof License.get().code === 'string';
    },
    isMyAdBlockEnrolled() {
      return License && License.get() && License.get().myadblock_enrollment === true;
    },
    shouldShowMyAdBlockEnrollment() {
      return License.isMyAdBlockEnrolled()
        && !License.isActiveLicense()
        && License.shouldShowPremiumCTA();
    },
    shouldShowPremiumDcCTA() {
      return (License && License.isActiveLicense() && License.get().suppress_premium_cta !== true);
    },
    shouldShowPremiumCTA() {
      return !(License && License.get().suppress_premium_cta === true);
    },
    shouldShowBlacklistCTA(newValue) {
      if (!License.shouldShowPremiumCTA()) {
        return false;
      }
      const currentLicense = License.get() || {};
      if (typeof newValue === 'boolean') {
        currentLicense.showBlacklistCTA = newValue;
        License.set(currentLicense);
        return null;
      }

      if (typeof currentLicense.showBlacklistCTA === 'undefined') {
        currentLicense.showBlacklistCTA = true;
        License.set(currentLicense);
      }
      return License && License.get() && License.get().showBlacklistCTA === true;
    },
    shouldShowWhitelistCTA(newValue) {
      if (!License.shouldShowPremiumCTA()) {
        return false;
      }
      const currentLicense = License.get() || {};
      if (typeof newValue === 'boolean') {
        currentLicense.showWhitelistCTA = newValue;
        License.set(currentLicense);
        return null;
      }

      if (typeof currentLicense.showWhitelistCTA === 'undefined') {
        currentLicense.showWhitelistCTA = true;
        License.set(currentLicense);
      }
      return License && License.get() && License.get().showWhitelistCTA === true;
    },
    displayPopupMenuNewCTA() {
      const isNotActive = !License.isActiveLicense();
      const variant = License.get() ? License.get().var : undefined;
      return License && isNotActive && [3, 4].includes(variant) && License.shouldShowPremiumCTA();
    },
  };
}());

const replacedPerPage = new _alias_storage_tab_session__WEBPACK_IMPORTED_MODULE_0__/* .TabSessionStorage */ .H('ab:premium:replacedPerPage');

// Records how many ads have been replaced by AdBlock.  This is used
// by the AdBlock to display statistics to the user.
const replacedCounts = (function getReplacedCount() {
  const adReplacedNotifier = new _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_9__/* .EventEmitter */ .v();
  const key = 'replaced_stats';
  (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .migrateData */ .ww)(key, true).then(() => {
    (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageGetHelper */ .nX)(key).then((data) => {
      let replacedCountData = data;
      if (!data) {
        replacedCountData = {};
      }
      if (replacedCountData.start === undefined) {
        replacedCountData.start = Date.now();
      }
      if (replacedCountData.total === undefined) {
        replacedCountData.total = 0;
      }
      replacedCountData.version = 1;
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(key, replacedCountData);
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .storageSet */ .eV)(key);
    });
  });

  return {
    recordOneAdReplaced(tabId) {
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageGetHelper */ .nX)(key).then((replacedCountData) => {
        const data = replacedCountData;
        data.total += 1;
        (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(key, data);
        browser.tabs.get(tabId).then(async (tab) => {
          let replaced = await replacedPerPage.get(tabId) || 0;
          await replacedPerPage.set(tabId, replaced += 1);
          adReplacedNotifier.emit('adReplaced', tabId, tab.url);
        });
      });
    },
    get() {
      return (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageGetHelper */ .nX)(key);
    },
    async getTotalAdsReplaced(tabId) {
      if (tabId) {
        return replacedPerPage.get(tabId);
      }
      return this.get().then(data => data.total);
    },
    adReplacedNotifier,
  };
}());

// for use in the premium enrollment process
// de-coupled from the `License.ready().then` code below because the delay
// prevents the addListener from being fired in a timely fashion.
const onInstalledPromise = new Promise(((resolve) => {
  browser.runtime.onInstalled.addListener((details) => {
    resolve(details);
  });
}));

// the order of Promises below dictacts the order of the data in the detailsArray
Promise.all([onInstalledPromise, License.ready(), _alias_subscriptionInit__WEBPACK_IMPORTED_MODULE_5__/* .initialize */ .j]).then((detailsArray) => {
  // Enroll existing users in Premium
  if (detailsArray.length > 0 && detailsArray[0].reason) {
    License.enrollUser();
    if (detailsArray[0].reason === 'install') {
      // create an alarm that will fire in ~ 7 days to show the "New" badge text
      browser.alarms.create(License.sevenDayAlarmName, { delayInMinutes: (60 * 24 * 7) });
      License.addSevenDayAlarmStateListener();
      browser.storage.local.set({ [License.sevenDayAlarmName]: true });
    }
  }
});

License.ready().then(() => {
  License.checkSevenDayAlarm();

  if (License.isActiveLicense()) {
    License.updatePeriodically();
  }
});

License.initialize(() => {
  if (!License.initialized) {
    License.initialized = true;
  }
});

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  License,
  replacedCounts,
});

const channels = new _channels__WEBPACK_IMPORTED_MODULE_2__/* .Channels */ .E(License);


/***/ }),

/***/ 9769:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _telemetry_background__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5441);
/* harmony import */ var _subscriptionadapter__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(1974);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, log */




const sendDCReport = function (url, type, id) {
  if (!url || !type) {
    return;
  }
  const reportData = {
    url,
    type,
    platform: _telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY */ .C && `browser:${_telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.browser */ .C.browser}, browser version:${_telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.browserVersion */ .C.browserVersion}, OS:${_telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.os */ .C.os}, OS version:${_telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.osVersion */ .C.osVersion}`,
    locale: browser.i18n.getUILanguage(),
    version: browser.runtime.getManifest().version,
  };
  if (id) {
    const subs = _subscriptionadapter__WEBPACK_IMPORTED_MODULE_1__/* ["default"].getSubscriptionsMinusText */ .Z.getSubscriptionsMinusText();
    if (subs && subs[id]) {
      const lastUpdate = subs[id].lastDownload || 0;
      reportData.filterListLastUpdate = new Date(lastUpdate * 1000);
    }
  }
  const formData = new FormData();
  formData.append('bug_report', JSON.stringify(reportData));
  fetch('https://getadblock.com/freshdesk/bugReportDistractionControl.php', {
    body: formData,
    method: 'post',
  }).catch((error) => {
    log('freshdesk returned error: ', error);
  });
};

browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.command !== 'sendDCReport' || !message.url || !message.type) {
    return;
  }
  sendDCReport(message.url, message.type, message.id);
  sendResponse({});
});


/***/ }),

/***/ 3283:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _telemetry_background__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(5441);
/* harmony import */ var _id_background_index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6703);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(9876);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var _check__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(2509);
/* harmony import */ var _channels__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(5633);
/* harmony import */ var _subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(1974);
/* harmony import */ var _prefs_background__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(1648);
/* harmony import */ var _servermessages__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(2559);
/* harmony import */ var _fetch_util__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(8171);
/* harmony import */ var _utilities_background_index__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(9555);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, channels,
   getUserFilters, Prefs, abpPrefPropertyNames,
   adblockIsDomainPaused, PubNub, adblockIsPaused,
   pausedFilterText1, pausedFilterText2,
   isWhitelistFilter, getCustomFilterMetaData */

/** @module SyncService */





// check.js imports disableSync from here
// eslint-disable-next-line import/no-cycle








const SyncService = (function getSyncService() {
  let storedSyncDomainPauses = [];
  let syncCommitVersion = 0;
  let currentExtensionName = '';
  let pubnub;
  const syncSchemaVersion = 1;
  const syncCommitVersionKey = 'SyncCommitKey';
  const syncLogMessageKey = 'SyncLogMessageKey';
  const syncPreviousDataKey = 'SyncPreviousDataKey';
  const syncExtensionNameKey = 'SyncExtensionNameKey';
  const syncPendingPostDataKey = 'syncPendingPostDataKey';
  const syncNotifier = new _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_9__/* .EventEmitter */ .v();
  let lastPostStatusCode = 200;
  let pendingPostData = false;
  let lastGetStatusCode = 200;
  let lastGetErrorResponse = {};
  const debounceWaitTime = 10000; // time in ms before posting data
  // Below is a list of filter list ids that have been added since the
  // sync feature was added to AdBlock, therefore these filter lists should be sent
  // with an ID of 'url:...' instead of the id in the betafish-subscriptions.json file
  // any adds to the the betafish-subscriptions.json file should be added here as well.
  const sendFilterListByURL = ['nordic', 'annoyances',
    'fb_notifications', 'easylist_plus_romanian', 'idcac'];
  const { flavor } = (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .getUserAgentInfo */ .K1)();
  const { os } = (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .getUserAgentInfo */ .K1)();

  function setCommitVersion(newVersionNum) {
    syncCommitVersion = newVersionNum;
  }

  function getLastPostStatusCode() {
    return lastPostStatusCode;
  }

  function resetLastPostStatusCode() {
    lastPostStatusCode = 200;
  }

  function setLastPostStatusCode(newCode) {
    lastPostStatusCode = newCode;
  }

  function getLastGetStatusCode() {
    return lastGetStatusCode;
  }

  function resetLastGetStatusCode() {
    lastGetStatusCode = 200;
  }

  function setLastGetStatusCode(newCode) {
    lastGetStatusCode = newCode;
  }

  function getLastGetErrorResponse() {
    return lastGetErrorResponse;
  }

  function resetLastGetErrorResponse() {
    lastGetErrorResponse = {};
  }

  function setLastGetErrorResponse(newObject) {
    lastGetErrorResponse = newObject;
  }

  function resetAllErrors() {
    resetLastGetErrorResponse();
    resetLastGetStatusCode();
    resetLastPostStatusCode();
  }

  const getCurrentExtensionName = function () {
    return currentExtensionName;
  };

  const getSyncLog = function () {
    return new Promise((resolve) => {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageGetHelper */ .nX)(syncLogMessageKey).then((logMsgs) => {
        const storedLog = JSON.parse(logMsgs || '[]');
        const theReturnObj = {};
        Object.assign(theReturnObj, storedLog);
        resolve(theReturnObj);
      });
    });
  };

  // TODO - when should we delete the log file???
  const deleteSyncLog = function () {
    (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageDeleteHelper */ .lE)(syncLogMessageKey);
  };

  const migrateSyncLog = function () {
    /* eslint-disable no-restricted-globals */
    if (typeof self.localStorage === 'undefined') {
      return;
    }
    let storedMsgs = localStorage.getItem(syncLogMessageKey);
    if (!storedMsgs) {
      return;
    }
    storedMsgs = JSON.parse(storedMsgs);
    while (storedMsgs.length > 500) { // only keep the last 500 log entries
      storedMsgs.shift();
    }
    (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncLogMessageKey, JSON.stringify(storedMsgs), (error) => {
      if (!error) {
        localStorage.removeItem(syncLogMessageKey);
      }
    });
  };

  function debounced(delay, fn) {
    let timerId;
    return function debouncedAgain(...args) {
      if (timerId) {
        clearTimeout(timerId);
      }
      timerId = setTimeout(() => {
        fn(...args);
        timerId = null;
      }, delay);
    };
  }

  // return meta data about the extension installation
  const getExtensionInfo = function () {
    return {
      flavor,
      browserVersion: _telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.browserVersion */ .C.browserVersion,
      os,
      osVersion: _telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.osVersion */ .C.osVersion,
      extVersion: _telemetry_background__WEBPACK_IMPORTED_MODULE_0__/* .TELEMETRY.version */ .C.version,
      syncSchemaVersion,
    };
  };

  /*
  ** @param arrOne, arrTwo - Arrays to compare
  ** @returns {boolean} - true if a and b are the same array
  **                      has the length and same values in any order
  **                      otherwise false
  */
  function arrayComparison(arrOne, arrTwo) {
    if (!Array.isArray(arrOne) || !Array.isArray(arrTwo)) {
      return false;
    }
    if (arrOne.length !== arrTwo.length) {
      return false;
    }
    return arrOne.every(element => arrTwo.includes(element));
  }

  /*
  ** @param a, b        - values (Object, Date, etc.)
  ** @returns {boolean} - true if a and b are the same object or
  **                      same primitive value or
  **                      have the same properties with the same values
  **                      otherwise false
  */
  function objectComparison(a, b) {
    // Helper to return a value's internal object [[Class]]
    // That this returns [object Type] even for primitives
    function getClass(obj) {
      return Object.prototype.toString.call(obj);
    }

    // If a and b reference the same value, return true
    if (a === b) {
      return true;
    }

    // If a and b aren't the same type, return false
    if (typeof a !== typeof b) {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object type compare is false', a, b);
      return false;
    }

    // Already know types are the same, so if type is number
    // and both NaN, return true
    if (typeof a === 'number' && Number.isNaN(a) && Number.isNaN(b)) {
      return true;
    }

    // Get internal [[Class]]
    const aClass = getClass(a);
    const bClass = getClass(b);

    // Return false if not same class
    if (aClass !== bClass) {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object class compare is false', a, b);
      return false;
    }

    // If they're Boolean, String or Number objects, check values
    if (
      aClass === '[object Boolean]'
      || aClass === '[object String]'
      || aClass === '[object Number]'
    ) {
      if (a.valueOf() !== b.valueOf()) {
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object valueOf compare is false', a, b);
        return false;
      }
    }

    // If they're RegExps, Dates or Error objects, check stringified values
    if (aClass === '[object RegExp]' || aClass === '[object Date]' || aClass === '[object Error]') {
      if (a.toString() !== b.toString()) {
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object string compare is false', a, b);
        return false;
      }
    }

    // For functions, check stringigied values are the same
    // Almost impossible to be equal if a and b aren't trivial
    // and are different functions
    if (aClass === '[object Function]' && a.toString() !== b.toString()) {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object function compare is false', a, b);
      return false;
    }

    // For all objects, (including Objects, Functions, Arrays and host objects),
    // check the properties
    const aKeys = Object.keys(a);
    const bKeys = Object.keys(b);

    // If they don't have the same number of keys, return false
    if (aKeys.length !== bKeys.length) {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object key length compare is false', a, b);
      return false;
    }

    if (Array.isArray(a) && Array.isArray(b)) {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('array compare is ', arrayComparison(a, b), a, b);
      return arrayComparison(a, b);
    }

    // Check they have the same keys
    if (!aKeys.every(key => Object.prototype.hasOwnProperty.call(b, key))) {
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('object keys compare is false', aKeys, bKeys);
      return false;
    }

    // Check key values - uses ES5 Object.keys
    return aKeys.every(key => objectComparison(a[key], b[key]));
  }

  const isDomainPauseFilter = function (filterText) {
    if (isWhitelistFilter(filterText)) {
      const domains = adblockIsDomainPaused();
      for (const domain in domains) {
        if (`@@${domain}$document` === filterText) {
          return true;
        }
      }
    }
    return false;
  };

  const isPauseFilter = function (filterText) {
    return (
      isWhitelistFilter(filterText) && ((pausedFilterText1 === filterText)
        || (pausedFilterText2 === filterText))
    );
  };

  function getCommitVersion() {
    return syncCommitVersion;
  }

  // Sync log message processing

  const addSyncLogText = function (msg) {
    (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageGetHelper */ .nX)(syncLogMessageKey).then((logMsgs) => {
      const storedLog = JSON.parse(logMsgs || '[]');
      storedLog.push(`${new Date().toUTCString()} , ${msg}`);
      while (storedLog.length > 500) { // only keep the last 500 log entries
        storedLog.shift();
      }
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncLogMessageKey, JSON.stringify(storedLog));
    });
  };

  const onExtensionNamesDownloadingAddLogEntry = function () {
    addSyncLogText('extension.names.downloading');
  };

  const onExtensionNamesDownloadedAddLogEntry = function () {
    addSyncLogText('extension.names.downloaded');
  };

  const onExtensionNamesDownloadingErrorAddLogEntry = function (errorCode) {
    addSyncLogText(`extension.names.downloading.error: ${errorCode}`);
  };

  const onExtensionNameUpdatingAddLogEntry = function () {
    addSyncLogText('extension.name.updating');
  };

  const onExtensionNameUpdatedAddLogEntry = function () {
    addSyncLogText('extension.name.updated');
  };

  const onExtensionNameUpdatedErrorAddLogEntry = function (errorCode) {
    addSyncLogText(`extension.names.updated.error: ${errorCode}`);
  };

  const onExtensionNameRemoveAddLogEntry = function () {
    addSyncLogText('extension.name.remove');
  };

  const onExtensionNameRemovedAddLogEntry = function () {
    addSyncLogText('extension.name.removed');
  };

  const onExtensionNamesRemoveErrorAddLogEntry = function (errorCode) {
    addSyncLogText(`extension.name.remove.error: ${errorCode}`);
  };

  const onPostDataSendingAddLogEntry = function () {
    addSyncLogText('post.data.sending');
  };

  const onPostDataSentAddLogEntry = function () {
    addSyncLogText(`post.data.sent, commit version: ${getCommitVersion()}`);
  };

  const onPostDataSentErrorAddLogEntry = function (errorCode) {
    addSyncLogText(`post.data.sent.error: ${errorCode}`);
  };

  const onSyncDataGettingAddLogEntry = function () {
    addSyncLogText('sync.data.getting');
  };

  const onSyncDataReceievedAddLogEntry = function () {
    addSyncLogText(`sync.data.receieved, commit version: ${getCommitVersion()}`);
  };

  const onSyncDataGettingErrorAddLogEntry = function (errorCode) {
    addSyncLogText(`sync.data.getting.error: ${errorCode}`);
  };

  const onSyncDataGettingErrorInitialFailAddLogEntry = function (errorCode) {
    addSyncLogText(`sync.data.getting.error.initial.fail: ${errorCode}`);
  };

  function cleanCustomFilter(filters) {
    // Remove the global pause white-list item if adblock is paused
    if (adblockIsPaused()) {
      let index = filters.indexOf(pausedFilterText1);
      if (index >= 0) {
        filters.splice(index, 1);
      }
      index = filters.indexOf(pausedFilterText2);
      if (index >= 0) {
        filters.splice(index, 1);
      }
    }

    // Remove the domain pause white-list items
    const domainPauses = adblockIsDomainPaused();
    for (const aDomain in domainPauses) {
      const index = filters.indexOf(`@@${aDomain}$document`);
      if (index >= 0) {
        filters.splice(index, 1);
      }
    }
    return filters;
  }

  const processSyncUpdate = async function (payload) {
    (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('processing sync update', payload);
    // do we need a check or comparison of payload.version vs. syncSchemaVersion ?
    if (payload.settings) {
      const keywords = Object.keys(payload.settings);
      // Use a Promise to wait until the previous 'set' is complete because
      // calling 'setSetting' several times in a row in a loop prevents some
      // settings from being saved to storage
      for (let inx = 0, p = Promise.resolve(); inx < keywords.length; inx++) {
        const id = keywords[inx];
        p = p.then(() => new Promise((resolve) => {
          let value = payload.settings[id];
          // since we receive a 'show_statsinpopup' property on the |Prefs| object
          // from older versions of AdBLock, use the incoming value from |Prefs|
          // object for backward compatability
          if (
            id === 'display_menu_stats'
            && payload.prefs
            && Object.prototype.hasOwnProperty.call(payload.prefs, 'show_statsinpopup')
          ) {
            value = payload.prefs.show_statsinpopup;
          }
          (0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .setSetting */ .Lt)(id, value, () => {
            resolve();
          });
        }));
      }
    }
    if (payload.subscriptions) {
      const currentSubs = await _subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__/* ["default"].getSubscriptionsMinusText */ .Z.getSubscriptionsMinusText();
      for (const id in currentSubs) {
        if (!payload.subscriptions[id] && currentSubs[id].subscribed) {
          (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync - removing subscription ', currentSubs[id].url);
          // eslint-disable-next-line no-await-in-loop
          await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.remove(currentSubs[id].url);
        }
      }
      for (const adblockId in payload.subscriptions) {
        if (!currentSubs[adblockId] || !currentSubs[adblockId].subscribed) {
          let url = _subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__/* ["default"].getUrlFromId */ .Z.getUrlFromId(adblockId);
          if (!url && adblockId.startsWith('url:')) {
            url = adblockId.slice(4);
          }
          if (_subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__/* ["default"].isLegacyDistractionControlById */ .Z.isLegacyDistractionControlById(adblockId)) {
            url = 'https://easylist-downloads.adblockplus.org/adblock_premium.txt';
          }
          if (url) {
            (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync - adding subscription ', url);
            // eslint-disable-next-line no-await-in-loop
            await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.add(url);
            _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.sync(url);
          }
        }
      }
    }

    if (payload.customFilterRules) {
      // capture, then remove all current custom filters, account for pause filters in
      // current processing
      let currentUserFilters = await getUserFilters();
      const onlyUserFilters = currentUserFilters.map(filter => filter.text);
      let results = [];
      for (const inx in payload.customFilterRules) {
        if (
          !_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.validate(payload.customFilterRules[inx])
          && !onlyUserFilters.includes(payload.customFilterRules[inx])
        ) {
          results.push(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.add([payload.customFilterRules[inx]]));
        }
      }
      await Promise.all(results);
      results = [];
      if (currentUserFilters && currentUserFilters.length) {
        currentUserFilters = cleanCustomFilter(currentUserFilters);
        // Delete / remove filters the user removed...
        if (currentUserFilters) {
          for (let i = 0; (i < currentUserFilters.length); i++) {
            const filter = currentUserFilters[i];
            if (!payload.customFilterRules.includes(filter.text)) {
              if (filter.text.length > 0) {
                if (!_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.validate(filter.text)) {
                  results.push(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.remove([filter.text]));
                }
              }
            }
          }
        }
      }
      await Promise.all(results);
    }
    if (payload.customRuleMetaData) {
      let currentUserFilters = await getUserFilters();
      currentUserFilters = currentUserFilters.map(filter => filter.text);
      for (const ruleText in payload.customRuleMetaData) {
        if (currentUserFilters.includes(ruleText)) {
          _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.setMetadata(ruleText, payload.customRuleMetaData[ruleText]);
        }
      }
    }
    if (payload.prefs) {
      for (const key in payload.prefs) {
        Prefs[key] = payload.prefs[key];
        // add any new Prefs to the array of Preferences we're tracking for sync
        if (abpPrefPropertyNames.indexOf(key) < 0) {
          abpPrefPropertyNames.push(key);
        }
        // since we no long use the 'show_statsinpopup' property on the |Prefs| object,
        // manually set Settings property for backward compatability
        if (key === 'show_statsinpopup') {
          (0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .setSetting */ .Lt)('display_menu_stats', payload.prefs[key]);
        }
      }
    }
    if (payload.channels) {
      for (const name in payload.channels) {
        const channelId = channels.getIdByName(name);
        if (channelId) {
          channels.setEnabled(channelId, payload.channels[name]);
        } else {
          // create a new channel to save the channel name and the enabled indicator
          channels.add({ name, param: undefined, enabled: payload.channels[name] });
        }
      }
    }
  };

  const process403ErrorCode = function () {
    // eslint-disable-next-line no-use-before-define
    disableSync(false);
  };

  // Retreive or 'get' the sync data from the sync server
  // Input: initialGet:boolean - if true, and the server returns a 404 error code,
  //                             then a 'post' is invoked
  //        disableEmitMsg:boolean - if true, then no sync notifier message will be emitted
  //                                 (usually used for post error processing)
  //        callback:function - function that will be called when success or failure occurs
  //        shouldForce:boolean - optional, force a response from the server (even if the commit
  //                              versions match), defaults to false
  const getSyncData = function (initialGet, disableEmitMsg, callback, shouldForce) {
    const getSuccess = function (text, statusCode) {
      let responseObj = {};
      if (text && typeof text === 'object') {
        responseObj = text;
      } else if (text && typeof text === 'string') {
        try {
          responseObj = JSON.parse(text);
        } catch (e) {
          // eslint-disable-next-line no-console
          console.log('Something went wrong with parsing license data.');
          // eslint-disable-next-line no-console
          console.log('error', e);
          // eslint-disable-next-line no-console
          console.log(text);
          return;
        }
      }
      if (responseObj && ((responseObj.commitVersion > syncCommitVersion) || shouldForce)) {
        if (responseObj.data) {
          try {
            processSyncUpdate(JSON.parse(responseObj.data));
          } catch (e) {
            // eslint-disable-next-line no-console
            console.log('failed to parse response data from server', responseObj.data);
            // eslint-disable-next-line no-console
            console.log(e);
          }
        }
        syncCommitVersion = responseObj.commitVersion;
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncCommitVersionKey, responseObj.commitVersion);
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncPreviousDataKey, responseObj.data);
        pendingPostData = false; // reset in case an update is received from another extension
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncPendingPostDataKey, pendingPostData);
      }
      if (!disableEmitMsg) {
        syncNotifier.emit('sync.data.receieved');
      }
      if (typeof callback === 'function') {
        callback(statusCode);
      }
    };

    const getFailure = function (statusCode, textStatus, responseJSON) {
      lastGetStatusCode = statusCode;
      lastGetErrorResponse = responseJSON;
      if (initialGet && statusCode === 404) {
        // eslint-disable-next-line no-use-before-define
        postDataSync(callback, initialGet);
        // now that the initial post is complete, enable Sync (add listeners, etc.)
        // with 'initialGet' now set to false
        // eslint-disable-next-line no-use-before-define
        enableSync();
        return;
      }
      if (initialGet && !disableEmitMsg) {
        syncNotifier.emit('sync.data.getting.error.initial.fail', statusCode);
      } else if (!disableEmitMsg) {
        syncNotifier.emit('sync.data.getting.error', statusCode, responseJSON);
        if (statusCode === 403) {
          process403ErrorCode();
        }
      }
      if (typeof callback === 'function') {
        callback(statusCode);
      }
    };

    if (!disableEmitMsg) {
      syncNotifier.emit('sync.data.getting');
    }
    lastGetStatusCode = 200;
    lastGetErrorResponse = {};
    // eslint-disable-next-line no-use-before-define
    requestSyncData(getSuccess, getFailure, undefined, shouldForce);
  };

  const getAllExtensionNames = function () {
    return new Promise(async (resolve) => {
      syncNotifier.emit('extension.names.downloading');
      fetch(`${_check__WEBPACK_IMPORTED_MODULE_3__/* .License.MAB_CONFIG.syncURL */ .Cz.MAB_CONFIG.syncURL}/devices/list`, {
        method: 'GET',
        cache: 'no-cache',
        headers: {
          'X-GABSYNC-PARAMS': JSON.stringify({
            extensionGUID: await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)(),
            licenseId: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId,
            extInfo: getExtensionInfo(),
          }),
        },
      })
        .then(async (response) => {
          if (response.ok) {
            const responseObj = await response.json();
            syncNotifier.emit('extension.names.downloaded', responseObj);
            resolve(responseObj);
            return;
          }
          if (response.status === 404) {
            syncNotifier.emit('extension.names.downloading.error', response.status);
            const text = await response.text();
            resolve(text);
            return;
          }
          (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync server error: ', response);
        })
        .catch((error) => {
          syncNotifier.emit('extension.names.downloading.error');
          (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync server returned error: ', error);
        });
    });
  };

  const setCurrentExtensionName = async function (newName) {
    if (newName && newName.trim().length >= 1 && newName.trim().length <= 50) {
      currentExtensionName = newName.trim();
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncExtensionNameKey, currentExtensionName);
      const thedata = {
        deviceName: currentExtensionName,
        extensionGUID: await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)(),
        licenseId: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId,
        extInfo: getExtensionInfo(),
      };
      syncNotifier.emit('extension.name.updating');
      (0,_fetch_util__WEBPACK_IMPORTED_MODULE_10__/* ["default"] */ .Z)(`${_check__WEBPACK_IMPORTED_MODULE_3__/* .License.MAB_CONFIG.syncURL */ .Cz.MAB_CONFIG.syncURL}/devices/add`, thedata)
        .then((response) => {
          if (response.ok) {
            syncNotifier.emit('extension.name.updated');
          } else {
            syncNotifier.emit('extension.name.updated.error', response.status);
          }
        })
        .catch((error) => {
          syncNotifier.emit('extension.name.updated.error');
          (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync server returned error: ', error);
        });
    }
  };
  const removeExtensionName = function (extensionName, extensionGUID) {
    const thedata = {
      deviceName: extensionName,
      extensionGUID,
      licenseId: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId,
      extInfo: getExtensionInfo(),
    };
    syncNotifier.emit('extension.name.remove');
    (0,_fetch_util__WEBPACK_IMPORTED_MODULE_10__/* ["default"] */ .Z)(`${_check__WEBPACK_IMPORTED_MODULE_3__/* .License.MAB_CONFIG.syncURL */ .Cz.MAB_CONFIG.syncURL}/devices/remove`, thedata)
      .then((response) => {
        if (response.ok) {
          if (extensionName === currentExtensionName) {
            currentExtensionName = '';
            (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncExtensionNameKey, currentExtensionName);
          }
          syncNotifier.emit('extension.name.removed');
        } else {
          syncNotifier.emit('extension.name.remove.error', response.status);
        }
      })
      .catch((error) => {
        syncNotifier.emit('extension.name.remove.error');
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync server returned error: ', error);
      });
  };


  const removeCurrentExtensionName = async function () {
    removeExtensionName(currentExtensionName, await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)());
  };

  // return all of the current user configurable extension options (settings, Prefs, filter list
  // sub, custom rules, themes, etc. Since a comparison will be done in this, and other sync'd
  // extensions, the payload should only contain settings, Prefs, etc and not data that can change
  // from browser to brower, version to version, etc.
  const getSyncInformation = async function () {
    const payload = {};
    payload.settings = (0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .getSettings */ .Gw)();
    payload.subscriptions = {};
    const subscriptions = await _subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__/* ["default"].getSubscriptionsMinusText */ .Z.getSubscriptionsMinusText();

    for (const adblockId in subscriptions) {
      if (subscriptions[adblockId].subscribed) {
        const { id } = subscriptions[adblockId];
        const url = _subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__/* ["default"].getV2URLFromID */ .Z.getV2URLFromID(id) || subscriptions[adblockId].url;
        if (adblockId === 'distraction-control') {
          const dcIDs = _subscriptionadapter__WEBPACK_IMPORTED_MODULE_5__/* ["default"].legacyDistractionControlIDs */ .Z.legacyDistractionControlIDs;
          for (const [dcID, dcURL] of Object.entries(dcIDs)) {
            payload.subscriptions[dcID] = dcURL;
          }
        } else if (sendFilterListByURL.includes(adblockId)) {
          payload.subscriptions[`url:${url}`] = url;
        } else {
          payload.subscriptions[adblockId] = url;
        }
      }
    }
    let userFilters = await getUserFilters();
    userFilters = userFilters.map(filter => filter.text).sort();
    payload.customFilterRules = cleanCustomFilter(userFilters);

    const metaDataArr = await getCustomFilterMetaData();
    if (metaDataArr && metaDataArr.length) {
      const ruleMetaData = {};
      for (let inx = 0; inx < metaDataArr.length; inx++) {
        if (metaDataArr[inx].text && metaDataArr[inx].metaData) {
          ruleMetaData[metaDataArr[inx].text] = metaDataArr[inx].metaData;
        }
      }
      payload.customRuleMetaData = ruleMetaData;
    }
    payload.prefs = {};
    for (const inx in abpPrefPropertyNames) {
      const name = abpPrefPropertyNames[inx];
      payload.prefs[name] = Prefs[name];
    }
    // since we no long use the 'show_statsinpopup' property on the |Prefs| object,
    // manually set it using the new 'show_statsinpopup' property on the Settings object
    // for backward compatability
    payload.prefs.show_statsinpopup = (0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .getSettings */ .Gw)().display_menu_stats;
    payload.channels = {};
    const guide = channels.getGuide();
    for (const id in guide) {
      payload.channels[guide[id].name] = guide[id].enabled;
    }
    (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync - sync payload', payload);
    return payload;
  };

  const postDataSync = async function (callback, initialGet) {
    if (!(0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .getSettings */ .Gw)().sync_settings) {
      return;
    }
    const payload = await getSyncInformation();
    const thedata = {
      data: JSON.stringify(payload),
      commitVersion: syncCommitVersion,
      extensionGUID: await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)(),
      licenseId: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId,
      extInfo: getExtensionInfo(),
    };
    browser.storage.local.get(syncPreviousDataKey).then((response) => {
      const previousData = response[syncPreviousDataKey] || '{}';
      if (objectComparison(payload, JSON.parse(previousData))) {
        return;
      }
      syncNotifier.emit('post.data.sending');
      lastPostStatusCode = 200;
      pendingPostData = false;
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncPendingPostDataKey, pendingPostData);
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sending sync \'payload\' to server', thedata);
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sending sync \'thedata\' to server', payload);
      (0,_fetch_util__WEBPACK_IMPORTED_MODULE_10__/* ["default"] */ .Z)(_check__WEBPACK_IMPORTED_MODULE_3__/* .License.MAB_CONFIG.syncURL */ .Cz.MAB_CONFIG.syncURL, thedata).then((postResponse) => {
        lastPostStatusCode = postResponse.status;
        if (postResponse.ok) {
          postResponse.json().then((responseObj) => {
            if (responseObj && responseObj.commitVersion > syncCommitVersion) {
              syncCommitVersion = responseObj.commitVersion;
              (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncCommitVersionKey, responseObj.commitVersion);
            }
            (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncPreviousDataKey, responseObj.data);
            if (typeof callback === 'function') {
              callback();
            }
            syncNotifier.emit('post.data.sent');
          });
        } else {
          syncNotifier.emit('post.data.sent.error', postResponse.status, initialGet);
          lastPostStatusCode = postResponse.status;
          if (postResponse.status === 409) {
            // this extension probably had an version of the sync data
            // aka - the sync commit version was behind the sync server
            // so, undo / revert all of the user changes that were just posted
            // by doing a 'GET'
            // because we want the above error to be persisted, will set the
            // 'disableEmitMsg' to true
            getSyncData(false, true);
            return;
          }
          if (postResponse.status === 403) {
            process403ErrorCode();
          }
          // all other currently known errors (0, 401, 404, 500).
          pendingPostData = true;
          (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncPendingPostDataKey, pendingPostData);
        }
      })
        .catch((error) => {
          syncNotifier.emit('extension.name.updated.error');
          // eslint-disable-next-line no-console
          console.log('sync server returned error: ', error);
        });
    });
  };

  const processUserSyncRequest = function () {
    if (pendingPostData) {
      postDataSync();
    } else {
      getSyncData(false, false, undefined, true);
    }
  };

  const processEventChangeRequest = function () {
    if (pendingPostData) {
      postDataSync();
    } else {
      getSyncData();
    }
  };

  const postDataSyncHandler = debounced(debounceWaitTime, postDataSync);

  // Sync Listeners
  function onFilterAdded(filter, subscription, position, calledPreviously) {
    // a delay is added to allow the domain pause filters time to be saved to storage
    // otherwise the domain pause filter check below would always fail
    if (calledPreviously === undefined) {
      setTimeout(() => {
        onFilterAdded(filter, subscription, position, true);
      }, 500);
      return;
    }
    if (isPauseFilter(filter.text)) {
      return;
    }
    if (isDomainPauseFilter(filter.text)) {
      storedSyncDomainPauses.push(filter.text);
      return;
    }
    postDataSyncHandler();
  }

  function onFilterRemoved(filter) {
    if (isPauseFilter(filter.text)) {
      return;
    }
    if (isDomainPauseFilter(filter.text)) {
      const filterTextIndex = storedSyncDomainPauses.indexOf(filter.text);
      storedSyncDomainPauses = storedSyncDomainPauses.slice(filterTextIndex);
      return;
    }
    postDataSyncHandler();
  }

  // a delay is added to allow the domain pause filters time to be saved to storage
  // otherwise the domain pause filter check below would always fail
  const onFilterListsSubAdded = function (sub, calledPreviously) {
    (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('onFilterListsSubAdded', sub);
    if (calledPreviously === undefined) {
      setTimeout(() => {
        onFilterListsSubAdded(sub, true);
      }, 1000);
      return;
    }
    let containsPauseFilter = false;
    if (sub.url && sub.url.startsWith('~user~') && sub._filterText.length) {
      const arrayLength = sub._filterText.length;
      for (let i = 0; i < arrayLength; i++) {
        const filter = sub._filterText[i];
        containsPauseFilter = isPauseFilter(filter);
        if (!containsPauseFilter && isDomainPauseFilter(filter)) {
          containsPauseFilter = true;
          storedSyncDomainPauses.push(filter.text);
        }
      }
    }
    if (containsPauseFilter) {
      return;
    }
    postDataSyncHandler();
  };

  const onFilterListsSubRemoved = function (sub) {
    let containsPauseFilter = false;
    if (sub.url && sub.url.startsWith('~user~') && sub._filterText.length) {
      const arrayLength = sub._filterText.length;
      for (let i = 0; i < arrayLength; i++) {
        const filter = sub._filterText[i];
        containsPauseFilter = isPauseFilter(filter);
        if (!containsPauseFilter && isDomainPauseFilter(filter.text)) {
          containsPauseFilter = true;
          const filterTextIndex = storedSyncDomainPauses.indexOf(filter.text);
          storedSyncDomainPauses = storedSyncDomainPauses.slice(filterTextIndex);
          return;
        }
      }
    }
    if (containsPauseFilter) {
      return;
    }
    postDataSyncHandler();
  };

  const onSettingsChanged = function (name) {
    if (name === 'sync_settings') {
      return; // don't process any sync setting changes
    }
    postDataSyncHandler();
  };

  const updateNetworkStatus = function () {
    if (navigator.onLine) {
      processEventChangeRequest();
    }
  };

  function processFetchRequest(commitVersion) {
    let fetchCommitVersion = commitVersion;
    if (!fetchCommitVersion) {
      return;
    }
    if (typeof fetchCommitVersion === 'string') {
      fetchCommitVersion = Number.parseInt(fetchCommitVersion, 10);
    }
    if (fetchCommitVersion === syncCommitVersion) {
      return;
    }
    getSyncData();
  }

  async function enablePubNub() {
    pubnub = new PubNub({
      subscribeKey: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.MAB_CONFIG.subscribeKey */ .Cz.MAB_CONFIG.subscribeKey,
      authKey: `${_check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId}_${await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)()}`,
      ssl: true,
    });

    pubnub.addListener({
      message(response) {
        if (response.message && response.message && response.message.commitVersion) {
          processFetchRequest(response.message.commitVersion);
        }
      },
      status(msg) {
        if (msg.category === 'PNNetworkUpCategory') {
          pubnub.subscribe({
            channels: [_check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId],
          });
        }
        if (msg.error === true && msg.category && msg.operation) {
          _servermessages__WEBPACK_IMPORTED_MODULE_7__/* ["default"].recordGeneralMessage */ .Z.recordGeneralMessage('pubnub_error', undefined, { licenseId: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId, category: msg.category, operation: msg.operation });
        }
      },
    });

    pubnub.subscribe({
      channels: [_check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId],
    });
  }

  const enableSync = function (initialGet) {
    (0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .setSetting */ .Lt)('sync_settings', true);
    const addListeners = function () {
      syncNotifier.on('sync.data.getting.error', onSyncDataGettingErrorAddLogEntry);
      syncNotifier.on('sync.data.getting.error.initial.fail', onSyncDataGettingErrorInitialFailAddLogEntry);
      syncNotifier.on('extension.names.downloading', onExtensionNamesDownloadingAddLogEntry);
      syncNotifier.on('sync.data.receieved', onSyncDataReceievedAddLogEntry);
      syncNotifier.on('sync.data.getting', onSyncDataGettingAddLogEntry);
      syncNotifier.on('post.data.sent.error', onPostDataSentErrorAddLogEntry);
      syncNotifier.on('post.data.sending', onPostDataSendingAddLogEntry);
      syncNotifier.on('post.data.sent', onPostDataSentAddLogEntry);
      syncNotifier.on('extension.name.remove.error', onExtensionNamesRemoveErrorAddLogEntry);
      syncNotifier.on('extension.name.removed', onExtensionNameRemovedAddLogEntry);
      syncNotifier.on('extension.name.remove', onExtensionNameRemoveAddLogEntry);
      syncNotifier.on('extension.name.updated.error', onExtensionNameUpdatedErrorAddLogEntry);
      syncNotifier.on('extension.name.updated', onExtensionNameUpdatedAddLogEntry);
      syncNotifier.on('extension.name.updating', onExtensionNameUpdatingAddLogEntry);
      syncNotifier.on('extension.names.downloaded', onExtensionNamesDownloadedAddLogEntry);
      syncNotifier.on('extension.names.downloading.error', onExtensionNamesDownloadingErrorAddLogEntry);

      // eslint-disable-next-line no-use-before-define
      _check__WEBPACK_IMPORTED_MODULE_3__/* .License.licenseNotifier.on */ .Cz.licenseNotifier.on('license.expired', processDisableSync);

      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.onAdded.addListener(onFilterListsSubAdded);
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.onRemoved.addListener(onFilterListsSubRemoved);

      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.onAdded.addListener(onFilterAdded);
      _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.onRemoved.addListener(onFilterRemoved);

      _prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .settingsNotifier.on */ .Pg.on('settings.changed', onSettingsChanged);
      _channels__WEBPACK_IMPORTED_MODULE_4__/* .channelsNotifier.on */ .l.on('channels.changed', postDataSyncHandler);

      for (const inx in abpPrefPropertyNames) {
        const name = abpPrefPropertyNames[inx];
        Prefs.on(name, postDataSyncHandler);
      }
      // wait a moment at start to allow all of the backgound scripts to load
      setTimeout(() => {
        enablePubNub();
      }, 1000);

      window.addEventListener('online', updateNetworkStatus);
      window.addEventListener('offline', updateNetworkStatus);
    };

    if (initialGet) {
      SyncService.getSyncData(initialGet, false, (response) => {
        if (response === 200 || response === 304) {
          addListeners();
        }
      });
      return;
    }

    addListeners();
  };

  function disablePubNub() {
    if (!pubnub) {
      return;
    }

    pubnub.removeAllListeners();
    pubnub.unsubscribeAll();
    pubnub = undefined;
  }

  const disableSync = function (removeName) {
    (0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .setSetting */ .Lt)('sync_settings', false);
    syncCommitVersion = 0;
    disablePubNub();
    _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.onAdded.removeListener(onFilterListsSubAdded);
    _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.subscriptions.onRemoved.removeListener(onFilterListsSubRemoved);

    _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.onAdded.removeListener(onFilterAdded);
    _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_2__.filters.onRemoved.removeListener(onFilterRemoved);

    _prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .settingsNotifier.off */ .Pg.off('settings.changed', onSettingsChanged);
    _channels__WEBPACK_IMPORTED_MODULE_4__/* .channelsNotifier.off */ .l.off('channels.changed', postDataSyncHandler);

    for (const inx in abpPrefPropertyNames) {
      const name = abpPrefPropertyNames[inx];
      Prefs.off(name, postDataSyncHandler);
    }

    storedSyncDomainPauses = [];
    if (removeName) {
      removeCurrentExtensionName();

      currentExtensionName = '';
      (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .chromeStorageSetHelper */ .rJ)(syncExtensionNameKey, currentExtensionName);
    }

    syncNotifier.off('sync.data.getting.error', onSyncDataGettingErrorAddLogEntry);
    syncNotifier.off('sync.data.getting.error.initial.fail', onSyncDataGettingErrorInitialFailAddLogEntry);
    syncNotifier.off('extension.names.downloading', onExtensionNamesDownloadingAddLogEntry);
    syncNotifier.off('sync.data.receieved', onSyncDataReceievedAddLogEntry);
    syncNotifier.off('sync.data.getting', onSyncDataGettingAddLogEntry);
    syncNotifier.off('post.data.sent.error', onPostDataSentErrorAddLogEntry);
    syncNotifier.off('post.data.sending', onPostDataSendingAddLogEntry);
    syncNotifier.off('post.data.sent', onPostDataSentAddLogEntry);
    syncNotifier.off('extension.name.remove.error', onExtensionNamesRemoveErrorAddLogEntry);
    syncNotifier.off('extension.name.removed', onExtensionNameRemovedAddLogEntry);
    syncNotifier.off('extension.name.remove', onExtensionNameRemoveAddLogEntry);
    syncNotifier.off('extension.name.updated.error', onExtensionNameUpdatedErrorAddLogEntry);
    syncNotifier.off('extension.name.updated', onExtensionNameUpdatedAddLogEntry);
    syncNotifier.off('extension.name.updating', onExtensionNameUpdatingAddLogEntry);
    syncNotifier.off('extension.names.downloaded', onExtensionNamesDownloadedAddLogEntry);
    syncNotifier.off('extension.names.downloading.error', onExtensionNamesDownloadingErrorAddLogEntry);

    // eslint-disable-next-line no-use-before-define
    _check__WEBPACK_IMPORTED_MODULE_3__/* .License.licenseNotifier.off */ .Cz.licenseNotifier.off('license.expired', processDisableSync);
    window.removeEventListener('online', updateNetworkStatus);
    window.removeEventListener('offline', updateNetworkStatus);
  };

  const processDisableSync = function () {
    disableSync(true);
  };

  // Retreive the sync data from the sync server
  // Input: successCallback:function - function that will be called when success occurs, the
  //                                   callback will be provided the response data
  //        errorCallback:function - function that will be called when  failure occurs, the
  //                                 callback will be provided the error code
  //        totalAttempts:integer - the number of 'get' attempts made (only used internally by
  //                               the retry logic)
  //        shouldForce:boolean - optional, force a response from the server (even if the commit
  //                              versions match), defaults to false
  const requestSyncData = async function (
    successCallback,
    errorCallback,
    totalAttempts,
    shouldForce,
  ) {
    let attemptCount = totalAttempts;
    if (!attemptCount) {
      attemptCount = 1;
    } else {
      attemptCount += 1;
    }
    const forceParam = shouldForce || false;

    fetch(_check__WEBPACK_IMPORTED_MODULE_3__/* .License.MAB_CONFIG.syncURL */ .Cz.MAB_CONFIG.syncURL, {
      method: 'GET',
      cache: 'no-cache',
      headers: {
        'X-GABSYNC-PARAMS': JSON.stringify({
          extensionGUID: await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)(),
          licenseId: _check__WEBPACK_IMPORTED_MODULE_3__/* .License.get */ .Cz.get().licenseId,
          commitVersion: syncCommitVersion,
          force: forceParam,
          extInfo: getExtensionInfo(),
        }),
      },
    })
      .then(async (response) => {
        if (response.ok && typeof successCallback === 'function') {
          const text = await response.text();
          successCallback(text, response.status);
        }
        if (!response.ok) {
          (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync server returned error, status', response.status);
          if (response.status === 304) {
            (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('response', response);
            return;
          }
          if ((response.status !== 404 || response.status !== 403) && attemptCount < 3) {
            setTimeout(() => {
              requestSyncData(successCallback, errorCallback, attemptCount, shouldForce);
            }, 1000); // wait 1 second for retry
            return;
          }
          if (typeof errorCallback === 'function') {
            const responseObj = await response.json();
            errorCallback(response.status, response.status, responseObj);
          }
        }
      })
      .catch((error) => {
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_8__/* .log */ .cM)('sync server returned error: ', error);
        errorCallback(error.message);
      });
  };

  _prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .settings.onload */ .Xd.onload().then(() => {
    _check__WEBPACK_IMPORTED_MODULE_3__/* .License.ready */ .Cz.ready().then(() => {
      if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_6__/* .getSettings */ .Gw)().sync_settings) {
        browser.storage.local.get(syncCommitVersionKey).then((response) => {
          syncCommitVersion = response[syncCommitVersionKey] || 0;
          browser.storage.local.get(syncPendingPostDataKey).then((postDataResponse) => {
            pendingPostData = postDataResponse[syncPendingPostDataKey] || false;
            processEventChangeRequest();
            enableSync();
            migrateSyncLog();
          });
        });
      }

      browser.storage.local.get(syncExtensionNameKey).then((response) => {
        currentExtensionName = response[syncExtensionNameKey] || '';
      });
    });
  });

  return {
    enableSync,
    disableSync,
    getSyncData,
    processFetchRequest,
    getCurrentExtensionName,
    getAllExtensionNames,
    setCurrentExtensionName,
    removeCurrentExtensionName,
    removeExtensionName,
    syncNotifier,
    getCommitVersion,
    setCommitVersion,
    getLastPostStatusCode,
    resetLastPostStatusCode,
    setLastPostStatusCode,
    getLastGetStatusCode,
    resetLastGetStatusCode,
    setLastGetStatusCode,
    getLastGetErrorResponse,
    resetLastGetErrorResponse,
    setLastGetErrorResponse,
    resetAllErrors,
    getSyncLog,
    deleteSyncLog,
    processUserSyncRequest,
    processEventChangeRequest,
    addSyncLogText,
  };
}());

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (SyncService);


/***/ }),

/***/ 1648:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Gw": () => (/* reexport */ settings/* getSettings */.Gw),
  "uR": () => (/* reexport */ settings/* isValidTheme */.uR),
  "uF": () => (/* binding */ background_migrateUserData),
  "Lt": () => (/* reexport */ settings/* setSetting */.Lt),
  "Xd": () => (/* reexport */ settings/* settings */.Xd),
  "Pg": () => (/* reexport */ settings/* settingsNotifier */.Pg)
});

// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
;// CONCATENATED MODULE: ./adblock-betafish/prefs/background/migration.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */
/* For ESLint: List any global identifiers used in this file below */
/* global browser  */
/**
 * @overview Migrates existing data from older versions
 */



async function unsubscribeToFilterList(url) {
  if (await ewe_api.subscriptions.has(url)) {
    await ewe_api.subscriptions.remove(url);
    return true;
  }
  return false;
}

/**
 * Migrates existing user data from older versions
 */
async function migrateUserData() {
  // We remove the AdBlock Custom filter list,
  // because it no longer serves any purpose
  unsubscribeToFilterList('https://cdn.adblockcdn.com/filters/adblock_custom.txt');

  // Remove any of the old DC filters,
  // Subscript to the new DC filter list
  const DISTRACTION_CONTROL_URL_LIST = [
    'https://easylist-downloads.adblockplus.org/v3/full/distraction-control-newsletter.txt',
    'https://cdn.adblockcdn.com/filters/distraction-control-newsletter.txt',
    'https://easylist-downloads.adblockplus.org/v3/full/distraction-control-push.txt',
    'https://cdn.adblockcdn.com/filters/distraction-control-push.txt',
    'https://easylist-downloads.adblockplus.org/v3/full/distraction-control-survey.txt',
    'https://cdn.adblockcdn.com/filters/distraction-control-survey.txt',
    'https://easylist-downloads.adblockplus.org/v3/full/distraction-control-video.txt',
    'https://cdn.adblockcdn.com/filters/distraction-control-video.txt',
  ];
  let subscribedTODC = false;
  for (const url of DISTRACTION_CONTROL_URL_LIST) {
    // eslint-disable-next-line no-await-in-loop
    subscribedTODC = await unsubscribeToFilterList(url);
  }

  if (subscribedTODC) {
    if (browser.runtime.getManifest().manifest_version === 2) {
      ewe_api.subscriptions.add('https://easylist-downloads.adblockplus.org/adblock_premium.txt');
    }
    if (browser.runtime.getManifest().manifest_version === 3) {
      ewe_api.subscriptions.add('https://easylist-downloads.adblockplus.org/v3/full/adblock_premium.txt');
    }
  }
}

/* harmony default export */ const migration = ({
  migrateUserData,
});

// EXTERNAL MODULE: ./adblock-betafish/prefs/background/settings.js
var settings = __webpack_require__(7330);
;// CONCATENATED MODULE: ./adblock-betafish/prefs/background/index.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */





const { migrateUserData: background_migrateUserData } = migration;


/***/ }),

/***/ 7330:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Gw": () => (/* binding */ getSettings),
/* harmony export */   "Lt": () => (/* binding */ setSetting),
/* harmony export */   "Pg": () => (/* binding */ settingsNotifier),
/* harmony export */   "Xd": () => (/* binding */ settings),
/* harmony export */   "uR": () => (/* binding */ isValidTheme)
/* harmony export */ });
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(9876);
/* harmony import */ var _utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7337);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser */





const settingsNotifier = new _vendor_adblockplusui_adblockpluschrome_lib_events__WEBPACK_IMPORTED_MODULE_1__/* .EventEmitter */ .v();
const abpPrefPropertyNames = ['show_statsinicon', 'shouldShowBlockElementMenu', 'show_devtools_panel'];
const validThemes = ['default_theme', 'dark_theme', 'watermelon_theme', 'solarized_theme', 'solarized_light_theme', 'rebecca_purple_theme', 'ocean_theme', 'sunshine_theme'];


// OPTIONAL SETTINGS
function Settings() {
  this.settingsKey = 'settings';
  this.defaults = {
    debug_logging: false,
    youtube_channel_whitelist: true,
    youtube_manage_subscribed: true,
    show_advanced_options: false,
    show_block_counts_help_link: true,
    display_menu_stats: true,
    show_survey: true,
    local_cdn: false,
    picreplacement: false,
    twitch_hiding: false,
    onpageMessages: true,
    color_themes: {
      popup_menu: 'default_theme',
      options_page: 'default_theme',
    },
  };
  const that = this;
  this.init = new Promise(((resolve) => {
    browser.storage.local.get(that.settingsKey).then((response) => {
      const settings = response.settings || {};
      that.data = (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__/* .extend */ .l7)(that.defaults, settings);
      if (settings.debug_logging) {
        (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__/* .logging */ .PW)(true);
      }
      if ('managed' in browser.storage) {
        browser.storage.managed.get(null).then((items) => {
          for (const key in items) {
            if (key === 'suppress_update_page' || key === 'suppress_surveys' || key === 'suppress_first_run_page') {
              that.data[key] = items[key];
            }
          }
          resolve();
        },
        // Opera and FF doesn't support browser.storage.managed, but instead of simply
        // removing the API, it gives an asynchronous error which we ignore here.
        () => {
          resolve();
        });
      } else {
        resolve();
      }
    });
  })).then(() => {
    (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__/* .log */ .cM)('\n===SETTINGS FINISHED LOADING===\n\n');
  });
}

Settings.prototype = {
  set(name, isEnabled, callback) {
    const originalValue = this.data[name];
    // Firefox passes weak references to objects, so in case isEnabled is an object,
    // we need to store a local copy of the object
    const localIsEnabled = JSON.parse(JSON.stringify(isEnabled));
    this.data[name] = localIsEnabled;
    const that = this;

    // Don't store defaults that the user hasn't modified
    browser.storage.local.get(this.settingsKey).then((response) => {
      const storedData = response.settings || {};

      storedData[name] = localIsEnabled;
      (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__/* .chromeStorageSetHelper */ .rJ)(that.settingsKey, storedData);
      if (originalValue !== localIsEnabled) {
        settingsNotifier.emit('settings.changed', name, localIsEnabled, originalValue);
      }
      if (callback !== undefined && typeof callback === 'function') {
        callback();
      }
    });
  },

  getAll() {
    return this.data;
  },

  onload() {
    return this.init;
  },

};

const settings = new Settings();

const getSettings = function () {
  return settings.getAll();
};

const setSetting = function (name, isEnabled, callback) {
  settings.set(name, isEnabled, callback);

  if (name === 'debug_logging') {
    (0,_utilities_background_bg_functions__WEBPACK_IMPORTED_MODULE_0__/* .logging */ .PW)(isEnabled);
  }
};

const disableSetting = function (name) {
  settings.set(name, false);
};

const isValidTheme = themeName => validThemes.includes(themeName);

// Attach methods to window
// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  disableSetting,
  getSettings,
  setSetting,
  settings,
  settingsNotifier,
  abpPrefPropertyNames,
  isValidTheme,
});


/***/ }),

/***/ 2559:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "Z": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _utilities_background_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9555);
/* harmony import */ var _id_background_index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6703);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser  */




// Log an 'error' message on GAB log server.
const ServerMessages = (function serverMessages() {
  const { flavor } = (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .getUserAgentInfo */ .K1)();
  const { os } = (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .getUserAgentInfo */ .K1)();
  // Log a message on GAB log server. The user's userid will be prepended to the
  // message.
  // If callback() is specified, call callback() after logging has completed
  const sendMessageToLogServer = function (payload, callback) {
    fetch('https://log.getadblock.com/v2/record_log.php', {
      method: 'POST',
      cache: 'no-cache',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(payload),
    })
      .then(() => {
        if (typeof callback === 'function') {
          callback();
        }
      })
      .catch((error) => {
        (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .log */ .cM)('message server returned error: ', error);
      });
  };

  // Log a message on GAB log server. The user's userid will be prepended to the
  // message.
  // If callback() is specified, call callback() after logging has completed
  const recordMessageWithUserID = async function (msg, queryType, callback, additionalParams) {
    if (!msg || !queryType) {
      return;
    }
    const payload = {
      u: await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)(),
      f: flavor,
      o: os,
      l: (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .determineUserLanguage */ .pN)(),
      t: queryType,
      v: browser.runtime.getManifest().version,
    };
    if (typeof additionalParams === 'object') {
      for (const prop in additionalParams) {
        payload[prop] = additionalParams[prop];
      }
    }
    const eventWithPayload = { event: msg, payload };
    sendMessageToLogServer(eventWithPayload, callback);
  };

  // Log a message on GAB log server.
  // If callback() is specified, call callback() after logging has completed
  const recordAnonymousMessage = function (msg, queryType, callback, additionalParams) {
    if (!msg || !queryType) {
      return;
    }
    const payload = {
      f: flavor,
      o: os,
      l: (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .determineUserLanguage */ .pN)(),
      t: queryType,
    };
    if (typeof additionalParams === 'object') {
      for (const prop in additionalParams) {
        payload[prop] = additionalParams[prop];
      }
    }
    const eventWithPayload = { event: msg, payload };
    sendMessageToLogServer(eventWithPayload, callback);
  };

  // Log a error message on GAB log server.
  // If callback() is specified, call callback() after logging has completed
  const recordAnonymousErrorMessage = function (msg, callback, additionalParams) {
    if (!msg) {
      return;
    }
    const payload = {
      f: flavor,
      o: os,
      l: (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .determineUserLanguage */ .pN)(),
      t: 'error',
    };
    if (typeof additionalParams === 'object') {
      for (const prop in additionalParams) {
        payload[prop] = additionalParams[prop];
      }
    }
    const eventWithPayload = { event: msg, payload };
    sendMessageToLogServer(eventWithPayload, callback);
  };

  const recordErrorMessage = function (msg, callback, additionalParams) {
    void recordMessageWithUserID(msg, 'error', callback, additionalParams);
  };

  // Log an 'status' related message on GAB log server.
  const recordStatusMessage = function (msg, callback, additionalParams) {
    void recordMessageWithUserID(msg, 'stats', callback, additionalParams);
  };

  // Log a 'general' message on GAB log server.
  const recordGeneralMessage = function (msg, callback, additionalParams) {
    void recordMessageWithUserID(msg, 'general', callback, additionalParams);
  };

  // Log a 'adreport' message on GAB log server.
  const recordAdreportMessage = function (msg, callback, additionalParams) {
    void recordMessageWithUserID(msg, 'adreport', callback, additionalParams);
  };

  // Send an error message to the backup log server. This is to be used when
  // there's fetch failure.  It may fail as well depending on the failure,
  // and state of the local computer & network
  const sendMessageToBackupLogServer = async function (msg, errorMsg, queryType = 'error') {
    const payload = {
      u: await (0,_id_background_index__WEBPACK_IMPORTED_MODULE_1__/* .getUserId */ .n)(),
      f: flavor,
      o: os,
      l: (0,_utilities_background_index__WEBPACK_IMPORTED_MODULE_0__/* .determineUserLanguage */ .pN)(),
      t: queryType,
      v: browser.runtime.getManifest().version,
      error: errorMsg,
    };
    const eventWithPayload = { event: msg, payload };
    fetch('https://192.241.161.10/v2/record_log.php', {
      method: 'POST',
      cache: 'no-cache',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(eventWithPayload),
    });
  };

  return {
    recordErrorMessage,
    recordAnonymousMessage,
    recordAnonymousErrorMessage,
    recordStatusMessage,
    recordGeneralMessage,
    recordAdreportMessage,
    sendMessageToBackupLogServer,
  };
}());

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (ServerMessages);


/***/ }),

/***/ 1974:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "Z": () => (/* binding */ subscriptionadapter)
});

// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
;// CONCATENATED MODULE: ./adblock-betafish/data/betafish-subscriptions.json
const betafish_subscriptions_namespaceObject = JSON.parse('{"https://easylist-downloads.adblockplus.org/exceptionrules.txt":{"id":"0798B6A2-94A4-4ADF-89ED-BEC112FC4C7F","adblockId":"acceptable_ads","index":1},"https://easylist-downloads.adblockplus.org/v3/full/exceptionrules.txt":{"id":"0798B6A2-94A4-4ADF-89ED-BEC112FC4C7F","adblockId":"acceptable_ads","index":1},"https://easylist-downloads.adblockplus.org/exceptionrules-privacy-friendly.txt":{"id":"F12E0801-A00B-49DE-B1E3-52C9C4F90C8C","adblockId":"acceptable_ads_privacy","index":2},"https://easylist-downloads.adblockplus.org/v3/full/exceptionrules-privacy-friendly.txt":{"id":"F12E0801-A00B-49DE-B1E3-52C9C4F90C8C","adblockId":"acceptable_ads_privacy","index":2},"https://easylist-downloads.adblockplus.org/v3/full/adblock_premium.txt":{"id":"CDAD4CF5-2706-42CB-B404-F5B9B61B8CAA","mv2URL":"https://easylist-downloads.adblockplus.org/adblock_premium.txt","adblockId":"distraction-control","index":4},"https://easylist-downloads.adblockplus.org/adblock_premium.txt":{"id":"CDAD4CF5-2706-42CB-B404-F5B9B61B8CAA","mv2URL":"https://easylist-downloads.adblockplus.org/adblock_premium.txt","adblockId":"distraction-control","index":4},"https://easylist-downloads.adblockplus.org/v3/full/nocoin.txt":{"adblockId":"bitcoin_mining_protection","id":"9CC3AF4D-EB89-4100-97C6-4EEE4F8A2E82","index":8},"https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/nocoin.txt":{"adblockId":"bitcoin_mining_protection","id":"9CC3AF4D-EB89-4100-97C6-4EEE4F8A2E82","index":8},"https://easylist-downloads.adblockplus.org/antiadblockfilters.txt":{"adblockId":"warning_removal","index":9},"https://easylist-downloads.adblockplus.org/v3/full/abpindo+easylist.txt":{"id":"B7D76369-DD19-4602-80E8-2E32DDB490AC","adblockId":"easylist_plus_indonesian","index":13},"https://easylist-downloads.adblockplus.org/abpindo+easylist.txt":{"id":"B7D76369-DD19-4602-80E8-2E32DDB490AC","adblockId":"easylist_plus_indonesian","index":13},"https://easylist-downloads.adblockplus.org/v3/full/abpvn+easylist.txt":{"id":"1C571EC7-6E52-47CC-B04A-4B3008D0AEBE","adblockId":"easylist_plus_vietnamese","index":14},"https://easylist-downloads.adblockplus.org/abpvn+easylist.txt":{"id":"1C571EC7-6E52-47CC-B04A-4B3008D0AEBE","adblockId":"easylist_plus_vietnamese","index":14},"https://easylist-downloads.adblockplus.org/v3/full/bulgarian_list+easylist.txt":{"id":"E22C3B40-DC90-49D7-8BF5-E60904AB159A","adblockId":"easylist_plus_bulgarian","index":15},"https://easylist-downloads.adblockplus.org/bulgarian_list+easylist.txt":{"id":"E22C3B40-DC90-49D7-8BF5-E60904AB159A","adblockId":"easylist_plus_bulgarian","index":15},"https://easylist-downloads.adblockplus.org/easylist.txt":{"id":"8C13E995-8F06-4927-BEA7-6C845FB7EEBF","adblockId":"easylist","index":16},"https://easylist-downloads.adblockplus.org/v3/full/easylist.txt":{"id":"8C13E995-8F06-4927-BEA7-6C845FB7EEBF","adblockId":"easylist","index":16},"https://easylist-downloads.adblockplus.org/v3/full/easylistchina+easylist.txt":{"id":"9BD3EA2F-889D-4CC3-B680-CF484F2BD1B9","adblockId":"chinese","index":17},"https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt":{"id":"9BD3EA2F-889D-4CC3-B680-CF484F2BD1B9","adblockId":"chinese","index":17},"https://easylist-downloads.adblockplus.org/v3/full/easylistczechslovak+easylist.txt":{"id":"4B6CE485-30AB-4213-AD17-504B3F2D2825","adblockId":"czech","index":18},"https://easylist-downloads.adblockplus.org/easylistczechslovak+easylist.txt":{"id":"4B6CE485-30AB-4213-AD17-504B3F2D2825","adblockId":"czech","index":18},"https://easylist-downloads.adblockplus.org/v3/full/easylistdutch+easylist.txt":{"id":"A4B88FB6-E5E5-417F-8A49-20B8244995FD","adblockId":"dutch","index":19},"https://easylist-downloads.adblockplus.org/easylistdutch+easylist.txt":{"id":"A4B88FB6-E5E5-417F-8A49-20B8244995FD","adblockId":"dutch","index":19},"https://easylist-downloads.adblockplus.org/v3/full/easylistgermany+easylist.txt":{"id":"0CD3D105-D3B3-4652-8489-94163DE9A08F","adblockId":"easylist_plus_german","index":20},"https://easylist-downloads.adblockplus.org/easylistgermany+easylist.txt":{"id":"0CD3D105-D3B3-4652-8489-94163DE9A08F","adblockId":"easylist_plus_german","index":20},"https://easylist-downloads.adblockplus.org/v3/full/israellist+easylist.txt":{"id":"07549D8B-F06F-4D9D-A567-929AA59E9D1D","adblockId":"israeli","index":21},"https://easylist-downloads.adblockplus.org/israellist+easylist.txt":{"id":"07549D8B-F06F-4D9D-A567-929AA59E9D1D","adblockId":"israeli","index":21},"https://easylist-downloads.adblockplus.org/v3/full/easylistitaly+easylist.txt":{"id":"BBC07C05-66F1-42EC-BD4D-7AD495FAC84B","adblockId":"italian","index":22},"https://easylist-downloads.adblockplus.org/easylistitaly+easylist.txt":{"id":"BBC07C05-66F1-42EC-BD4D-7AD495FAC84B","adblockId":"italian","index":22},"https://easylist-downloads.adblockplus.org/v3/full/easylistlithuania+easylist.txt":{"id":"CBE50FA2-DE3F-480C-B1D7-04289391C033","adblockId":"easylist_plus_lithuania","index":23},"https://easylist-downloads.adblockplus.org/easylistlithuania+easylist.txt":{"id":"CBE50FA2-DE3F-480C-B1D7-04289391C033","adblockId":"easylist_plus_lithuania","index":23},"https://easylist-downloads.adblockplus.org/v3/full/easylistpolish+easylist.txt":{"id":"3D2C09D0-DF1C-4C8E-9947-A23DCEAF8F8B","adblockId":"easylist_plus_polish","index":24},"https://easylist-downloads.adblockplus.org/easylistpolish+easylist.txt":{"id":"3D2C09D0-DF1C-4C8E-9947-A23DCEAF8F8B","adblockId":"easylist_plus_polish","index":24},"https://easylist-downloads.adblockplus.org/v3/full/easylistportuguese+easylist.txt":{"id":"14DF7BE6-9675-4E07-987A-D8A1000F9FEF","adblockId":"easylist_plus_portuguese","index":25},"https://easylist-downloads.adblockplus.org/easylistportuguese+easylist.txt":{"id":"14DF7BE6-9675-4E07-987A-D8A1000F9FEF","adblockId":"easylist_plus_portuguese","index":25},"https://easylist-downloads.adblockplus.org/v3/full/easylistspanish+easylist.txt":{"id":"C3D13A19-3E8D-41F5-AD64-0F3B36DDE128","adblockId":"easylist_plus_spanish","index":26},"https://easylist-downloads.adblockplus.org/easylistspanish+easylist.txt":{"id":"C3D13A19-3E8D-41F5-AD64-0F3B36DDE128","adblockId":"easylist_plus_spanish","index":26},"https://easylist-downloads.adblockplus.org/v3/full/indianlist+easylist.txt":{"id":"25A31255-AB36-48A4-9086-06192DE71119","adblockId":"easylist_plus_indian","index":27},"https://easylist-downloads.adblockplus.org/indianlist+easylist.txt":{"id":"25A31255-AB36-48A4-9086-06192DE71119","adblockId":"easylist_plus_indian","index":27},"https://easylist-downloads.adblockplus.org/v3/full/koreanlist+easylist.txt":{"id":"2708BCB7-2E45-41BC-B517-1730CF532F89","adblockId":"easylist_plun_korean","index":28},"https://easylist-downloads.adblockplus.org/koreanlist+easylist.txt":{"id":"2708BCB7-2E45-41BC-B517-1730CF532F89","adblockId":"easylist_plun_korean","index":28},"https://easylist-downloads.adblockplus.org/v3/full/latvianlist+easylist.txt":{"id":"950C88EA-2DD1-42E3-B2A2-2DF2ED15563A","adblockId":"latvian","index":29},"https://easylist-downloads.adblockplus.org/latvianlist+easylist.txt":{"id":"950C88EA-2DD1-42E3-B2A2-2DF2ED15563A","adblockId":"latvian","index":29},"https://easylist-downloads.adblockplus.org/v3/full/liste_ar+liste_fr+easylist.txt":{"id":"684A25C6-6B5D-458A-8A2B-BAC0A12B0B15","adblockId":"easylist_plus_arabic_plus_french","index":30},"https://easylist-downloads.adblockplus.org/liste_ar+liste_fr+easylist.txt":{"id":"684A25C6-6B5D-458A-8A2B-BAC0A12B0B15","adblockId":"easylist_plus_arabic_plus_french","index":30},"https://easylist-downloads.adblockplus.org/v3/full/liste_fr+easylist.txt":{"id":"2CEA1481-C29C-44F1-A084-A2A019533797","adblockId":"easylist_plus_french","index":31},"https://easylist-downloads.adblockplus.org/liste_fr+easylist.txt":{"id":"2CEA1481-C29C-44F1-A084-A2A019533797","adblockId":"easylist_plus_french","index":31},"https://easylist-downloads.adblockplus.org/v3/full/ruadlist+easylist.txt":{"id":"1B5F78CA-8B30-4BDF-B0A3-451CB2202984","adblockId":"russian","index":32},"https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt":{"id":"1B5F78CA-8B30-4BDF-B0A3-451CB2202984","adblockId":"russian","index":32},"https://easylist-downloads.adblockplus.org/v3/full/rolist+easylist.txt":{"id":"EEEF75EC-B2B4-49F4-BC49-17B08266F334","adblockId":"easylist_plus_romanian","index":33},"https://easylist-downloads.adblockplus.org/rolist+easylist.txt":{"id":"EEEF75EC-B2B4-49F4-BC49-17B08266F334","adblockId":"easylist_plus_romanian","index":33},"https://easylist-downloads.adblockplus.org/v3/full/abp-filters-anti-cv.txt":{"id":"D4028CDD-3D39-4624-ACC7-8140F4EC3238","adblockId":"anticircumvent","index":34},"https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt":{"id":"D4028CDD-3D39-4624-ACC7-8140F4EC3238","adblockId":"anticircumvent","index":34},"https://easylist-downloads.adblockplus.org/v3/full/easyprivacy.txt":{"id":"D72B6F06-52B2-4FED-96A2-1BF59CDD7AEC","adblockId":"easyprivacy","index":35},"https://easylist-downloads.adblockplus.org/easyprivacy.txt":{"id":"D72B6F06-52B2-4FED-96A2-1BF59CDD7AEC","adblockId":"easyprivacy","index":35},"https://easylist-downloads.adblockplus.org/v3/full/i_dont_care_about_cookies.txt":{"id":"2090F374-29D9-4202-B2CE-139D6492D95E","adblockId":"idcac","index":36},"https://easylist-downloads.adblockplus.org/i_dont_care_about_cookies.txt":{"id":"2090F374-29D9-4202-B2CE-139D6492D95E","adblockId":"idcac","index":36},"https://easylist-downloads.adblockplus.org/v3/full/fanboy-social.txt":{"id":"0A679439-445F-4DE7-84B9-88341F6DA520","adblockId":"antisocial","index":37},"https://easylist-downloads.adblockplus.org/fanboy-social.txt":{"id":"0A679439-445F-4DE7-84B9-88341F6DA520","adblockId":"antisocial","index":37},"https://secure.fanboy.co.nz/fanboy-annoyance.txt":{"id":"0B0296EB-1CC5-49CD-AD38-8AF27420B7E4","adblockId":"annoyances","index":38},"https://easylist-downloads.adblockplus.org/v3/full/fanboy-annoyance.txt":{"id":"0B0296EB-1CC5-49CD-AD38-8AF27420B7E4","adblockId":"annoyances","index":38},"https://easylist-downloads.adblockplus.org/v3/full/fanboy-notifications.txt":{"id":"5BD2BB73-459D-4A74-AF9D-A10157268350","adblockId":"fb_notifications","index":39},"https://easylist-downloads.adblockplus.org/fanboy-notifications.txt":{"id":"5BD2BB73-459D-4A74-AF9D-A10157268350","adblockId":"fb_notifications","index":39},"https://easylist-downloads.adblockplus.org/v3/full/dandelion_sprouts_nordic_filters+easylist.txt":{"id":"96932CD9-6DDF-4D97-B92F-FDF747B6FAA2","adblockId":"nordic","index":55},"https://easylist-downloads.adblockplus.org/dandelion_sprouts_nordic_filters+easylist.txt":{"id":"96932CD9-6DDF-4D97-B92F-FDF747B6FAA2","adblockId":"nordic","index":55}}');
;// CONCATENATED MODULE: ./adblock-betafish/subscriptionadapter.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */
/* For ESLint: List any global identifiers used in this file below */
/* global  */




const legacyDistractionControlIDs = {
  'distraction-control-video': 'https://cdn.adblockcdn.com/filters/distraction-control-video.txt',
  'distraction-control-survey': 'https://cdn.adblockcdn.com/filters/distraction-control-survey.txt',
  'distraction-control-newsletter': 'https://cdn.adblockcdn.com/filters/distraction-control-newsletter.txt',
  'distraction-control-push': 'https://cdn.adblockcdn.com/filters/distraction-control-push.txt',
};

// Adapters & helpers to add the legacy AB 'id' to the ABP subscriptions
// Also adds the 'language' and 'hidden' properties
const SubscriptionAdapter = (function getSubscriptionAdapter() {
  const addAdBlockProperties = function (sub) {
    let subscription = Object.assign({}, sub);
    const { url } = subscription;
    if (betafish_subscriptions_namespaceObject[url]) {
      subscription = Object.assign(subscription, betafish_subscriptions_namespaceObject[url]);
      if (Object.prototype.hasOwnProperty.call(sub, 'languages')) {
        subscription.languages = [].concat(sub.languages);
      }
      if (!Object.prototype.hasOwnProperty.call(subscription, 'language')) {
        subscription.language = (subscription.languages && subscription.languages.length > 0);
      }
    }
    subscription.correctedURL = subscription.url;
    return subscription;
  };

  // Get the URL for the corresponding ID
  const getUrlFromId = function (searchID) {
    for (const url in betafish_subscriptions_namespaceObject) {
      const subscription = betafish_subscriptions_namespaceObject[url];
      const { adblockId } = subscription;
      if (searchID === adblockId) {
        return url;
      }
    }
    return '';
  };

  // Get the ID for the corresponding URL
  const getIdFromURL = function (searchURL) {
    for (const url in betafish_subscriptions_namespaceObject) {
      const subscription = betafish_subscriptions_namespaceObject[url];
      const { adblockId } = subscription;
      if (searchURL === url) {
        return adblockId;
      }
    }
    return null;
  };

  // Get the MV2 URL for the corresponding ID
  const getV2URLFromID = function (searchID) {
    for (const url in betafish_subscriptions_namespaceObject) {
      const subscription = betafish_subscriptions_namespaceObject[url];
      const { id } = subscription;
      if (searchID === id && !url.includes('/v3/')) {
        return url;
      }
    }
    return null;
  };

  // Get the MV2 URL for the corresponding URL
  // if not found, return the passed parameter
  const getV2URLFromURL = function (searchURL) {
    const subscription = betafish_subscriptions_namespaceObject[searchURL];
    if (subscription && subscription.id) {
      return getV2URLFromID(subscription.id);
    }
    return searchURL;
  };

  // determine if the specified filter list is a legacy
  // Distraction Control filter list
  // returns true if the ID is a legacy DC filter list URL
  //         false otherwise
  const isLegacyDistractionControlById = function (id) {
    return Object.prototype.hasOwnProperty.call(legacyDistractionControlIDs, id);
  };


  // determine if the specified filter list is language specific
  // returns the boolean language attribue (if found)
  //         false otherwise
  const isLanguageSpecific = function (searchID) {
    // check for EasyList, as it is a language-specific list (en), but
    // shouldn't be treated as such by the AdBlock code
    if (searchID === 'easylist') {
      return false;
    }

    for (let subscription of ewe_api.subscriptions.getRecommendations()) {
      subscription = addAdBlockProperties(subscription);
      const { adblockId } = subscription;
      if (adblockId === searchID) {
        return subscription.language;
      }
    }
    return false;
  };

  // Get the ID for the corresponding URL
  const getSubscriptionInfoFromURL = function (searchURL) {
    for (let subscription of ewe_api.subscriptions.getRecommendations()) {
      subscription = addAdBlockProperties(subscription);
      const { url } = subscription;
      if (searchURL === url) {
        return subscription;
      }
    }
    return null;
  };

  // Unsubcribe the user from the subscription specified in the argument
  const unsubscribe = async function (options) {
    const subscriptionUrl = getUrlFromId(options.adblockId);
    if (subscriptionUrl !== '') {
      try {
        await ewe_api.subscriptions.remove(subscriptionUrl);
      } catch (e) {
        // do nothing
      }
    }
  };

  // Get only the user's subscriptions with in the AB format
  // without the filter contents (text)
  const getSubscriptionsMinusText = async function () {
    const result = {};
    const subscriptions = await ewe_api.subscriptions.getDownloadable();
    subscriptions.forEach(async (subscription) => {
      const tempSub = addAdBlockProperties(subscription);
      // if the subscription doesn't have a 'adblockId' property, use the 'URL' as an
      // 'adblockId' property
      if (!tempSub.adblockId || tempSub.adblockId === undefined) {
        tempSub.adblockId = `url:${subscription.url}`;
      }
      // add the 'subscribed' property
      tempSub.subscribed = true;
      result[tempSub.adblockId] = tempSub;
    });
    return result;
  };

  const rareFilterLists = {
    'http://fanboy.co.nz/fanboy-turkish.txt': 56,
    'https://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus&mimetype=plaintext': 57,
    'https://adblock.gardar.net/is.abp.txt': 58,
    'https://github.com/SlashArash/adblockfa': 59,
    'https://adblock.ee/list.php': 60,
  };

  // Get a binary string representation of the users subscriptions
  const getSubscriptionsChecksum = async function () {
    let resultA = 0;
    let resultB = 0;
    const subscriptions = await ewe_api.subscriptions.getDownloadable();
    subscriptions.forEach(async (subscription) => {
      const sub = addAdBlockProperties(subscription);
      let index = sub.index || 0; // 0 is the 'unkown' index
      // if URL wasn't found in our subscription file, check the rareFilterLists to get the index
      if (index === 0 && rareFilterLists[sub.url]) {
        index = rareFilterLists[sub.url];
      }
      index = parseInt(index, 10);
      // We can only use 31 bits because the leftmost bit is the signed bit
      if (index < 31) {
        resultA |= (2 ** index); // eslint-disable-line no-bitwise
      } else {
        resultB |= (2 ** (index - 31)); // eslint-disable-line no-bitwise
      }
    });
    return resultB.toString(2).padStart(32, '0') + resultA.toString(2).padStart(31, '0');
  };

  // Get all subscriptions in the AB format
  // without the filter contents (text)
  const getAllSubscriptionsMinusText = async function () {
    const userSubs = await getSubscriptionsMinusText();
    for (const subscription of ewe_api.subscriptions.getRecommendations()) {
      const sub = addAdBlockProperties(subscription);
      const { adblockId } = sub;
      if (!(adblockId in userSubs)) {
        userSubs[adblockId] = sub;
      } else {
        Object.assign(userSubs[adblockId], sub);
      }
    }
    for (const url in betafish_subscriptions_namespaceObject) {
      let sub = Object.assign({}, betafish_subscriptions_namespaceObject[url]);
      sub.url = url;
      sub = addAdBlockProperties(sub);
      const { adblockId } = sub;
      if (!(adblockId in userSubs)) {
        userSubs[adblockId] = sub;
      }
    }
    return userSubs;
  };
  // Get all distraction control subscriptions
  // without the filter contents (text)
  const getDCSubscriptionsMinusText = async function () {
    const userSubs = await getAllSubscriptionsMinusText();
    const result = {};
    for (const adblockId in userSubs) {
      const {
        url, type, title, homepage, hidden, subscribed, index,
      } = userSubs[adblockId];
      if (url === 'https://easylist-downloads.adblockplus.org/adblock_premium.txt') {
        result[adblockId] = {};
        result[adblockId].subscribed = subscribed;
        result[adblockId].adblockId = adblockId;
        result[adblockId].url = url;
        result[adblockId].userSubmitted = false;
        result[adblockId].hidden = hidden;
        result[adblockId].type = type;
        result[adblockId].title = title;
        result[adblockId].homepage = homepage;
        result[adblockId].index = index;
      }
    }
    return result;
  };


  // Subcribe the user to the subscription specified in the argument
  const subscribe = function (options) {
    if (options && options.adblockId) {
      const subscriptionUrl = getUrlFromId(options.adblockId);
      if (subscriptionUrl) {
        ewe_api.subscriptions.add(subscriptionUrl);
      }
    }
  };

  return {
    getSubscriptionInfoFromURL,
    getUrlFromId,
    unsubscribe,
    subscribe,
    getSubscriptionsMinusText,
    getSubscriptionsChecksum,
    getAllSubscriptionsMinusText,
    getDCSubscriptionsMinusText,
    getIdFromURL,
    isLegacyDistractionControlById,
    legacyDistractionControlIDs,
    isLanguageSpecific,
    getV2URLFromID,
    getV2URLFromURL,
  };
}());

/* harmony default export */ const subscriptionadapter = (SubscriptionAdapter);


/***/ }),

/***/ 5441:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "fp": () => (/* reexport */ IPM),
  "C": () => (/* reexport */ TELEMETRY)
});

// UNUSED EXPORTS: telemetryNotifier

// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/events.js
var events = __webpack_require__(9876);
// EXTERNAL MODULE: ./adblock-betafish/servermessages.js
var servermessages = __webpack_require__(2559);
// EXTERNAL MODULE: ./adblock-betafish/alias/prefs.js
var prefs = __webpack_require__(4428);
// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./adblock-betafish/subscriptionadapter.js + 1 modules
var subscriptionadapter = __webpack_require__(1974);
// EXTERNAL MODULE: ./adblock-betafish/id/background/index.ts + 1 modules
var background = __webpack_require__(6703);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/index.ts + 2 modules
var utilities_background = __webpack_require__(9555);
;// CONCATENATED MODULE: ./adblock-betafish/telemetry/background/telemetry-base.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, channels, replacedCounts, getSettings
    BigInt, LocalCDN,  */










const FiftyFiveMinutes = 3300000;

class TelemetryBase {
  constructor(
    totalRequestsStorageKeyArg,
    nextRequestTimeStorageKeyArg,
    alarmNameArg,
    hostURLPrefArg,
  ) {
    this.totalRequestsStorageKey = totalRequestsStorageKeyArg;
    this.nextRequestTimeStorageKey = nextRequestTimeStorageKeyArg;
    this.alarmName = alarmNameArg;
    this.hostURLPref = hostURLPrefArg;
    this.dataCorrupt = false;
    // Get some information about the version, os, and browser
    this.version = browser.runtime.getManifest().version;
    this.os = (0,utilities_background/* getUserAgentInfo */.K1)().os;
    this.osVersion = (0,utilities_background/* getUserAgentInfo */.K1)().osVersion;
    this.flavor = (0,utilities_background/* getUserAgentInfo */.K1)().flavor;
    this.browserVersion = (0,utilities_background/* getUserAgentInfo */.K1)().browserVersion;
    this.firstRun = false;
    this.userId = '';
    // added calls to these two methods because the need to be
    // called in the first turn of the event loop
    this.addAlarmListener();
    this.checkIdleState();
  }

  // Check if the computer was woken up, and if there was a pending alarm
  // that should fired during the sleep, then
  // remove it, and fire the update ourselves.
  // see - https://bugs.chromium.org/p/chromium/issues/detail?id=471524
  checkIdleState() {
    browser.idle.onStateChanged.addListener(async (newState) => {
      if (newState === 'active') {
        const alarm = await browser.alarms.get(this.alarmName);
        if (alarm && Date.now() > alarm.scheduledTime) {
          await browser.alarms.clear(this.alarmName);
          await this.pingNow();
          await this.scheduleNextPing();
          await this.sleepThenPing();
        } else if (alarm) {
          // if the alarm should fire in the future,
          // re-add the alarm so it fires at the correct time
          const originalTime = alarm.scheduledTime;
          const wasCleared = await browser.alarms.clear(this.alarmName);
          if (wasCleared) {
            browser.alarms.create(this.alarmName, { when: originalTime });
          }
        }
      }
    });
  }

  addAlarmListener = () => {
    browser.alarms.onAlarm.addListener(async (alarm) => {
      if (alarm && alarm.name === this.alarmName) {
        await this.pingNow();
        await this.scheduleNextPing();
        await this.sleepThenPing();
      }
    });
  };

  // Get the user a userid.
  async loadUserID() {
    if (!this.userId) {
      this.userId = await (0,background/* getUserId */.n)();
    }
    return this.userId;
  }

  // Clean up / remove old, unused data in localStorage
  cleanUpLocalStorage() {
    (0,utilities_background/* storageSet */.eV)(this.totalRequestsStorageKey);
    (0,utilities_background/* storageSet */.eV)(this.nextRequestTimeStorageKey);
  }

  async getTelemetryData() {
    const response = await browser.storage.local.get(this.totalRequestsStorageKey);
    let data = {};
    const settingsObj = getSettings();
    const totalPings = response[this.totalRequestsStorageKey] || 0;
    const themeOptionsPage = settingsObj.color_themes.options_page.replace('_theme', '');
    const themePopupMenu = settingsObj.color_themes.popup_menu.replace('_theme', '');
    let subsStr = '-1';
    if (typeof BigInt === 'function') {
      subsStr = BigInt(`0b${await subscriptionadapter/* default.getSubscriptionsChecksum */.Z.getSubscriptionsChecksum()}`).toString();
    }

    data = {
      u: this.userId,
      v: this.version,
      f: this.flavor,
      o: this.os,
      bv: this.browserVersion,
      ov: this.osVersion,
      ad: settingsObj.show_advanced_options ? '1' : '0',
      yt: settingsObj.youtube_channel_whitelist ? '1' : '0',
      l: (0,utilities_background/* determineUserLanguage */.pN)(),
      pc: totalPings,
      dcv2: settingsObj.data_collection_v2 ? '1' : '0',
      ldc: settingsObj.local_data_collection ? '1' : '0',
      cdn: settingsObj.local_cdn ? '1' : '0',
      rc: await replacedCounts.getTotalAdsReplaced(),
      to: themeOptionsPage,
      tm: themePopupMenu,
      sy: settingsObj.sync_settings ? '1' : '0',
      ir: channels.isAnyEnabled() ? '1' : '0',
      cir: channels.channelGuide[channels.getIdByName('CustomChannel')].enabled ? '1' : '0',
      tca: settingsObj.twitch_channel_allowlist ? '1' : '0',
      sup: settingsObj.suppress_update_page ? '1' : '0',
      ss: settingsObj.suppress_surveys ? '1' : '0',
      sfrp: settingsObj.suppress_first_run_page ? '1' : '0',
      opm: settingsObj.onpageMessages ? '1' : '0',
      subs: subsStr,
    };

    if (typeof LocalCDN !== 'undefined') {
      data.cdnr = await LocalCDN.getRedirectCount();
      data.cdnd = await LocalCDN.getDataCount();
    } else {
      data.cdnr = 0;
      data.cdnd = 0;
    }

    // only on Chrome, Edge, or Firefox
    if ((this.flavor === 'E' || this.flavor === 'CM' || this.flavor === 'F') && prefs/* Prefs.blocked_total */.B.blocked_total) {
      data.b = prefs/* Prefs.blocked_total */.B.blocked_total;
    }
    if (browser.runtime.id) {
      data.extid = browser.runtime.id;
    }
    const subs = await subscriptionadapter/* default.getAllSubscriptionsMinusText */.Z.getAllSubscriptionsMinusText();
    if (subs) {
      const aa = subs.acceptable_ads;
      const aaPrivacy = subs.acceptable_ads_privacy;

      if (!aa && !aaPrivacy) {
        data.aa = 'u'; // Both filter lists unavailable
      } else if (aa.subscribed) {
        data.aa = '1';
      } else if (aaPrivacy.subscribed) {
        data.aa = '2';
      } else if (!aa.subscribed && !aaPrivacy.subscribed) {
        data.aa = '0'; // Both filter lists unsubscribed
      }
    }

    data.crctotal = 0;
    data.crcsnippet = 0;
    data.crcelemhideemulation = 0;
    data.crcelemhideexception = 0;
    data.crcelemhide = 0;
    data.crcallowing = 0;
    data.crcblocking = 0;
    data.crccomment = 0;
    data.crcinvalid = 0;

    const userFilters = await ewe_api.filters.getUserFilters();
    for (let j = 0; j < userFilters.length; j++) {
      const filter = userFilters[j];
      data[`crc${filter.type}`] += 1;
      data.crctotal += 1;
    }

    data.dc = this.dataCorrupt ? '1' : '0';
    data.isPinned = '-1';
    const userSettings = browser.action.getUserSettings
      && await browser.action.getUserSettings();
    if (userSettings) {
      data.isPinned = userSettings.isOnToolbar ? '1' : '0';
    }
    if (browser.permissions && browser.permissions.getAll) {
      const allPermissions = await browser.permissions.getAll();
      data.dhp = allPermissions.origins && allPermissions.origins.includes('<all_urls>') ? '1' : '0';
    } else {
      data.dhp = '1';
    }
    return data;
  }

  // Return the number of milliseconds until the next scheduled ping.
  async millisTillNextPing() {
    // If we've detected data corruption issues,
    // then default to a 55 minute ping interval
    if (this.dataCorrupt) {
      return FiftyFiveMinutes;
    }
    const response = await browser.storage.local.get(this.nextRequestTimeStorageKey);
    if (!response[this.nextRequestTimeStorageKey]) {
      this.firstRun = true;
    }
    let nextPingTime = response[this.nextRequestTimeStorageKey];
    if (typeof nextPingTime !== 'number' || Number.isNaN(nextPingTime)) {
      nextPingTime = 0;
    }
    if (nextPingTime === 0 && this.firstRun) {
      return (1000 * 60);
    }
    // if we don't have a 'next ping time', or it's not a valid number,
    // default to 55 minute ping interval
    if (
      typeof nextPingTime !== 'number'
      || nextPingTime === 0
      || Number.isNaN(nextPingTime)
    ) {
      return FiftyFiveMinutes;
    }
    return (nextPingTime - Date.now());
  }

  async sleepThenPing() {
    const delay = await this.millisTillNextPing();
    browser.alarms.create(this.alarmName, { delayInMinutes: (delay / 1000 / 60) });
  }


  async start() {
    await this.loadUserID();
    // Do 'stuff' when we're first installed...
    // - send a message
    const response = await browser.storage.local.get(this.totalRequestsStorageKey);
    if (!response[this.totalRequestsStorageKey]) {
      if (browser.management && browser.management.getSelf) {
        const info = await browser.management.getSelf();
        if (info) {
          servermessages/* default.recordGeneralMessage */.Z.recordGeneralMessage(`new_install_${info.installType}`);
        } else {
          servermessages/* default.recordGeneralMessage */.Z.recordGeneralMessage('new_install');
        }
      } else {
        servermessages/* default.recordGeneralMessage */.Z.recordGeneralMessage('new_install');
      }
    }
    // This will sleep, then ping, then schedule a new ping, then
    // call itself to start the process over again.
    await this.sleepThenPing();
    this.cleanUpLocalStorage();
  }

  async untilLoaded() {
    await this.loadUserID();
    return this.userId;
  }

  get browser() {
    return ({
      E: 'Chrome',
      CM: 'Edge',
      F: 'Firefox',
    })[this.flavor];
  }
}

/* harmony default export */ const telemetry_base = (TelemetryBase);

// EXTERNAL MODULE: ./adblock-betafish/fetch-util.js
var fetch_util = __webpack_require__(8171);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/telemetry/background/telemetry-ping.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, LocalCDN */








const telemetryNotifier = new events/* EventEmitter */.v();

class Telemetry extends telemetry_base {
  // Called just after we ping the server, to schedule our next ping.
  scheduleNextPing() {
    return new Promise(async (resolve) => {
      const response = await browser.storage.local.get(this.totalRequestsStorageKey);
      let totalPings = response[this.totalRequestsStorageKey];
      if (typeof totalPings !== 'number' || Number.isNaN(totalPings)) {
        totalPings = 0;
      }
      totalPings += 1;
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(this.totalRequestsStorageKey, totalPings);

      let delayHours;
      if (totalPings === 1) { // Ping one hour after install
        delayHours = 1;
      } else if (totalPings < 9) { // Then every day for a week
        delayHours = 24;
      } else { // Then weekly forever
        delayHours = 24 * 7;
      }
      const millis = 1000 * 60 * 60 * delayHours;
      const nextPingTime = Date.now() + millis;
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(this.nextRequestTimeStorageKey, nextPingTime, (error) => {
        this.dataCorrupt = !!error;
        resolve();
      });
    });
  }

  sendPingData(pingData) {
    return new Promise(async (resolve) => {
      const response = await (0,fetch_util/* default */.Z)(prefs/* Prefs.get */.B.get(this.hostURLPref), pingData)
        // Send any network errors during the ping fetch to a dedicated log server
        // to help us determine why there's been a drop in ping requests
        // See https://gitlab.com/adblockinc/ext/adblock/adblock/-/issues/136
        .catch((error) => {
          void servermessages/* default.sendMessageToBackupLogServer */.Z.sendMessageToBackupLogServer('fetch_error', error.toString());
          (0,bg_functions/* log */.cM)('ping server returned error: ', error);
        });
      if (response && response.ok) {
        telemetryNotifier.emit('ping.complete');
      } else {
        (0,bg_functions/* log */.cM)('Ping server returned error: ', (response && response.statusText));
      }
      resolve(pingData);
    });
  }

  // Tell the server we exist.
  async pingNow() {
    const pingData = await this.getTelemetryData();
    if (!pingData.u) {
      return pingData;
    }
    // attempt to stop users that are pinging us 'a lot'
    // by checking the current ping count,
    // if the ping count is above a theshold,
    // then only ping 'occasionally'
    if (pingData.pc > 5000) {
      if (pingData.pc > 5000 && pingData.pc < 100000 && ((pingData.pc % 5000) !== 0)) {
        return pingData;
      }
      if (pingData.pc >= 100000 && ((pingData.pc % 50000) !== 0)) {
        return pingData;
      }
    }
    pingData.cmd = 'ping';
    if (browser.management && browser.management.getSelf) {
      const info = await browser.management.getSelf();
      pingData.it = info.installType.charAt(0);
    }
    if (typeof LocalCDN !== 'undefined') {
      const missedVersions = LocalCDN.getMissedVersions();
      if (missedVersions) {
        servermessages/* default.recordGeneralMessage */.Z.recordGeneralMessage('cdn_miss_stats', undefined, { cdnm: missedVersions });
      }
    }
    return this.sendPingData(pingData);
  }
}

/* harmony default export */ const telemetry_ping = (Telemetry);

// EXTERNAL MODULE: ./adblock-betafish/utilities/background/logger.ts
var logger = __webpack_require__(8095);
// EXTERNAL MODULE: ./adblock-betafish/ipm/background/index.ts + 6 modules
var ipm_background = __webpack_require__(9164);
;// CONCATENATED MODULE: ./adblock-betafish/telemetry/background/telemetry-ipm.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser */











class IPMTelemetry extends telemetry_base {
  /**
 * Processes a response from the IPM server. Will request command execution
 * if necessary.
 *
 * @param response The response from the IPM server
 */
  static async processResponse(response) {
    if (!response.ok) {
      logger/* error */.vU(`[Telemetry]: Bad response status from IPM server: ${response.status}`);
      return;
    }
    telemetryNotifier.emit('ipm.ping.complete');

    // if the server responded with something, we assume it's a command
    const responseText = await response.text();
    if (responseText) {
      const body = JSON.parse(responseText);
      (0,ipm_background/* executeIPMCommand */.LE)(body);
    }
  }

  // Called just after we ping the server, to schedule our next ping.
  scheduleNextPing() {
    return new Promise(async (resolve) => {
      const response = await browser.storage.local.get(this.totalRequestsStorageKey);
      let totalPings = response[this.totalRequestsStorageKey];
      if (typeof totalPings !== 'number' || Number.isNaN(totalPings)) {
        totalPings = 0;
      }
      totalPings += 1;
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(this.totalRequestsStorageKey, totalPings);

      let delayHours;
      if (totalPings === 1) { // Ping one hour after install
        delayHours = 1;
      } else { // Then every day
        delayHours = 24;
      }
      const millis = 1000 * 60 * 60 * delayHours;
      let nextPingTime = Date.now() + millis;
      // The smear factor isn't added for the first ping
      // so that the first IPM ping is sent ASAP after installation
      if (totalPings >= 2) {
        const smear = Math.floor(Math.random() * 600000) + 60000;
        // add a random amount of time (between 1 minute and 11 minutes)
        // to the next ping time to avoid overloading the server
        // with requests at the same time every day
        nextPingTime += smear;
      }
      (0,bg_functions/* chromeStorageSetHelper */.rJ)(this.nextRequestTimeStorageKey, nextPingTime, (error) => {
        this.dataCorrupt = !!error;
        resolve();
      });
    });
  }

  async sendPingData(pingData) {
    // as we about to send all user events, we can delete them
    void (0,ipm_background/* clearEvents */.QF)();
    const response = await (0,fetch_util/* default */.Z)(prefs/* Prefs.get */.B.get(this.hostURLPref), pingData).catch((error) => {
      logger/* error */.vU('ipm ping error', error);
    });
    IPMTelemetry.processResponse(response);
  }

  async pingNow() {
    const pingData = await (0,ipm_background/* getPayload */.He)();
    await this.sendPingData(pingData);
    return pingData;
  }
}

/* harmony default export */ const telemetry_ipm = (IPMTelemetry);

;// CONCATENATED MODULE: ./adblock-betafish/telemetry/background/telemetry.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */




const IPM = new telemetry_ipm('total_ipm_pings', 'next_ipm_ping_time', 'ipm_pingalarm', 'ipm_server_url');
const TELEMETRY = new telemetry_ping('total_pings', 'next_ping_time', 'pingalarm', 'ping_server_url');

;// CONCATENATED MODULE: ./adblock-betafish/telemetry/background/index.js
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */





/***/ }),

/***/ 9667:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2209);
/* harmony import */ var _prefs_background__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(1648);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, ext,
   addCustomFilter, */





const twitchChannelNamePages = new Map();

// On single page sites, such as Twitch, that update the URL using the History API pushState(),
// they don't actually load a new page, we need to get notified when this happens
// and update the URLs in the Page and Frame objects
const twitchHistoryStateUpdateHandler = async function (details) {
  if (details
      && Object.prototype.hasOwnProperty.call(details, 'frameId')
      && Object.prototype.hasOwnProperty.call(details, 'tabId')
      && Object.prototype.hasOwnProperty.call(details, 'url')
      && details.transitionType === 'link') {
    const myURL = new URL(details.url);
    if (myURL.hostname === 'www.twitch.tv') {
      const myFrame = ext.getFrame(details.tabId, details.frameId);
      const myPage = ext.getPage(details.tabId);
      myPage._url = myURL;
      myFrame.url = myURL;
      myFrame._url = myURL;
      if (await _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__.filters.getAllowingFilters(myPage.id).length) {
        (0,_vendor_adblockplusui_adblockpluschrome_lib_browserAction__WEBPACK_IMPORTED_MODULE_1__/* .setBadge */ .q_)(details.tabId, { number: '' });
      }
    }
  }
};

// Creates a custom filter entry that whitelists a YouTube channel
// Inputs: url:string url of the page
// Returns: null if successful, otherwise an exception
const createWhitelistFilterForTwitchChannel = function (url, origin) {
  let twitchChannel;
  if (/ab_channel=/.test(url)) {
    [, twitchChannel] = url.match(/ab_channel=([^]*)/);
  } else {
    twitchChannel = url.split('/').pop();
  }
  if (twitchChannel) {
    const filter = `@@||twitch.tv/*${twitchChannel}^$document`;
    return addCustomFilter(filter, origin);
  }
  return undefined;
};

const twitchMessageHandler = function (message, sender, sendResponse) {
  if (message.command === 'createWhitelistFilterForTwitchChannel' && message.url) {
    sendResponse(createWhitelistFilterForTwitchChannel(message.url, message.origin));
    return;
  }
  if (message.command === 'updateTwitchChannelName' && message.channelName) {
    twitchChannelNamePages.set(sender.tab.id, message.channelName);
    sendResponse({});
  }
};

const addTwitchAllowlistListeners = function () {
  twitchChannelNamePages.clear();
  browser.runtime.onMessage.addListener(twitchMessageHandler);
  browser.webNavigation.onHistoryStateUpdated.addListener(twitchHistoryStateUpdateHandler);
};

const removeTwitchAllowlistListeners = function () {
  twitchChannelNamePages.clear();
  browser.runtime.onMessage.removeListener(twitchMessageHandler);
  browser.webNavigation.onHistoryStateUpdated.removeListener(twitchHistoryStateUpdateHandler);
};

_prefs_background__WEBPACK_IMPORTED_MODULE_2__/* .settings.onload */ .Xd.onload().then(() => {
  if ((0,_prefs_background__WEBPACK_IMPORTED_MODULE_2__/* .getSettings */ .Gw)().twitch_channel_allowlist) {
    addTwitchAllowlistListeners();
  }
});

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  addTwitchAllowlistListeners,
  removeTwitchAllowlistListeners,
  twitchChannelNamePages,
});


/***/ }),

/***/ 7337:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "E_": () => (/* binding */ sessionStorageGet),
/* harmony export */   "PW": () => (/* binding */ logging),
/* harmony export */   "Qr": () => (/* binding */ isEmptyObject),
/* harmony export */   "Yv": () => (/* binding */ createFilterMetaData),
/* harmony export */   "bg": () => (/* binding */ sessionStorageSet),
/* harmony export */   "cM": () => (/* binding */ log),
/* harmony export */   "eV": () => (/* binding */ storageSet),
/* harmony export */   "he": () => (/* binding */ parseUri),
/* harmony export */   "l7": () => (/* binding */ extend),
/* harmony export */   "lE": () => (/* binding */ chromeStorageDeleteHelper),
/* harmony export */   "nX": () => (/* binding */ chromeStorageGetHelper),
/* harmony export */   "pN": () => (/* binding */ determineUserLanguage),
/* harmony export */   "qo": () => (/* binding */ reloadOptionsPageTabs),
/* harmony export */   "rJ": () => (/* binding */ chromeStorageSetHelper),
/* harmony export */   "ww": () => (/* binding */ migrateData)
/* harmony export */ });
/* unused harmony export storageGet */
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser */

/* eslint-disable import/no-mutable-exports */
let log = function log() {
};
// Enabled in adblock_start_common.js and background.js if the user wants
const logging = function (enabled) {
  if (enabled) {
    /* eslint-disable  @typescript-eslint/no-shadow */
    log = function log(...args) {
      // eslint-disable-next-line no-console
      console.log(...args);
    };
  }
};
logging(false); // disabled by default

// Determine what language the user's browser is set to use
const determineUserLanguage = function () {
  return browser.i18n.getUILanguage();
};

// Parse a URL. Based upon http://blog.stevenlevithan.com/archives/parseuri
// parseUri 1.2.2, (c) Steven Levithan <stevenlevithan.com>, MIT License
// Inputs: url: the URL you want to parse
// Outputs: object containing all parts of |url| as attributes
const parseUriRegEx = /^(([^:]+(?::|$))(?:(?:\w+:)?\/\/)?(?:[^:@/]*(?::[^:@/]*)?@)?(([^:/?#]*)(?::(\d*))?))((?:[^?#/]*\/)*[^?#]*)(\?[^#]*)?(#.*)?/;
const parseUri = function (url) {
  const matches = parseUriRegEx.exec(url);

  // The key values are identical to the JS location object values for that key
  const keys = ['href', 'origin', 'protocol', 'host', 'hostname', 'port',
    'pathname', 'search', 'hash'];
  const uri = {};
  for (let i = 0; (matches && i < keys.length); i++) {
    uri[keys[i]] = matches[i] || '';
  }
  return uri;
};

// Parses the search part of a URL into a key: value object.
// e.g., ?hello=world&ext=adblock would become {hello:"world", ext:"adblock"}
// Inputs: search: the search query of a URL. Must have &-separated values.
parseUri.parseSearch = function parseSearch(searchQuery) {
  const params = {};
  let search = searchQuery;
  let pair;

  // Fails if a key exists twice (e.g., ?a=foo&a=bar would return {a:"bar"}
  search = search.substring(search.indexOf('?') + 1).split('&');

  for (let i = 0; i < search.length; i++) {
    pair = search[i].split('=');
    if (pair[0] && !pair[1]) {
      pair[1] = '';
    }
    const pairKey = decodeURIComponent(pair[0]);
    const pairValue = decodeURIComponent(pair[1]);
    if (pairKey && pairValue !== 'undefined') {
      params[pairKey] = pairValue;
    }
  }
  return params;
};

// Strip third+ level domain names from the domain and return the result.
// Inputs: domain: the domain that should be parsed
// keepDot: true if trailing dots should be preserved in the domain
// Returns: the parsed domain
parseUri.secondLevelDomainOnly = function stripThirdPlusLevelDomain(domain, keepDot) {
  if (domain) {
    const match = domain.match(/([^.]+\.(?:co\.)?[^.]+)\.?$/) || [domain, domain];
    return match[keepDot ? 0 : 1].toLowerCase();
  }

  return domain;
};

const sessionStorageMap = new Map();
//
// Inputs: key:string.
// Returns value if key exists, else undefined.
/**
 * @deprecated consider using SessionStorage
 */
const sessionStorageGet = function (key) {
  return sessionStorageMap.get(key);
};

// Inputs: key:string, value:object.
// If value === undefined, removes key from storage.
// Returns undefined.
/**
 * @deprecated consider using SessionStorage
 */
const sessionStorageSet = function (key, value) {
  if (value === undefined) {
    sessionStorageMap.delete(key);
    return;
  }
  sessionStorageMap.set(key, value);
};


// Inputs: key:string.
// Returns object from localStorage.
// The following two functions should only be used when
// multiple 'sets' & 'gets' may occur in immediately preceding each other
// browser.storage.local.get & set instead
// deprecated on background / service worker pages
/**
 * @deprecated consider using browser.storage.local
 */
const storageGet = function (key) {
  if (typeof localStorage === 'undefined') {
    return undefined;
  }
  const store = localStorage;
  const json = store.getItem(key);
  if (json == null) {
    return undefined;
  }
  try {
    return JSON.parse(json);
  } catch (e) {
    log(`Couldn't parse json for ${key}`, e);
    return undefined;
  }
};

// Inputs: key:string, value:object.
// If value === undefined, removes key from storage.
// Returns undefined.
/**
 * @deprecated consider using browser.storage.local
 */
const storageSet = function (key, value) {
  if (typeof localStorage === 'undefined') {
    return;
  }
  const store = localStorage;
  if (value === undefined) {
    store.removeItem(key);
    return;
  }
  try {
    store.setItem(key, JSON.stringify(value));
  } catch (ex) {
    // eslint-disable-next-line no-console
    console.log(ex);
  }
};

const chromeStorageSetHelper = function (key, value, callback) {
  const items = {};
  items[key] = value;
  browser.storage.local.set(items).then(() => {
    if (typeof callback === 'function') {
      callback();
    }
  }).catch((error) => {
    if (typeof callback === 'function') {
      callback(error);
    }
  });
};

const chromeStorageGetHelper = function (storageKey) {
  return new Promise(((resolve, reject) => {
    browser.storage.local.get(storageKey).then((items) => {
      resolve(items[storageKey]);
    }).catch((error) => {
      // eslint-disable-next-line no-console
      console.error(error);
      reject(error);
    });
  }));
};

const chromeStorageDeleteHelper = function (key) {
  return browser.storage.local.remove(key);
};

// Migrate any stored data from localStorage to
// chrome.storage.local
// if the data is successfully migrated to chrome.storage,
// then the original data in localStorage is removed
// Inputs:
//   key: string - the data storage key
//   parseData: Boolean - indicates if the stored data should be parse prior to being saved
//                        in chrome.storage
const migrateData = function (key, parseData) {
  return new Promise((resolve, reject) => {
    /* eslint-disable no-restricted-globals */
    if (typeof self.localStorage === 'undefined') {
      resolve();
    }
    let data = localStorage.getItem(key);
    if (data) {
      if (parseData) {
        data = JSON.parse(data);
      }

      chromeStorageSetHelper(key, data, (error) => {
        if (!error) {
          if (typeof localStorage !== 'undefined') {
            localStorage.removeItem(key);
          }
          resolve();
        } else {
          reject(error);
        }
      });
    } else {
      resolve();
    }
  });
};

const reloadOptionsPageTabs = function () {
  const optionTabQuery = {
    url: `chrome-extension://${browser.runtime.id}/options.html*`,
  };
  browser.tabs.query(optionTabQuery).then((tabs) => {
    for (const i in tabs) {
      browser.tabs.reload(tabs[i].id);
    }
  });
};

// eslint-disable-next-line max-len
const isEmptyObject = obj => !!(obj && Object.keys(obj).length === 0 && obj.constructor === Object);

// mimics jQuery's functionality
function extend(primaryArg, ...args) {
  const obj = primaryArg;
  for (let i = 0; i < args.length; i++) {
    for (const key in args[i]) {
      if (Object.prototype.hasOwnProperty.call(args[i], key)) {
        obj[key] = args[i][key];
      }
    }
  }
  return obj;
}

// Creates the meta data to be saved with a users custom filter rules
// Return a new object that the following structure:
// created - a Integer representing the number of milliseconds elapsed
//           since January 1, 1970 00:00:00 UTC.
// origin - a String representing the method that user added the filter rule
//
// Inputs: origin? - optional value
const createFilterMetaData = (origin) => {
  const data = { created: Date.now() };
  if (origin) {
    data.origin = origin;
  }
  return data;
};


/***/ }),

/***/ 1926:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(209);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__);
/*
 * This file is part of AdBlock  <https://getadblock.com/>,
 * Copyright (C) 2013-present  Adblock, Inc.
 *
 * AdBlock is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * AdBlock is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with AdBlock.  If not, see <http://www.gnu.org/licenses/>.
 */

/* For ESLint: List any global identifiers used in this file below */
/* global browser, getSettings, settings, addCustomFilter, getUserFilters,
   isWhitelistFilter */



const ytChannelNamePages = new Map();

const webRequestFilter = {
  url:
    [
      { hostEquals: 'www.youtube.com' },
    ],
};

let lastInjectedTimestamp = 10000;

// Creates a custom filter entry that whitelists a YouTube channel
// Inputs: channelName:string parsed channel name
// Returns:  null if successful, otherwise an exception
const createAllowlistFilterForYoutubeChannelName = function (channelName, origin) {
  if (channelName) {
    const filterText = `@@||www.youtube.com/*${channelName}|$document`;
    return addCustomFilter(filterText, origin);
  }
  return undefined;
};

// Creates a custom filter entry that whitelists a YouTube channel
// Inputs: url:string url of the page
// Returns: null if successful, otherwise an exception
const createWhitelistFilterForYoutubeChannel = function (url, origin) {
  let ytChannel;
  if (/ab_channel=/.test(url)) {
    [, ytChannel] = url.match(/ab_channel=([^]*)/);
  } else {
    ytChannel = url.split('/').pop();
  }
  if (ytChannel) {
    return createAllowlistFilterForYoutubeChannelName(ytChannel, origin);
  }
  return undefined;
};

const removeAllowlistFilterForYoutubeChannel = function (text) {
  if (isWhitelistFilter(text)) {
    _vendor_webext_sdk_dist_ewe_api__WEBPACK_IMPORTED_MODULE_0__.filters.remove([text]);
  }
};

const injectScript = async function (scriptFileName, tabId) {
  try {
    if (browser.scripting) {
      return browser.scripting.executeScript({
        target: { tabId, allFrames: false },
        files: [scriptFileName],
      });
    }
    return browser.tabs.executeScript(tabId, { file: scriptFileName, allFrames: false, runAt: 'document_start' });
  } catch (error) {
    /* eslint-disable-next-line no-console */
    console.error(error);
    return null;
  }
};

// inject the manage YT subscription
const injectManagedContentScript = async function (details, historyUpdated) {
  const { tabId } = details;
  const pingResponse = await browser.tabs.sendMessage(tabId, { command: 'ping_yt_manage_cs' });
  // Since the onHistoryStateUpdated may get called more than once with the exact same data,
  // check the timestamps, and only inject the content script once
  const diff = details.timeStamp - lastInjectedTimestamp;
  if (pingResponse && pingResponse.status === 'yes') {
    lastInjectedTimestamp = details.timeStamp;
    void browser.tabs.sendMessage(tabId, { command: 'addYouTubeOnPageIcons', historyUpdated });
  } else if (diff > 100) { // check if the timestamp difference is more than 100 ms
    lastInjectedTimestamp = details.timeStamp;
    await injectScript('purify.min.js', tabId);
    await injectScript('adblock-yt-manage-cs.js', tabId);
    void browser.tabs.sendMessage(tabId, { command: 'addYouTubeOnPageIcons', historyUpdated });
  }
};

const managedSubPageCompleted = function (details) {
  const theURL = new URL(details.url);
  if (theURL.pathname === '/feed/channels') {
    void injectManagedContentScript(details);
  }
};

// On single page sites, such as YouTube, that update the URL using the History API pushState(),
// they don't actually load a new page, we need to get notified when this happens
// and update the URLs in the Page and Frame objects
const ytHistoryHandler = function (details) {
  if (details
    && Object.prototype.hasOwnProperty.call(details, 'tabId')
    && Object.prototype.hasOwnProperty.call(details, 'url')
    && details.transitionType === 'link') {
    const myURL = new URL(details.url);
    if (getSettings().youtube_manage_subscribed && myURL.pathname === '/feed/channels') {
      // check if the user clicked the back / forward buttons, if so,
      // the data on the page is already loaded,
      // so the content script does not have to wait for it to load.
      void injectManagedContentScript(details, !(details.transitionQualifiers && details.transitionQualifiers.includes('forward_back')));
    }
  }
};

const addYTChannelListeners = function () {
  browser.webNavigation.onHistoryStateUpdated.addListener(ytHistoryHandler, webRequestFilter);
  if (getSettings().youtube_manage_subscribed) {
    browser.webNavigation.onCompleted.addListener(managedSubPageCompleted, webRequestFilter);
  }
};

const removeYTChannelListeners = function () {
  browser.webNavigation.onHistoryStateUpdated.removeListener(ytHistoryHandler, webRequestFilter);
  browser.webNavigation.onCompleted.removeListener(managedSubPageCompleted, webRequestFilter);
};

settings.onload().then(() => {
  if (getSettings().youtube_channel_whitelist) {
    addYTChannelListeners();
  }
});

const openYTManagedSubPage = function () {
  browser.tabs.create({ url: 'https://www.youtube.com/feed/channels' });
};

const getAllAdsAllowedUserFilters = async function () {
  const userFilters = await getUserFilters();
  const adsAllowedUserFilters = [];
  for (let inx = 0; inx < userFilters.length; inx++) {
    const filter = userFilters[inx];
    if (isWhitelistFilter(filter.text) && filter.text && filter.text.includes('youtube.com')) {
      adsAllowedUserFilters.push(filter.text);
    }
  }
  return adsAllowedUserFilters;
};

let previousYTchannelId = '';
let previousYTuserId = '';

// Listen for the message from the content scripts
browser.runtime.onMessage.addListener((message, sender, sendResponse) => {
  if (message.command === 'updateYouTubeChannelName' && message.channelName) {
    ytChannelNamePages.set(sender.tab.id, message.channelName);
    sendResponse({});
    return;
  }
  if (message.command === 'get_channel_name_by_channel_id' && message.channelId) {
    if (previousYTchannelId !== message.channelId) {
      previousYTchannelId = message.channelId;
      const xhr = new XMLHttpRequest();
      const { channelId } = message;
      const key = atob('QUl6YVN5QzJKMG5lbkhJZ083amZaUUYwaVdaN3BKd3dsMFczdUlz');
      const url = 'https://www.googleapis.com/youtube/v3/channels';
      xhr.open('GET', `${url}?part=snippet&id=${channelId}&key=${key}`);
      xhr.onload = function xhrOnload() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          const json = JSON.parse(xhr.response);
          // Got name of the channel
          if (json && json.items && json.items[0]) {
            const channelName = json.items[0].snippet.title;
            ytChannelNamePages.set(sender.tab.id, channelName);
            void browser.tabs.sendMessage(sender.tab.id, {
              command: 'updateURLWithYouTubeChannelName',
              channelName,
            });
          }
        }
      };
      xhr.send();
      sendResponse({});
      return;
    }
    void browser.tabs.sendMessage(sender.tab.id, {
      command: 'updateURLWithYouTubeChannelName',
      channelName: ytChannelNamePages.get(sender.tab.id),
    });
    sendResponse({});
    return;
  }
  if (message.command === 'get_channel_name_by_user_id' && message.userId) {
    if (previousYTuserId !== message.userId) {
      previousYTuserId = message.userId;
      const xhr = new XMLHttpRequest();
      const { userId } = message;
      const key = atob('QUl6YVN5QzJKMG5lbkhJZ083amZaUUYwaVdaN3BKd3dsMFczdUlz');
      const url = 'https://www.googleapis.com/youtube/v3/channels';
      xhr.open('GET', `${url}?part=snippet&forUsername=${userId}&key=${key}`);
      xhr.onload = function xhrOnload() {
        if (xhr.readyState === 4 && xhr.status === 200) {
          const json = JSON.parse(xhr.response);
          // Got name of the channel
          if (json && json.items && json.items[0]) {
            const channelName = json.items[0].snippet.title;
            ytChannelNamePages.set(sender.tab.id, channelName);
            void browser.tabs.sendMessage(sender.tab.id, {
              command: 'updateURLWithYouTubeChannelName',
              channelName,
            });
          }
        }
      };
      xhr.send();
      sendResponse({});
    } else {
      void browser.tabs.sendMessage(sender.tab.id, {
        command: 'updateURLWithYouTubeChannelName',
        channelName: ytChannelNamePages.get(sender.tab.id),
      });
      sendResponse({});
    }
  }
  if (message.command === 'getAllAdsAllowedUserFilters') {
    /* eslint-disable consistent-return */
    return getAllAdsAllowedUserFilters();
  }
  if (message.command === 'removeAllowlistFilterForYoutubeChannel' && message.text) {
    removeAllowlistFilterForYoutubeChannel(message.text);
    sendResponse({});
  }
  if (message.command === 'createWhitelistFilterForYoutubeChannel' && message.url) {
    sendResponse(createWhitelistFilterForYoutubeChannel(message.url, message.origin));
  }
  if (message.command === 'createAllowlistFilterForYoutubeChannelName' && message.channelName) {
    sendResponse(createAllowlistFilterForYoutubeChannelName(message.channelName, message.origin));
  }
  if (message.command === 'blockAllSubscribedChannel' && message.channelNames) {
    setTimeout(async () => {
      const { channelNames } = message;
      const parsedChannelNames = [];
      const userFilters = await getAllAdsAllowedUserFilters();
      for (const [channelName] of Object.entries(channelNames)) {
        const name = channelNames[channelName].parsedChannelName;
        parsedChannelNames.push(name);
        for (let inx = 0; inx < userFilters.length; inx++) {
          const filterText = userFilters[inx];
          if (filterText.indexOf(name) > 1) {
            removeAllowlistFilterForYoutubeChannel(filterText);
          }
        }
      }
    }, 10);
    sendResponse({});
  }
  if (message.command === 'allowAllSubscribedChannel' && message.channelNames) {
    const { channelNames } = message;
    for (const [channelName] of Object.entries(channelNames)) {
      const name = channelNames[channelName].parsedChannelName;
      createAllowlistFilterForYoutubeChannelName(name);
    }
    sendResponse({});
  }
});

// eslint-disable-next-line no-restricted-globals
Object.assign(self, {
  addYTChannelListeners,
  removeYTChannelListeners,
  ytChannelNamePages,
  openYTManagedSubPage,
});


/***/ }),

/***/ 3194:
/***/ ((__unused_webpack_module, exports) => {

"use strict";
var __webpack_unused_export__;
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



let contentTypes =
/**
 * Content types for request blocking and allowing (allowlisting).
 *
 * There are two kinds of content types: resource types, and special
 * (non-resource) types.
 *
 * Resource types include web resources like scripts, images, and so on.
 *
 * Special types include filter options for popup blocking and CSP header
 * injection as well as flags for allowing documents.
 *
 * By default a filter matches any resource type, but if a filter has an
 * explicit resource type, special option, or allowing flag, like
 * `$script`, `$popup`, or `$elemhide`, then it matches only the given type,
 * option, or flag.
 *
 * @type {Object}
 *
 * @public
 */
exports.Tr = {
  // Types of web resources.
  OTHER: 1,
  SCRIPT: 2,
  IMAGE: 4,
  STYLESHEET: 8,
  OBJECT: 16,
  SUBDOCUMENT: 32,
  WEBSOCKET: 128,
  WEBRTC: 256,
  PING: 1024,
  XMLHTTPREQUEST: 2048, // 1 << 11

  MEDIA: 16384,
  FONT: 32768, // 1 << 15

  // Special filter options.
  POPUP: 1 << 24,
  CSP: 1 << 25,
  HEADER: 1 << 26,

  // Allowing flags.
  DOCUMENT: 1 << 27,
  GENERICBLOCK: 1 << 28,
  ELEMHIDE: 1 << 29,
  GENERICHIDE: 1 << 30
};

// Backwards compatibility.
contentTypes.BACKGROUND = contentTypes.IMAGE;
contentTypes.XBL = contentTypes.OTHER;
contentTypes.DTD = contentTypes.OTHER;

const RESOURCE_TYPES =
/**
 * Bitmask for resource types like `$script`, `$image`, `$stylesheet`, and so
 * on.
 *
 * If a filter has no explicit content type, it applies to all resource types
 * (but not to any {@link module:contentTypes.SPECIAL_TYPES special types}).
 *
 * @const {number}
 *
 * @package
 */
// The first 24 bits are reserved for resource types like "script", "image",
// and so on.
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType
__webpack_unused_export__ = (1 << 24) - 1;

const SPECIAL_TYPES = ~RESOURCE_TYPES & (1 << 31) - 1;
/**
 * Bitmask for special "types" (options and flags) like `$csp`, `$elemhide`,
 * and so on.
 *
 * @const {number}
 *
 * @package
 */
__webpack_unused_export__ = SPECIAL_TYPES;

/**
 * Bitmask for "types" that match against request context more than
 * actual content type. When matching against context types, you
 * should also include the request's resource type.
 *
 * @const {number}
 *
 * @package
 */
const CONTEXT_TYPES = contentTypes.HEADER | contentTypes.CSP;
__webpack_unused_export__ = CONTEXT_TYPES;

/**
 * Bitmask for "types" (flags) that are for exception rules only, like
 * `$document`, `$elemhide`, and so on.
 *
 * @const {number}
 *
 * @package
 */
__webpack_unused_export__ = contentTypes.DOCUMENT |
                         contentTypes.GENERICBLOCK |
                         contentTypes.ELEMHIDE |
                         contentTypes.GENERICHIDE;

/**
 * Yields individual types from a filter's type mask.
 *
 * @param {number} contentType A filter's type mask.
 * @param {number} [selection] Which types to yield.
 *
 * @generator
 * @yields {number}
 *
 * @package
 */
__webpack_unused_export__ = function* enumerateTypes(contentType, selection = ~0) {
  for (let mask = contentType & selection, bitIndex = 0;
    mask != 0; mask >>>= 1, bitIndex++) {
    if ((mask & 1) != 0) {
      // Note: The zero-fill right shift by zero is necessary for dropping the
      // sign.
      yield 1 << bitIndex >>> 0;
    }
  }
};


/***/ }),

/***/ 1935:
/***/ (function(module, exports) {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
		__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
		(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  } else { var mod; }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (module) {
  /* webextension-polyfill - v0.8.0 - Tue Apr 20 2021 11:27:38 */

  /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */

  /* vim: set sts=2 sw=2 et tw=80: */

  /* This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  "use strict";

  if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.prototype) {
    const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received.";
    const SEND_RESPONSE_DEPRECATION_WARNING = "Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)"; // Wrapping the bulk of this polyfill in a one-time-use function is a minor
    // optimization for Firefox. Since Spidermonkey does not fully parse the
    // contents of a function until the first time it's called, and since it will
    // never actually need to be called, this allows the polyfill to be included
    // in Firefox nearly for free.

    const wrapAPIs = extensionAPIs => {
      // NOTE: apiMetadata is associated to the content of the api-metadata.json file
      // at build time by replacing the following "include" with the content of the
      // JSON file.
      const apiMetadata = {
        "alarms": {
          "clear": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "clearAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "get": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "bookmarks": {
          "create": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getChildren": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getRecent": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getSubTree": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTree": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "move": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeTree": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "browserAction": {
          "disable": {
            "minArgs": 0,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "enable": {
            "minArgs": 0,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "getBadgeBackgroundColor": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getBadgeText": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getPopup": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTitle": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "openPopup": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "setBadgeBackgroundColor": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setBadgeText": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setIcon": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "setPopup": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setTitle": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "browsingData": {
          "remove": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "removeCache": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeCookies": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeDownloads": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeFormData": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeHistory": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeLocalStorage": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removePasswords": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removePluginData": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "settings": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "commands": {
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "contextMenus": {
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "cookies": {
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAllCookieStores": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "set": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "devtools": {
          "inspectedWindow": {
            "eval": {
              "minArgs": 1,
              "maxArgs": 2,
              "singleCallbackArg": false
            }
          },
          "panels": {
            "create": {
              "minArgs": 3,
              "maxArgs": 3,
              "singleCallbackArg": true
            },
            "elements": {
              "createSidebarPane": {
                "minArgs": 1,
                "maxArgs": 1
              }
            }
          }
        },
        "downloads": {
          "cancel": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "download": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "erase": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getFileIcon": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "open": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "pause": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeFile": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "resume": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "show": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "extension": {
          "isAllowedFileSchemeAccess": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "isAllowedIncognitoAccess": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "history": {
          "addUrl": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "deleteAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "deleteRange": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "deleteUrl": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getVisits": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "i18n": {
          "detectLanguage": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAcceptLanguages": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "identity": {
          "launchWebAuthFlow": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "idle": {
          "queryState": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "management": {
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getSelf": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "setEnabled": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "uninstallSelf": {
            "minArgs": 0,
            "maxArgs": 1
          }
        },
        "notifications": {
          "clear": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "create": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getPermissionLevel": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "pageAction": {
          "getPopup": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTitle": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "hide": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setIcon": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "setPopup": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setTitle": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "show": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "permissions": {
          "contains": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "request": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "runtime": {
          "getBackgroundPage": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getPlatformInfo": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "openOptionsPage": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "requestUpdateCheck": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "sendMessage": {
            "minArgs": 1,
            "maxArgs": 3
          },
          "sendNativeMessage": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "setUninstallURL": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "sessions": {
          "getDevices": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getRecentlyClosed": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "restore": {
            "minArgs": 0,
            "maxArgs": 1
          }
        },
        "storage": {
          "local": {
            "clear": {
              "minArgs": 0,
              "maxArgs": 0
            },
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "remove": {
              "minArgs": 1,
              "maxArgs": 1
            },
            "set": {
              "minArgs": 1,
              "maxArgs": 1
            }
          },
          "managed": {
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            }
          },
          "sync": {
            "clear": {
              "minArgs": 0,
              "maxArgs": 0
            },
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "remove": {
              "minArgs": 1,
              "maxArgs": 1
            },
            "set": {
              "minArgs": 1,
              "maxArgs": 1
            }
          }
        },
        "tabs": {
          "captureVisibleTab": {
            "minArgs": 0,
            "maxArgs": 2
          },
          "create": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "detectLanguage": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "discard": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "duplicate": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "executeScript": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getCurrent": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getZoom": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getZoomSettings": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "goBack": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "goForward": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "highlight": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "insertCSS": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "move": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "query": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "reload": {
            "minArgs": 0,
            "maxArgs": 2
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeCSS": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "sendMessage": {
            "minArgs": 2,
            "maxArgs": 3
          },
          "setZoom": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "setZoomSettings": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "update": {
            "minArgs": 1,
            "maxArgs": 2
          }
        },
        "topSites": {
          "get": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "webNavigation": {
          "getAllFrames": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getFrame": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "webRequest": {
          "handlerBehaviorChanged": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "windows": {
          "create": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getCurrent": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getLastFocused": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        }
      };

      if (Object.keys(apiMetadata).length === 0) {
        throw new Error("api-metadata.json has not been included in browser-polyfill");
      }
      /**
       * A WeakMap subclass which creates and stores a value for any key which does
       * not exist when accessed, but behaves exactly as an ordinary WeakMap
       * otherwise.
       *
       * @param {function} createItem
       *        A function which will be called in order to create the value for any
       *        key which does not exist, the first time it is accessed. The
       *        function receives, as its only argument, the key being created.
       */


      class DefaultWeakMap extends WeakMap {
        constructor(createItem, items = undefined) {
          super(items);
          this.createItem = createItem;
        }

        get(key) {
          if (!this.has(key)) {
            this.set(key, this.createItem(key));
          }

          return super.get(key);
        }

      }
      /**
       * Returns true if the given object is an object with a `then` method, and can
       * therefore be assumed to behave as a Promise.
       *
       * @param {*} value The value to test.
       * @returns {boolean} True if the value is thenable.
       */


      const isThenable = value => {
        return value && typeof value === "object" && typeof value.then === "function";
      };
      /**
       * Creates and returns a function which, when called, will resolve or reject
       * the given promise based on how it is called:
       *
       * - If, when called, `chrome.runtime.lastError` contains a non-null object,
       *   the promise is rejected with that value.
       * - If the function is called with exactly one argument, the promise is
       *   resolved to that value.
       * - Otherwise, the promise is resolved to an array containing all of the
       *   function's arguments.
       *
       * @param {object} promise
       *        An object containing the resolution and rejection functions of a
       *        promise.
       * @param {function} promise.resolve
       *        The promise's resolution function.
       * @param {function} promise.reject
       *        The promise's rejection function.
       * @param {object} metadata
       *        Metadata about the wrapped method which has created the callback.
       * @param {boolean} metadata.singleCallbackArg
       *        Whether or not the promise is resolved with only the first
       *        argument of the callback, alternatively an array of all the
       *        callback arguments is resolved. By default, if the callback
       *        function is invoked with only a single argument, that will be
       *        resolved to the promise, while all arguments will be resolved as
       *        an array if multiple are given.
       *
       * @returns {function}
       *        The generated callback function.
       */


      const makeCallback = (promise, metadata) => {
        return (...callbackArgs) => {
          if (extensionAPIs.runtime.lastError) {
            promise.reject(new Error(extensionAPIs.runtime.lastError.message));
          } else if (metadata.singleCallbackArg || callbackArgs.length <= 1 && metadata.singleCallbackArg !== false) {
            promise.resolve(callbackArgs[0]);
          } else {
            promise.resolve(callbackArgs);
          }
        };
      };

      const pluralizeArguments = numArgs => numArgs == 1 ? "argument" : "arguments";
      /**
       * Creates a wrapper function for a method with the given name and metadata.
       *
       * @param {string} name
       *        The name of the method which is being wrapped.
       * @param {object} metadata
       *        Metadata about the method being wrapped.
       * @param {integer} metadata.minArgs
       *        The minimum number of arguments which must be passed to the
       *        function. If called with fewer than this number of arguments, the
       *        wrapper will raise an exception.
       * @param {integer} metadata.maxArgs
       *        The maximum number of arguments which may be passed to the
       *        function. If called with more than this number of arguments, the
       *        wrapper will raise an exception.
       * @param {boolean} metadata.singleCallbackArg
       *        Whether or not the promise is resolved with only the first
       *        argument of the callback, alternatively an array of all the
       *        callback arguments is resolved. By default, if the callback
       *        function is invoked with only a single argument, that will be
       *        resolved to the promise, while all arguments will be resolved as
       *        an array if multiple are given.
       *
       * @returns {function(object, ...*)}
       *       The generated wrapper function.
       */


      const wrapAsyncFunction = (name, metadata) => {
        return function asyncFunctionWrapper(target, ...args) {
          if (args.length < metadata.minArgs) {
            throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
          }

          if (args.length > metadata.maxArgs) {
            throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
          }

          return new Promise((resolve, reject) => {
            if (metadata.fallbackToNoCallback) {
              // This API method has currently no callback on Chrome, but it return a promise on Firefox,
              // and so the polyfill will try to call it with a callback first, and it will fallback
              // to not passing the callback if the first call fails.
              try {
                target[name](...args, makeCallback({
                  resolve,
                  reject
                }, metadata));
              } catch (cbError) {
                console.warn(`${name} API method doesn't seem to support the callback parameter, ` + "falling back to call it without a callback: ", cbError);
                target[name](...args); // Update the API method metadata, so that the next API calls will not try to
                // use the unsupported callback anymore.

                metadata.fallbackToNoCallback = false;
                metadata.noCallback = true;
                resolve();
              }
            } else if (metadata.noCallback) {
              target[name](...args);
              resolve();
            } else {
              target[name](...args, makeCallback({
                resolve,
                reject
              }, metadata));
            }
          });
        };
      };
      /**
       * Wraps an existing method of the target object, so that calls to it are
       * intercepted by the given wrapper function. The wrapper function receives,
       * as its first argument, the original `target` object, followed by each of
       * the arguments passed to the original method.
       *
       * @param {object} target
       *        The original target object that the wrapped method belongs to.
       * @param {function} method
       *        The method being wrapped. This is used as the target of the Proxy
       *        object which is created to wrap the method.
       * @param {function} wrapper
       *        The wrapper function which is called in place of a direct invocation
       *        of the wrapped method.
       *
       * @returns {Proxy<function>}
       *        A Proxy object for the given method, which invokes the given wrapper
       *        method in its place.
       */


      const wrapMethod = (target, method, wrapper) => {
        return new Proxy(method, {
          apply(targetMethod, thisObj, args) {
            return wrapper.call(thisObj, target, ...args);
          }

        });
      };

      let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);
      /**
       * Wraps an object in a Proxy which intercepts and wraps certain methods
       * based on the given `wrappers` and `metadata` objects.
       *
       * @param {object} target
       *        The target object to wrap.
       *
       * @param {object} [wrappers = {}]
       *        An object tree containing wrapper functions for special cases. Any
       *        function present in this object tree is called in place of the
       *        method in the same location in the `target` object tree. These
       *        wrapper methods are invoked as described in {@see wrapMethod}.
       *
       * @param {object} [metadata = {}]
       *        An object tree containing metadata used to automatically generate
       *        Promise-based wrapper functions for asynchronous. Any function in
       *        the `target` object tree which has a corresponding metadata object
       *        in the same location in the `metadata` tree is replaced with an
       *        automatically-generated wrapper function, as described in
       *        {@see wrapAsyncFunction}
       *
       * @returns {Proxy<object>}
       */

      const wrapObject = (target, wrappers = {}, metadata = {}) => {
        let cache = Object.create(null);
        let handlers = {
          has(proxyTarget, prop) {
            return prop in target || prop in cache;
          },

          get(proxyTarget, prop, receiver) {
            if (prop in cache) {
              return cache[prop];
            }

            if (!(prop in target)) {
              return undefined;
            }

            let value = target[prop];

            if (typeof value === "function") {
              // This is a method on the underlying object. Check if we need to do
              // any wrapping.
              if (typeof wrappers[prop] === "function") {
                // We have a special-case wrapper for this method.
                value = wrapMethod(target, target[prop], wrappers[prop]);
              } else if (hasOwnProperty(metadata, prop)) {
                // This is an async method that we have metadata for. Create a
                // Promise wrapper for it.
                let wrapper = wrapAsyncFunction(prop, metadata[prop]);
                value = wrapMethod(target, target[prop], wrapper);
              } else {
                // This is a method that we don't know or care about. Return the
                // original method, bound to the underlying object.
                value = value.bind(target);
              }
            } else if (typeof value === "object" && value !== null && (hasOwnProperty(wrappers, prop) || hasOwnProperty(metadata, prop))) {
              // This is an object that we need to do some wrapping for the children
              // of. Create a sub-object wrapper for it with the appropriate child
              // metadata.
              value = wrapObject(value, wrappers[prop], metadata[prop]);
            } else if (hasOwnProperty(metadata, "*")) {
              // Wrap all properties in * namespace.
              value = wrapObject(value, wrappers[prop], metadata["*"]);
            } else {
              // We don't need to do any wrapping for this property,
              // so just forward all access to the underlying object.
              Object.defineProperty(cache, prop, {
                configurable: true,
                enumerable: true,

                get() {
                  return target[prop];
                },

                set(value) {
                  target[prop] = value;
                }

              });
              return value;
            }

            cache[prop] = value;
            return value;
          },

          set(proxyTarget, prop, value, receiver) {
            if (prop in cache) {
              cache[prop] = value;
            } else {
              target[prop] = value;
            }

            return true;
          },

          defineProperty(proxyTarget, prop, desc) {
            return Reflect.defineProperty(cache, prop, desc);
          },

          deleteProperty(proxyTarget, prop) {
            return Reflect.deleteProperty(cache, prop);
          }

        }; // Per contract of the Proxy API, the "get" proxy handler must return the
        // original value of the target if that value is declared read-only and
        // non-configurable. For this reason, we create an object with the
        // prototype set to `target` instead of using `target` directly.
        // Otherwise we cannot return a custom object for APIs that
        // are declared read-only and non-configurable, such as `chrome.devtools`.
        //
        // The proxy handlers themselves will still use the original `target`
        // instead of the `proxyTarget`, so that the methods and properties are
        // dereferenced via the original targets.

        let proxyTarget = Object.create(target);
        return new Proxy(proxyTarget, handlers);
      };
      /**
       * Creates a set of wrapper functions for an event object, which handles
       * wrapping of listener functions that those messages are passed.
       *
       * A single wrapper is created for each listener function, and stored in a
       * map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`
       * retrieve the original wrapper, so that  attempts to remove a
       * previously-added listener work as expected.
       *
       * @param {DefaultWeakMap<function, function>} wrapperMap
       *        A DefaultWeakMap object which will create the appropriate wrapper
       *        for a given listener function when one does not exist, and retrieve
       *        an existing one when it does.
       *
       * @returns {object}
       */


      const wrapEvent = wrapperMap => ({
        addListener(target, listener, ...args) {
          target.addListener(wrapperMap.get(listener), ...args);
        },

        hasListener(target, listener) {
          return target.hasListener(wrapperMap.get(listener));
        },

        removeListener(target, listener) {
          target.removeListener(wrapperMap.get(listener));
        }

      });

      const onRequestFinishedWrappers = new DefaultWeakMap(listener => {
        if (typeof listener !== "function") {
          return listener;
        }
        /**
         * Wraps an onRequestFinished listener function so that it will return a
         * `getContent()` property which returns a `Promise` rather than using a
         * callback API.
         *
         * @param {object} req
         *        The HAR entry object representing the network request.
         */


        return function onRequestFinished(req) {
          const wrappedReq = wrapObject(req, {}
          /* wrappers */
          , {
            getContent: {
              minArgs: 0,
              maxArgs: 0
            }
          });
          listener(wrappedReq);
        };
      }); // Keep track if the deprecation warning has been logged at least once.

      let loggedSendResponseDeprecationWarning = false;
      const onMessageWrappers = new DefaultWeakMap(listener => {
        if (typeof listener !== "function") {
          return listener;
        }
        /**
         * Wraps a message listener function so that it may send responses based on
         * its return value, rather than by returning a sentinel value and calling a
         * callback. If the listener function returns a Promise, the response is
         * sent when the promise either resolves or rejects.
         *
         * @param {*} message
         *        The message sent by the other end of the channel.
         * @param {object} sender
         *        Details about the sender of the message.
         * @param {function(*)} sendResponse
         *        A callback which, when called with an arbitrary argument, sends
         *        that value as a response.
         * @returns {boolean}
         *        True if the wrapped listener returned a Promise, which will later
         *        yield a response. False otherwise.
         */


        return function onMessage(message, sender, sendResponse) {
          let didCallSendResponse = false;
          let wrappedSendResponse;
          let sendResponsePromise = new Promise(resolve => {
            wrappedSendResponse = function (response) {
              if (!loggedSendResponseDeprecationWarning) {
                console.warn(SEND_RESPONSE_DEPRECATION_WARNING, new Error().stack);
                loggedSendResponseDeprecationWarning = true;
              }

              didCallSendResponse = true;
              resolve(response);
            };
          });
          let result;

          try {
            result = listener(message, sender, wrappedSendResponse);
          } catch (err) {
            result = Promise.reject(err);
          }

          const isResultThenable = result !== true && isThenable(result); // If the listener didn't returned true or a Promise, or called
          // wrappedSendResponse synchronously, we can exit earlier
          // because there will be no response sent from this listener.

          if (result !== true && !isResultThenable && !didCallSendResponse) {
            return false;
          } // A small helper to send the message if the promise resolves
          // and an error if the promise rejects (a wrapped sendMessage has
          // to translate the message into a resolved promise or a rejected
          // promise).


          const sendPromisedResult = promise => {
            promise.then(msg => {
              // send the message value.
              sendResponse(msg);
            }, error => {
              // Send a JSON representation of the error if the rejected value
              // is an instance of error, or the object itself otherwise.
              let message;

              if (error && (error instanceof Error || typeof error.message === "string")) {
                message = error.message;
              } else {
                message = "An unexpected error occurred";
              }

              sendResponse({
                __mozWebExtensionPolyfillReject__: true,
                message
              });
            }).catch(err => {
              // Print an error on the console if unable to send the response.
              console.error("Failed to send onMessage rejected reply", err);
            });
          }; // If the listener returned a Promise, send the resolved value as a
          // result, otherwise wait the promise related to the wrappedSendResponse
          // callback to resolve and send it as a response.


          if (isResultThenable) {
            sendPromisedResult(result);
          } else {
            sendPromisedResult(sendResponsePromise);
          } // Let Chrome know that the listener is replying.


          return true;
        };
      });

      const wrappedSendMessageCallback = ({
        reject,
        resolve
      }, reply) => {
        if (extensionAPIs.runtime.lastError) {
          // Detect when none of the listeners replied to the sendMessage call and resolve
          // the promise to undefined as in Firefox.
          // See https://github.com/mozilla/webextension-polyfill/issues/130
          if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {
            resolve();
          } else {
            reject(new Error(extensionAPIs.runtime.lastError.message));
          }
        } else if (reply && reply.__mozWebExtensionPolyfillReject__) {
          // Convert back the JSON representation of the error into
          // an Error instance.
          reject(new Error(reply.message));
        } else {
          resolve(reply);
        }
      };

      const wrappedSendMessage = (name, metadata, apiNamespaceObj, ...args) => {
        if (args.length < metadata.minArgs) {
          throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
        }

        if (args.length > metadata.maxArgs) {
          throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
        }

        return new Promise((resolve, reject) => {
          const wrappedCb = wrappedSendMessageCallback.bind(null, {
            resolve,
            reject
          });
          args.push(wrappedCb);
          apiNamespaceObj.sendMessage(...args);
        });
      };

      const staticWrappers = {
        devtools: {
          network: {
            onRequestFinished: wrapEvent(onRequestFinishedWrappers)
          }
        },
        runtime: {
          onMessage: wrapEvent(onMessageWrappers),
          onMessageExternal: wrapEvent(onMessageWrappers),
          sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
            minArgs: 1,
            maxArgs: 3
          })
        },
        tabs: {
          sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
            minArgs: 2,
            maxArgs: 3
          })
        }
      };
      const settingMetadata = {
        clear: {
          minArgs: 1,
          maxArgs: 1
        },
        get: {
          minArgs: 1,
          maxArgs: 1
        },
        set: {
          minArgs: 1,
          maxArgs: 1
        }
      };
      apiMetadata.privacy = {
        network: {
          "*": settingMetadata
        },
        services: {
          "*": settingMetadata
        },
        websites: {
          "*": settingMetadata
        }
      };
      return wrapObject(extensionAPIs, staticWrappers, apiMetadata);
    };

    if (typeof chrome != "object" || !chrome || !chrome.runtime || !chrome.runtime.id) {
      throw new Error("This script should only be loaded in a browser extension.");
    } // The build process adds a UMD wrapper around this file, which makes the
    // `module` variable available.


    module.exports = wrapAPIs(chrome);
  } else {
    module.exports = browser;
  }
});


/***/ }),

/***/ 6703:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "n": () => (/* reexport */ getUserId)
});

// EXTERNAL MODULE: ./node_modules/webextension-polyfill/dist/browser-polyfill.js
var browser_polyfill = __webpack_require__(1935);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/id/background/id.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};


const userIdStorageKey = 'userid';
function getUserId() {
    return __awaiter(this, void 0, void 0, function* () {
        const response = yield browser_polyfill.storage.local.get(userIdStorageKey);
        let userId = '';
        if (!response[userIdStorageKey]) {
            const timeSuffix = (Date.now()) % 1e8;
            const alphabet = 'abcdefghijklmnopqrstuvwxyz0123456789';
            const result = [];
            for (let i = 0; i < 8; i++) {
                const choice = Math.floor(Math.random() * alphabet.length);
                result.push(alphabet[choice]);
            }
            userId = result.join('') + timeSuffix;
            (0,bg_functions/* chromeStorageSetHelper */.rJ)(userIdStorageKey, userId);
        }
        else {
            userId = response[userIdStorageKey];
        }
        return userId;
    });
}

;// CONCATENATED MODULE: ./adblock-betafish/id/background/index.ts



/***/ }),

/***/ 9164:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "G7": () => (/* reexport */ CommandName),
  "QF": () => (/* reexport */ clearEvents),
  "qX": () => (/* reexport */ createSafeOriginUrl),
  "_E": () => (/* reexport */ dismissCommand),
  "LE": () => (/* reexport */ executeIPMCommand),
  "J": () => (/* reexport */ getBehavior),
  "L5": () => (/* reexport */ getContent),
  "He": () => (/* reexport */ getPayload),
  "UE": () => (/* reexport */ isNotEmpty),
  "w6": () => (/* reexport */ isSafeUrl),
  "Ny": () => (/* reexport */ recordEvent),
  "yA": () => (/* reexport */ setCommandActor),
  "uU": () => (/* reexport */ validateParams)
});

// UNUSED EXPORTS: DataType, LicenseState, PlatformStatus, PlatformType, commandLibraryVersion, eventStorageKey, isNumeric

// EXTERNAL MODULE: ./adblock-betafish/utilities/background/index.ts + 2 modules
var background = __webpack_require__(9555);
// EXTERNAL MODULE: ./adblock-betafish/alias/prefs.js
var prefs = __webpack_require__(4428);
;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/command-library.types.ts
const commandLibraryVersion = 1;
var CommandName;
(function (CommandName) {
    CommandName["createOnPageDialog"] = "create_on_page_dialog";
    CommandName["createTab"] = "create_tab";
})(CommandName || (CommandName = {}));

;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/command-library.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};



const knownCommandsList = Object.values(CommandName);
const commandStorageKey = "ipm_commands";
const actorByCommandName = new Map();
const unexecutableCommands = new Map();
function isCommand(candidate) {
    return (typeof candidate === "object" &&
        candidate !== null &&
        "version" in candidate &&
        "ipm_id" in candidate &&
        "command_name" in candidate);
}
function setCommandActor(commandName, actor) {
    actorByCommandName.set(commandName, actor);
    retryExecuteCommands(commandName);
}
function canProcessCommand(command) {
    return (command.version === commandLibraryVersion &&
        knownCommandsList.includes(command.command_name));
}
function dismissCommand(ipmId) {
    const command = getCommand(ipmId);
    if (!command) {
        return;
    }
    const commandStorage = prefs/* Prefs.get */.B.get(commandStorageKey);
    delete commandStorage[command.ipm_id];
    prefs/* Prefs.set */.B.set(commandStorageKey, commandStorage);
}
function getBehavior(ipmId) {
    const command = getCommand(ipmId);
    if (!command) {
        return null;
    }
    const actor = actorByCommandName.get(command.command_name);
    if (!actor) {
        return null;
    }
    return actor.getBehavior(command);
}
function getCommand(ipmId) {
    const commandStorage = prefs/* Prefs.get */.B.get(commandStorageKey);
    return commandStorage[ipmId] || null;
}
function getContent(ipmId) {
    const command = getCommand(ipmId);
    if (!command) {
        return null;
    }
    const actor = actorByCommandName.get(command.command_name);
    if (!actor) {
        return null;
    }
    return actor.getContent(command);
}
function hasProcessedCommand(ipmId) {
    const commandStorage = prefs/* Prefs.get */.B.get(commandStorageKey);
    return ipmId in commandStorage;
}
function retryExecuteCommands(commandName) {
    for (const [command, isInitialization] of unexecutableCommands) {
        if (command.command_name !== commandName) {
            continue;
        }
        unexecutableCommands.delete(command);
        executeIPMCommand(command, isInitialization);
    }
}
function storeCommandData(command) {
    const storage = prefs/* Prefs.get */.B.get(commandStorageKey);
    storage[command.ipm_id] = command;
    prefs/* Prefs.set */.B.set(commandStorageKey, storage);
}
function executeIPMCommand(command, isInitialization = false) {
    if (!isCommand(command)) {
        background/* error */.vU("[ipm]: Invalid command received.");
        return;
    }
    if (!canProcessCommand(command)) {
        background/* error */.vU("[ipm]: Unknown command name received:", command.command_name);
        return;
    }
    const actor = actorByCommandName.get(command.command_name);
    if (!actor) {
        background/* warn */.ZK("[ipm]: No actor found:", command.command_name);
        unexecutableCommands.set(command, isInitialization);
        return;
    }
    if (!actor.isValidCommand(command)) {
        background/* error */.vU("[ipm]: Invalid parameters received.");
        return;
    }
    if (!isInitialization) {
        if (hasProcessedCommand(command.ipm_id)) {
            background/* error */.vU("[ipm]: Campaign already processed:", command.ipm_id);
            return;
        }
        storeCommandData(command);
    }
    actor.handleCommand(command.ipm_id);
}
function start() {
    return __awaiter(this, void 0, void 0, function* () {
        yield prefs/* Prefs.untilLoaded */.B.untilLoaded;
        const commandStorage = prefs/* Prefs.get */.B.get(commandStorageKey);
        for (const command of Object.values(commandStorage)) {
            executeIPMCommand(command, true);
        }
    });
}
void start().catch(background/* error */.vU);

// EXTERNAL MODULE: ./build/templates/info.chrome.js.tmpl
var info_chrome_js = __webpack_require__(755);
// EXTERNAL MODULE: ./node_modules/webextension-polyfill/dist/browser-polyfill.js
var browser_polyfill = __webpack_require__(1935);
;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/data-collection.types.ts
var DataType;
(function (DataType) {
    DataType["customer"] = "customer";
    DataType["device"] = "device";
    DataType["event"] = "event";
})(DataType || (DataType = {}));
var PlatformType;
(function (PlatformType) {
    PlatformType["web"] = "web";
})(PlatformType || (PlatformType = {}));
var LicenseState;
(function (LicenseState) {
    LicenseState["active"] = "active";
    LicenseState["inactive"] = "inactive";
})(LicenseState || (LicenseState = {}));
var PlatformStatus;
(function (PlatformStatus) {
    PlatformStatus["true"] = "true";
})(PlatformStatus || (PlatformStatus = {}));
const eventStorageKey = 'ipm_events';

// EXTERNAL MODULE: ./adblock-betafish/id/background/index.ts + 1 modules
var id_background = __webpack_require__(6703);
// EXTERNAL MODULE: ./adblock-betafish/picreplacement/check.js
var check = __webpack_require__(2509);
;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/data-collection.ts
var data_collection_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};







function leftPad(value) {
    return value.toString().padStart(2, '0');
}
function getLocalTime() {
    const date = new Date();
    return [
        date.getFullYear(),
        '-',
        leftPad(date.getMonth() + 1),
        '-',
        leftPad(date.getDate()),
        'T',
        leftPad(date.getHours()),
        ':',
        leftPad(date.getMinutes()),
        ':',
        leftPad(date.getSeconds()),
    ].join('');
}
function getBaseAttributes() {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        return {
            app_name: info_chrome_js.baseName,
            browser_name: info_chrome_js.application,
            os: (yield browser_polyfill.runtime.getPlatformInfo()).os,
            language_tag: browser_polyfill.i18n.getUILanguage(),
            app_version: info_chrome_js.addonVersion,
            command_library_version: commandLibraryVersion,
            install_type: (yield browser_polyfill.management.getSelf()).installType,
        };
    });
}
function getEventData(ipmId, name) {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        return {
            type: DataType.event,
            device_id: yield (0,id_background/* getUserId */.n)(),
            action: name,
            platform: PlatformType.web,
            app_version: info_chrome_js.addonVersion,
            user_time: getLocalTime(),
            attributes: Object.assign(Object.assign({}, (yield getBaseAttributes())), { ipm_id: ipmId }),
        };
    });
}
function getDeviceData() {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        yield prefs/* Prefs.untilLoaded */.B.untilLoaded;
        return {
            type: DataType.device,
            device_id: yield (0,id_background/* getUserId */.n)(),
            attributes: Object.assign(Object.assign({}, (yield getBaseAttributes())), { blocked_total: prefs/* Prefs.get */.B.get('blocked_total'), license_status: check/* License.isActiveLicense */.Cz.isActiveLicense() ? LicenseState.active : LicenseState.inactive }),
        };
    });
}
function getUserData() {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        return {
            type: DataType.customer,
            platforms: [{ platform: PlatformType.web, active: PlatformStatus["true"] }],
            attributes: yield getBaseAttributes(),
        };
    });
}
function getPayload() {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        yield prefs/* Prefs.untilLoaded */.B.untilLoaded;
        const user = yield getUserData();
        const device = yield getDeviceData();
        const events = prefs/* Prefs.get */.B.get(eventStorageKey);
        return { user, device, events };
    });
}
function clearEvents() {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        yield prefs/* Prefs.untilLoaded */.B.untilLoaded;
        prefs/* Prefs.set */.B.set(eventStorageKey, []);
    });
}
function recordEvent(ipmId, name) {
    return data_collection_awaiter(this, void 0, void 0, function* () {
        yield prefs/* Prefs.untilLoaded */.B.untilLoaded;
        const eventData = yield getEventData(ipmId, name);
        const eventStorage = prefs/* Prefs.get */.B.get(eventStorageKey);
        eventStorage.push(eventData);
        prefs/* Prefs.set */.B.set(eventStorageKey, eventStorage);
    });
}

;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/url.ts

function createSafeOriginUrl(url) {
    const safeOrigin = prefs/* Prefs.get */.B.get("ipm_safe_origin");
    let safeOriginUrl;
    try {
        safeOriginUrl = new URL(url, safeOrigin);
    }
    catch (ex) {
        return null;
    }
    if (safeOriginUrl.origin !== safeOrigin) {
        return null;
    }
    return safeOriginUrl.href;
}

;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/param-validator.ts

const isNumeric = (param) => typeof param === "number" && !Number.isNaN(param);
const isNotEmpty = (param) => typeof param === "string" && param.length > 0;
const isSafeUrl = (param) => {
    if (typeof param !== "string") {
        return false;
    }
    const url = createSafeOriginUrl(param);
    return typeof url === "string";
};
function validateParams(command, paramDefinitions) {
    return paramDefinitions
        .map((definition) => {
        const name = String(definition.name);
        const param = command[name];
        return definition.validate(param)
            ? ""
            : `Invalid value for parameter "${name}", got "${param}":`;
    })
        .filter((result) => result !== "");
}

;// CONCATENATED MODULE: ./adblock-betafish/ipm/background/index.ts









/***/ }),

/***/ 6141:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// EXTERNAL MODULE: ./node_modules/webextension-polyfill/dist/browser-polyfill.js
var browser_polyfill = __webpack_require__(1935);
// EXTERNAL MODULE: ./adblock-betafish/ipm/background/index.ts + 6 modules
var background = __webpack_require__(9164);
// EXTERNAL MODULE: ./adblock-betafish/picreplacement/check.js
var check = __webpack_require__(2509);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/index.ts + 2 modules
var utilities_background = __webpack_require__(9555);
// EXTERNAL MODULE: ./adblock-betafish/prefs/background/settings.js
var settings = __webpack_require__(7330);
;// CONCATENATED MODULE: ./adblock-betafish/new-tab/background/middleware/new-tab.ts


const paramDefinitionList = [
    {
        name: 'url',
        validate: background/* isSafeUrl */.w6,
    },
];
function isNewTabCommand(command) {
    const validationErrors = (0,background/* validateParams */.uU)(command, paramDefinitionList);
    if (validationErrors.length === 0) {
        return true;
    }
    utilities_background/* error */.vU('[new-tab]: Invalid parameters received:', validationErrors.join(' '));
    return false;
}
function isNewTabBehavior(candidate) {
    return (candidate !== null
        && typeof candidate === 'object'
        && 'target' in candidate);
}
function getBehavior(command) {
    if (!isNewTabCommand(command)) {
        return null;
    }
    return {
        target: command.url,
    };
}
function getContent() {
    return null;
}
function setNewTabCommandHandler(handler) {
    (0,background/* setCommandActor */.yA)(background/* CommandName.createTab */.G7.createTab, {
        getBehavior,
        getContent,
        handleCommand: handler,
        isValidCommand: isNewTabCommand,
    });
}

;// CONCATENATED MODULE: ./adblock-betafish/new-tab/background/middleware/new-tab.types.ts
var NewTabEventType;
(function (NewTabEventType) {
    NewTabEventType["created"] = "tab_created";
    NewTabEventType["loaded"] = "tab_loaded";
})(NewTabEventType || (NewTabEventType = {}));

;// CONCATENATED MODULE: ./adblock-betafish/new-tab/background/middleware/index.ts



;// CONCATENATED MODULE: ./adblock-betafish/new-tab/background/tab-manager.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};






const tabIds = new Set();
const onCreatedHandlerByIPMids = new Map();
const onUpdatedHandlerByIPMids = new Map();
const openNewtabOnUpdatedHandlerByIPMids = new Map();
const openNewtabOnUpdated = (ipmId, tabId, changeInfo, tab) => {
    if (changeInfo.status !== 'complete' || tab === null || tabId !== tab.id) {
        return;
    }
    const onUpdatedHandler = openNewtabOnUpdatedHandlerByIPMids.get(ipmId);
    openNewtabOnUpdatedHandlerByIPMids.delete(ipmId);
    browser_polyfill.tabs.onUpdated.removeListener(onUpdatedHandler);
    (0,background/* recordEvent */.Ny)(ipmId, NewTabEventType.loaded);
};
function openNewtab(ipmId) {
    return __awaiter(this, void 0, void 0, function* () {
        utilities_background/* debug */.fF('[new-tab]:openNewtab');
        const behavior = (0,background/* getBehavior */.J)(ipmId);
        if (!isNewTabBehavior(behavior)) {
            utilities_background/* debug */.fF('[new-tab]: No command behavior');
            (0,background/* dismissCommand */._E)(ipmId);
            return;
        }
        const targetUrl = (0,background/* createSafeOriginUrl */.qX)(behavior.target);
        if (!targetUrl) {
            (0,background/* dismissCommand */._E)(ipmId);
            return;
        }
        let tab = null;
        const onUpdatedHandler = openNewtabOnUpdated.bind(null, ipmId);
        openNewtabOnUpdatedHandlerByIPMids.set(ipmId, onUpdatedHandler);
        browser_polyfill.tabs.onUpdated.addListener(onUpdatedHandler);
        tab = yield browser_polyfill.tabs.create({ url: targetUrl }).catch((error) => {
            utilities_background/* error */.vU('[new-tab]: create tab error', error);
            return null;
        });
        if (tab !== null) {
            (0,background/* recordEvent */.Ny)(ipmId, NewTabEventType.created);
            (0,background/* dismissCommand */._E)(ipmId);
        }
    });
}
const openNotificationTab = (ipmId) => {
    const onCreatedHandler = onCreatedHandlerByIPMids.get(ipmId);
    onCreatedHandlerByIPMids.delete(ipmId);
    const onUpdatedHandler = onUpdatedHandlerByIPMids.get(ipmId);
    onUpdatedHandlerByIPMids.delete(ipmId);
    browser_polyfill.tabs.onCreated.removeListener(onCreatedHandler);
    browser_polyfill.tabs.onUpdated.removeListener(onUpdatedHandler);
    browser_polyfill.tabs.onRemoved.removeListener(onRemoved);
    tabIds.clear();
    openNewtab(ipmId);
};
const onCreated = (ipmId, tab) => {
    if (tab.url === 'about:newtab') {
        openNotificationTab(ipmId);
        return;
    }
    tabIds.add(tab.id);
};
const onRemoved = (tabId) => {
    tabIds.delete(tabId);
};
const onUpdated = (ipmId, tabId, changeInfo, tab) => {
    if (!tabIds.has(tabId) || changeInfo.status !== 'complete') {
        return;
    }
    tabIds.delete(tabId);
    if (tab.url && /^https?:/.test(tab.url)) {
        return;
    }
    openNotificationTab(ipmId);
};
function handleCommand(ipmId) {
    return __awaiter(this, void 0, void 0, function* () {
        utilities_background/* debug */.fF('[new-tab]:tab manager handleCommand', ipmId);
        yield check/* License.ready */.Cz.ready();
        if (check/* License.isActiveLicense */.Cz.isActiveLicense()) {
            (0,background/* dismissCommand */._E)(ipmId);
            return;
        }
        const { installType } = yield browser_polyfill.management.getSelf();
        if (installType === 'admin') {
            (0,background/* dismissCommand */._E)(ipmId);
            return;
        }
        yield settings/* settings.onload */.Xd.onload();
        if ((0,settings/* getSettings */.Gw)().suppress_update_page) {
            utilities_background/* debug */.fF('[new-tab]:suppress_update_page - true');
            (0,background/* dismissCommand */._E)(ipmId);
            return;
        }
        const onCreatedHandler = onCreated.bind(null, ipmId);
        onCreatedHandlerByIPMids.set(ipmId, onCreatedHandler);
        const onUpdatedHandler = onUpdated.bind(null, ipmId);
        onUpdatedHandlerByIPMids.set(ipmId, onUpdatedHandler);
        browser_polyfill.tabs.onCreated.addListener(onCreatedHandler);
        browser_polyfill.tabs.onRemoved.addListener(onRemoved);
        browser_polyfill.tabs.onUpdated.addListener(onUpdatedHandler);
    });
}
function start() {
    return __awaiter(this, void 0, void 0, function* () {
        utilities_background/* debug */.fF('[new-tab]:tab manager start');
        setNewTabCommandHandler(handleCommand);
    });
}
void start().catch(utilities_background/* error */.vU);

;// CONCATENATED MODULE: ./adblock-betafish/new-tab/background/index.ts



/***/ }),

/***/ 4245:
/***/ ((__unused_webpack_module, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// EXTERNAL MODULE: ./node_modules/webextension-polyfill/dist/browser-polyfill.js
var browser_polyfill = __webpack_require__(1935);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/port.js
var port = __webpack_require__(6960);
// EXTERNAL MODULE: ./adblock-betafish/alias/storage/tab-session.js
var tab_session = __webpack_require__(440);
;// CONCATENATED MODULE: ./adblock-betafish/i18n/background/locale.ts

function getLocaleInfo() {
    return {
        locale: browser_polyfill.i18n.getUILanguage(),
        readingDirection: browser_polyfill.i18n.getMessage("@@bidi_dir")
    };
}

;// CONCATENATED MODULE: ./adblock-betafish/i18n/background/index.ts



// EXTERNAL MODULE: ./adblock-betafish/ipm/background/index.ts + 6 modules
var background = __webpack_require__(9164);
// EXTERNAL MODULE: ./adblock-betafish/picreplacement/check.js
var check = __webpack_require__(2509);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/index.ts + 2 modules
var utilities_background = __webpack_require__(9555);
// EXTERNAL MODULE: ./adblock-betafish/prefs/background/settings.js
var settings = __webpack_require__(7330);
// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./adblock-betafish/alias/prefs.js
var prefs = __webpack_require__(4428);
;// CONCATENATED MODULE: ./adblock-betafish/polyfills/background/polyfill.ts
function isFilterMetadata(candidate) {
    return (candidate !== null &&
        typeof candidate === "object" &&
        "created" in candidate &&
        "origin" in candidate);
}

;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/middleware/ipm-onpage-dialog.types.ts
var Timing;
(function (Timing) {
    Timing["afterWebAllowlisting"] = "after_web_allowlisting";
    Timing["revisitWebAllowlisted"] = "revisit_web_allowlisted_site";
})(Timing || (Timing = {}));
var DialogEventType;
(function (DialogEventType) {
    DialogEventType["buttonClicked"] = "dialog_button_clicked";
    DialogEventType["closed"] = "dialog_closed";
    DialogEventType["ignored"] = "dialog_ignored";
    DialogEventType["injected"] = "dialog_injected";
})(DialogEventType || (DialogEventType = {}));

;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/middleware/ipm-onpage-dialog.ts



const paramDefinitionList = [
    {
        name: 'timing',
        validate: (param) => typeof param === 'undefined'
            || param === Timing.afterWebAllowlisting
            || param === Timing.revisitWebAllowlisted,
    },
    {
        name: 'display_duration',
        validate: (param) => typeof param === 'undefined'
            || (typeof param === 'number' && param >= 0 && param <= 20),
    },
    {
        name: 'sub_title',
        validate: background/* isNotEmpty */.UE,
    },
    {
        name: 'upper_body',
        validate: background/* isNotEmpty */.UE,
    },
    {
        name: 'button_label',
        validate: background/* isNotEmpty */.UE,
    },
    {
        name: 'button_target',
        validate: background/* isSafeUrl */.w6,
    },
];
function isDialogCommand(command) {
    const validationErrors = (0,background/* validateParams */.uU)(command, paramDefinitionList);
    if (validationErrors.length === 0) {
        return true;
    }
    utilities_background/* error */.vU('[onpage-dialog]: Invalid parameters received:', validationErrors.join(' '));
    return false;
}
function getBehavior(command) {
    if (!isDialogCommand(command)) {
        return null;
    }
    return {
        displayDuration: typeof command.display_duration === 'number'
            ? command.display_duration
            : 5,
        target: command.button_target,
        timing: command.timing,
    };
}
function getContent(command) {
    if (!isDialogCommand(command)) {
        return null;
    }
    return {
        body: command.lower_body
            ? [command.upper_body, command.lower_body]
            : [command.upper_body],
        button: command.button_label,
        title: command.sub_title,
    };
}
function isDialogBehavior(candidate) {
    return (candidate !== null
        && typeof candidate === 'object'
        && 'displayDuration' in candidate
        && 'target' in candidate
        && 'timing' in candidate);
}
function isDialogContent(candidate) {
    return (candidate !== null
        && typeof candidate === 'object'
        && 'body' in candidate
        && 'button' in candidate
        && 'title' in candidate);
}
function isTiming(candidate) {
    return (typeof candidate === 'string'
        && Object.values(Timing).includes(candidate));
}
function setDialogCommandHandler(handler) {
    (0,background/* setCommandActor */.yA)(background/* CommandName.createOnPageDialog */.G7.createOnPageDialog, {
        getBehavior,
        getContent,
        handleCommand: handler,
        isValidCommand: isDialogCommand,
    });
}

;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/middleware/index.ts



;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/timing.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};





const ewe = ewe_api;
const configsStorageKey = 'onpage_dialog_timing_configurations';
const knownConfigs = new Map();
function getAllowlistingTime(tabId) {
    return __awaiter(this, void 0, void 0, function* () {
        const allowlistingFilterTexts = yield ewe.filters.getAllowingFilters(tabId);
        if (allowlistingFilterTexts.length === 0) {
            return null;
        }
        for (const filterText of allowlistingFilterTexts) {
            const metadata = yield ewe.filters.getMetadata(filterText);
            if (!isFilterMetadata(metadata)) {
                continue;
            }
            if (metadata.origin !== 'web') {
                continue;
            }
            return metadata.created;
        }
        return null;
    });
}
function isTimingConfiguration(candidate) {
    return (candidate !== null
        && typeof candidate === 'object'
        && 'cooldownDuration' in candidate
        && 'maxDisplayCount' in candidate);
}
function isWithin(timestamp, minutes) {
    return timestamp < Date.now() - minutes * 60 * 1000;
}
function initializeConfigs() {
    const configs = prefs/* Prefs.get */.B.get(configsStorageKey);
    for (const [timing, config] of Object.entries(configs)) {
        if (!isTiming(timing) || !isTimingConfiguration(config)) {
            utilities_background/* warn */.ZK('[onpage-dialog] Unknown timing configuration', timing);
            continue;
        }
        knownConfigs.set(timing, config);
    }
    utilities_background/* debug */.fF('[onpage-dialog]: Known timing configurations', knownConfigs);
}
function shouldBeDismissed(timing, stats) {
    const config = knownConfigs.get(timing);
    if (!config) {
        utilities_background/* debug */.fF('[onpage-dialog]: Unknown timing');
        return true;
    }
    utilities_background/* debug */.fF('[onpage-dialog]: Display count', `${stats.displayCount}/${config.maxDisplayCount}`);
    return stats.displayCount >= config.maxDisplayCount;
}
function shouldBeShown(timing, tabId, stats) {
    return __awaiter(this, void 0, void 0, function* () {
        const config = knownConfigs.get(timing);
        if (!config) {
            utilities_background/* debug */.fF('[onpage-dialog]: Unknown timing');
            return false;
        }
        const allowlistingTime = yield getAllowlistingTime(tabId);
        if (allowlistingTime === null) {
            utilities_background/* debug */.fF('[onpage-dialog]: Not allowlisted');
            return false;
        }
        if (typeof config.maxAllowlistingDelay === 'number'
            && isWithin(allowlistingTime, config.maxAllowlistingDelay)) {
            utilities_background/* debug */.fF('[onpage-dialog]: Allowlisted too long ago');
            return false;
        }
        if (typeof config.minAllowlistingDelay === 'number'
            && !isWithin(allowlistingTime, config.minAllowlistingDelay)) {
            utilities_background/* debug */.fF('[onpage-dialog]: Allowlisted too recently');
            return false;
        }
        if (!isWithin(stats.lastDisplayTime, config.cooldownDuration * 60)) {
            utilities_background/* debug */.fF('[onpage-dialog]: Dialog shown too recently');
            return false;
        }
        if (shouldBeDismissed(timing, stats)) {
            utilities_background/* debug */.fF('[onpage-dialog]: No more dialogs to show for command');
            return false;
        }
        return true;
    });
}
function start() {
    return __awaiter(this, void 0, void 0, function* () {
        yield prefs/* Prefs.untilLoaded */.B.untilLoaded;
        initializeConfigs();
        prefs/* Prefs.on */.B.on(configsStorageKey, () => {
            initializeConfigs();
        });
    });
}

;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/stats.ts

const statsStorageKey = 'onpage_dialog_command_stats';
function clearStats(ipmId) {
    const statsStorage = prefs/* Prefs.get */.B.get(statsStorageKey);
    delete statsStorage[ipmId];
    prefs/* Prefs.set */.B.set(statsStorageKey, statsStorage);
}
function getStats(ipmId) {
    const statsStorage = prefs/* Prefs.get */.B.get(statsStorageKey);
    return statsStorage[ipmId] || null;
}
function isStats(candidate) {
    return (candidate !== null
        && typeof candidate === 'object'
        && 'displayCount' in candidate
        && 'lastDisplayTime' in candidate);
}
function setStats(ipmId, stats) {
    const storage = prefs/* Prefs.get */.B.get(statsStorageKey);
    storage[ipmId] = stats;
    prefs/* Prefs.set */.B.set(statsStorageKey, storage);
}

;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/tab-manager.ts
var tab_manager_awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};











const assignedIpmIds = new tab_session/* TabSessionStorage */.H('onpage-dialog:ipm');
const unassignedIpmIds = new Set();
function sendMessage(tabId, message) {
    return browser_polyfill.tabs.sendMessage(tabId, message, { frameId: 0 });
}
function dismissDialogCommand(ipmId) {
    utilities_background/* debug */.fF('[onpage-dialog]: Dismiss command');
    unassignedIpmIds.delete(ipmId);
    (0,background/* dismissCommand */._E)(ipmId);
}
function dismissDialog(tabId, ipmId) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        utilities_background/* debug */.fF('[onpage-dialog]: Dismiss dialog');
        try {
            yield sendMessage(tabId, { type: 'onpage-dialog.hide' });
            yield assignedIpmIds.delete(tabId);
        }
        catch (ex) {
        }
        const behavior = (0,background/* getBehavior */.J)(ipmId);
        if (!isDialogBehavior(behavior)) {
            return;
        }
        const stats = getStats(ipmId);
        if (!isStats(stats)) {
            return;
        }
        if (!shouldBeDismissed(behavior.timing, stats)) {
            utilities_background/* debug */.fF('[onpage-dialog]: Keep command active');
            return;
        }
        dismissDialogCommand(ipmId);
        clearStats(ipmId);
    });
}
function handleCommand(ipmId) {
    setStats(ipmId, {
        displayCount: 0,
        lastDisplayTime: 0,
    });
    unassignedIpmIds.add(ipmId);
}
function handleCloseMessage(message, sender) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        const ipmId = yield assignedIpmIds.get(sender.page.id);
        if (typeof ipmId !== 'string') {
            return;
        }
        void dismissDialog(sender.page.id, ipmId);
        (0,background/* recordEvent */.Ny)(ipmId, DialogEventType.closed);
    });
}
function handleContinueMessage(message, sender) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        const ipmId = yield assignedIpmIds.get(sender.page.id);
        if (!ipmId) {
            return;
        }
        const behavior = (0,background/* getBehavior */.J)(ipmId);
        if (!behavior) {
            return;
        }
        const targetUrl = (0,background/* createSafeOriginUrl */.qX)(behavior.target);
        if (!targetUrl) {
            return;
        }
        void browser_polyfill.tabs.create({ url: targetUrl });
        void dismissDialog(sender.page.id, ipmId);
        (0,background/* recordEvent */.Ny)(ipmId, DialogEventType.buttonClicked);
    });
}
function handleGetMessage(message, sender) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        const ipmId = yield assignedIpmIds.get(sender.page.id);
        if (!ipmId) {
            return null;
        }
        const content = (0,background/* getContent */.L5)(ipmId);
        if (!isDialogContent(content)) {
            return null;
        }
        return {
            content,
            localeInfo: getLocaleInfo(),
        };
    });
}
function handlePingMessage(message, sender) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        const ipmId = yield assignedIpmIds.get(sender.page.id);
        if (!ipmId) {
            return;
        }
        const behavior = (0,background/* getBehavior */.J)(ipmId);
        if (!behavior || !isDialogBehavior(behavior)) {
            return;
        }
        if (behavior.displayDuration === 0
            || message.displayDuration < behavior.displayDuration) {
            return;
        }
        void dismissDialog(sender.page.id, ipmId);
        (0,background/* recordEvent */.Ny)(ipmId, DialogEventType.ignored);
    });
}
function handleTabRemovedEvent(data) {
    const { tabId, value: ipmId } = data;
    if (typeof ipmId !== 'string') {
        return;
    }
    void dismissDialog(tabId, ipmId);
    (0,background/* recordEvent */.Ny)(ipmId, DialogEventType.ignored);
}
function showDialog(tabId, ipmId, stats) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        utilities_background/* debug */.fF('[onpage-dialog]: Show dialog');
        yield assignedIpmIds.set(tabId, ipmId);
        setStats(ipmId, {
            displayCount: stats.displayCount + 1,
            lastDisplayTime: Date.now(),
        });
        if (browser_polyfill.scripting) {
            yield browser_polyfill.scripting.insertCSS({
                files: ['adblock-onpage-dialog-user.css'],
                origin: 'USER',
                target: { tabId },
            });
            yield browser_polyfill.scripting.executeScript({
                files: ['onpage-dialog.postload.js'],
                target: { tabId },
            });
        }
        else {
            yield browser_polyfill.tabs.insertCSS(tabId, {
                file: 'adblock-onpage-dialog-user.css',
                allFrames: false,
                cssOrigin: 'user',
                runAt: 'document_start',
            }).catch((error) => {
                utilities_background/* error */.vU('Injection of adblock-onpage-dialog-user.css failed');
                utilities_background/* error */.vU(error);
            });
            yield browser_polyfill.tabs.executeScript(tabId, {
                file: 'onpage-dialog.postload.js',
                allFrames: false,
            }).catch((error) => {
                utilities_background/* error */.vU('Injection of onpage-dialog-cs.js failed');
                utilities_background/* error */.vU(error);
            });
        }
        (0,background/* recordEvent */.Ny)(ipmId, DialogEventType.injected);
    });
}
function handleTabsUpdatedEvent(tabId, changeInfo, tab) {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        if (unassignedIpmIds.size === 0) {
            utilities_background/* debug */.fF('[onpage-dialog]: No command');
            return;
        }
        if (changeInfo.status !== 'complete'
            || tab.incognito
            || !tab.url
            || !/^https?:/.test(tab.url)) {
            return;
        }
        for (const ipmId of unassignedIpmIds) {
            if (check/* License.isActiveLicense */.Cz.isActiveLicense()) {
                utilities_background/* debug */.fF('[tm]: User has Premium');
                dismissDialogCommand(ipmId);
                continue;
            }
            if ((0,settings/* getSettings */.Gw)().show_survey === false) {
                utilities_background/* debug */.fF('[onpage-dialog]:show_survey - disabled');
                dismissDialogCommand(ipmId);
                continue;
            }
            if ((0,settings/* getSettings */.Gw)().suppress_surveys) {
                utilities_background/* debug */.fF('[onpage-dialog]:suppress_surveys - enabled');
                dismissDialogCommand(ipmId);
                continue;
            }
            if ((0,settings/* getSettings */.Gw)().onpageMessages === false) {
                utilities_background/* debug */.fF('[onpage-dialog]:onpageMessages - disabled');
                dismissDialogCommand(ipmId);
                continue;
            }
            const behavior = (0,background/* getBehavior */.J)(ipmId);
            if (!isDialogBehavior(behavior)) {
                utilities_background/* debug */.fF('[onpage-dialog]: No command behavior');
                dismissDialogCommand(ipmId);
                continue;
            }
            const stats = getStats(ipmId);
            if (!isStats(stats)) {
                utilities_background/* debug */.fF('[onpage-dialog]: No command stats');
                dismissDialogCommand(ipmId);
                continue;
            }
            if (!(yield shouldBeShown(behavior.timing, tabId, stats))) {
                utilities_background/* debug */.fF("[onpage-dialog]: Don't show");
                continue;
            }
            yield showDialog(tabId, ipmId, stats);
        }
    });
}
function tab_manager_start() {
    return tab_manager_awaiter(this, void 0, void 0, function* () {
        yield start();
        port/* port.on */.N.on('onpage-dialog.close', handleCloseMessage);
        port/* port.on */.N.on('onpage-dialog.continue', handleContinueMessage);
        port/* port.on */.N.on('onpage-dialog.get', handleGetMessage);
        port/* port.on */.N.on('onpage-dialog.ping', handlePingMessage);
        ext.addTrustedMessageTypes(null, [
            'onpage-dialog.continue',
            'onpage-dialog.close',
            'onpage-dialog.get',
            'onpage-dialog.ping',
        ]);
        assignedIpmIds.on('tab-removed', handleTabRemovedEvent);
        browser_polyfill.tabs.onUpdated.addListener(handleTabsUpdatedEvent);
        setDialogCommandHandler(handleCommand);
    });
}
void tab_manager_start().catch(utilities_background/* error */.vU);

;// CONCATENATED MODULE: ./adblock-betafish/onpage-dialog/background/index.ts



/***/ }),

/***/ 9555:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "lE": () => (/* reexport */ bg_functions/* chromeStorageDeleteHelper */.lE),
  "nX": () => (/* reexport */ bg_functions/* chromeStorageGetHelper */.nX),
  "rJ": () => (/* reexport */ bg_functions/* chromeStorageSetHelper */.rJ),
  "fF": () => (/* reexport */ logger/* debug */.fF),
  "pN": () => (/* reexport */ bg_functions/* determineUserLanguage */.pN),
  "vU": () => (/* reexport */ logger/* error */.vU),
  "K1": () => (/* reexport */ getUserAgentInfo),
  "cM": () => (/* reexport */ bg_functions/* log */.cM),
  "eV": () => (/* reexport */ bg_functions/* storageSet */.eV),
  "ZK": () => (/* reexport */ logger/* warn */.ZK)
});

// UNUSED EXPORTS: FlavorType, LogLevel, createFilterMetaData, extend, info, isEmptyObject, logging, migrateData, parseUri, reloadOptionsPageTabs, sessionStorageGet, sessionStorageSet, storageGet

// EXTERNAL MODULE: ./adblock-betafish/utilities/background/logger.ts
var logger = __webpack_require__(8095);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/logger.types.ts
var logger_types = __webpack_require__(8736);
// EXTERNAL MODULE: ./adblock-betafish/utilities/background/bg-functions.js
var bg_functions = __webpack_require__(7337);
;// CONCATENATED MODULE: ./adblock-betafish/utilities/background/user-agent-info.types.ts
var FlavorType;
(function (FlavorType) {
    FlavorType["chrome"] = "E";
    FlavorType["edge"] = "CM";
    FlavorType["firefox"] = "F";
})(FlavorType || (FlavorType = {}));

;// CONCATENATED MODULE: ./adblock-betafish/utilities/background/user-agent-info.ts

let info;
function parseUserAgent() {
    let flavor = FlavorType.chrome;
    let match = navigator.userAgent.match(/(CrOS \w+|Windows NT|Mac OS X|Linux) ([\d._]+)?/);
    const os = (match || [])[1] || 'Unknown';
    const osVersion = (match || [])[2] || 'Unknown';
    match = navigator.userAgent.match(/(?:Chrome|Version)\/([\d.]+)/);
    const edgeMatch = navigator.userAgent.match(/(?:Edg|Version)\/([\d.]+)/);
    const firefoxMatch = navigator.userAgent.match(/(?:Firefox)\/([\d.]+)/);
    if (edgeMatch) {
        match = edgeMatch;
        flavor = FlavorType.edge;
    }
    else if (firefoxMatch) {
        match = firefoxMatch;
        flavor = FlavorType.firefox;
    }
    const browserVersion = (match || [])[1] || 'Unknown';
    return {
        flavor, os, osVersion, browserVersion,
    };
}
function getUserAgentInfo() {
    if (!info) {
        info = parseUserAgent();
    }
    return info;
}

;// CONCATENATED MODULE: ./adblock-betafish/utilities/background/index.ts







/***/ }),

/***/ 8095:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "ZK": () => (/* binding */ warn),
/* harmony export */   "fF": () => (/* binding */ debug),
/* harmony export */   "vU": () => (/* binding */ error)
/* harmony export */ });
/* unused harmony export info */
/* harmony import */ var _alias_prefs__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(4428);
/* harmony import */ var _logger_types__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(8736);


function log(level, fn, ...data) {
    const minLevel = _alias_prefs__WEBPACK_IMPORTED_MODULE_0__/* .Prefs.get */ .B.get("logger_log_level");
    if (level < minLevel) {
        return;
    }
    fn(...data);
}
const debug = log.bind(null, _logger_types__WEBPACK_IMPORTED_MODULE_1__/* .LogLevel.debug */ .i.debug, console.debug);
const error = log.bind(null, _logger_types__WEBPACK_IMPORTED_MODULE_1__/* .LogLevel.error */ .i.error, console.error);
const info = log.bind(null, _logger_types__WEBPACK_IMPORTED_MODULE_1__/* .LogLevel.info */ .i.info, console.info);
const warn = log.bind(null, _logger_types__WEBPACK_IMPORTED_MODULE_1__/* .LogLevel.warn */ .i.warn, console.warn);


/***/ }),

/***/ 8736:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "i": () => (/* binding */ LogLevel)
/* harmony export */ });
var LogLevel;
(function (LogLevel) {
    LogLevel[LogLevel["debug"] = 1] = "debug";
    LogLevel[LogLevel["info"] = 2] = "info";
    LogLevel[LogLevel["warn"] = 3] = "warn";
    LogLevel[LogLevel["error"] = 4] = "error";
})(LogLevel || (LogLevel = {}));


/***/ }),

/***/ 7650:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "MU": () => (/* binding */ setListener),
  "U3": () => (/* binding */ setSchedule)
});

// UNUSED EXPORTS: removeListener, removeSchedule

// EXTERNAL MODULE: ./vendor/adblockplusui/src/core/scheduled-event-emitter/background/scheduled-event-emitter.types.ts
var scheduled_event_emitter_types = __webpack_require__(1784);
;// CONCATENATED MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/storage/session.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * In-memory storage for use outside of service worker context.
 * @type {Map<string,any>}
 */
const memoryStorage = new Map();

/**
 * Indicates whether we need to store in-memory data using a dedicated browser
 * API. When we're running in the context of a service worker, we can no longer
 * rely on in-memory storage.
 * @type {boolean}
 */
const useMemoryStorage = !("session" in browser.storage);

/**
 * Session storage for storing in-memory data in a way that's safe to use in
 * a service worker context.
 */
class SessionStorage
{
  /**
   * Initializes session storage.
   * @param {string} namespace
   */
  constructor(namespace)
  {
    this._namespace = namespace;
  }

  /**
   * Generates unique storage key for storing values globally for given key.
   * @param {string} key
   * @return {string}
   */
  _getGlobalKey(key)
  {
    return `session:${this._namespace}:${key}`;
  }

  /**
   * Deletes session storage entry for given key.
   * @param {string} key
   * @return {Promise}
   */
  async delete(key)
  {
    const globalKey = this._getGlobalKey(key);
    if (useMemoryStorage)
      return memoryStorage.delete(globalKey);

    return browser.storage.session.remove(globalKey);
  }

  /**
   * Retrieves session storage entry for given key.
   * @param {string} key
   * @return {Promise<any>}
   */
  async get(key)
  {
    const globalKey = this._getGlobalKey(key);
    if (useMemoryStorage)
      return memoryStorage.get(globalKey);

    const storage = await browser.storage.session.get(globalKey);
    return storage[globalKey];
  }

  /**
   * Sets session storage entry for given key.
   * @param {string} key
   * @param {any} value
   * @return {Promise}
   */
  async set(key, value)
  {
    const globalKey = this._getGlobalKey(key);
    if (useMemoryStorage)
    {
      memoryStorage.set(globalKey, value);
      return;
    }

    browser.storage.session.set({[globalKey]: value});
  }
}

;// CONCATENATED MODULE: ./vendor/adblockplusui/src/core/scheduled-event-emitter/background/scheduled-event-emitter.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};


const global = typeof window !== "undefined" ? window : self;
const storageKey = "schedules";
const storage = new SessionStorage("ScheduledEventEmitter.storage");
const initialization = initialize();
let schedules = Object.create(null);
const listeners = new Map();
function setListener(name, listener) {
    return __awaiter(this, void 0, void 0, function* () {
        yield initialization;
        if (listeners.has(name)) {
            warn(`Overwriting already registered listener for event "${name}".`);
        }
        listeners.set(name, listener);
        activateSchedules();
    });
}
function setSchedule(name, time, scheduleType = scheduled_event_emitter_types/* ScheduleType.once */.I.once) {
    return __awaiter(this, void 0, void 0, function* () {
        yield initialization;
        if (name in schedules) {
            warn(`Overwriting already registered schedule for name "${name}".`);
        }
        schedules[name] = {
            period: time,
            next: time + Date.now(),
            runOnce: scheduleType === scheduled_event_emitter_types/* ScheduleType.once */.I.once,
            count: 0
        };
        yield persistSchedules();
        activateSchedules();
    });
}
function removeSchedule(name) {
    return __awaiter(this, void 0, void 0, function* () {
        yield initialization;
        const schedule = schedules[name];
        if (!schedule) {
            return;
        }
        if (schedule.runOnce) {
            global.clearTimeout(schedule.activationId);
        }
        else {
            global.clearInterval(schedule.activationId);
        }
        delete schedules[name];
        yield persistSchedules();
    });
}
function removeListener(name) {
    return __awaiter(this, void 0, void 0, function* () {
        yield initialization;
        listeners.delete(name);
    });
}
function initialize() {
    return __awaiter(this, void 0, void 0, function* () {
        yield reviveSchedules();
    });
}
function persistSchedules() {
    return __awaiter(this, void 0, void 0, function* () {
        yield storage.set(storageKey, schedules);
    });
}
function reviveSchedules() {
    return __awaiter(this, void 0, void 0, function* () {
        const storedSchedules = yield storage.get(storageKey);
        if (Object.prototype.toString.call(storedSchedules) !== "[object Object]") {
            warn("Could not restore stored schedules.");
            return;
        }
        schedules = storedSchedules;
        Object.keys(schedules).forEach((name) => {
            delete schedules[name].activationId;
        });
    });
}
function activateSchedules() {
    const now = Date.now();
    Object.entries(schedules).forEach(([name, schedule]) => {
        const delta = schedule.next - now;
        const isDue = delta <= 0;
        const activationKey = "activationId";
        if (activationKey in schedule) {
            return;
        }
        if (!schedule.runOnce) {
            schedule.activationId = global.setInterval(() => emitEvent(name), schedule.period);
            return;
        }
        if (!isDue) {
            schedule.activationId = global.setTimeout(() => emitEvent(name), delta);
            return;
        }
        emitEvent(name);
    });
}
function emitEvent(name) {
    return __awaiter(this, void 0, void 0, function* () {
        const schedule = schedules[name];
        const listener = listeners.get(name);
        if (!schedule || !listener) {
            return;
        }
        schedule.count += 1;
        const now = Date.now();
        const callCount = schedule.count;
        listener({ callCount });
        if (schedule.runOnce) {
            yield removeSchedule(name);
        }
        else {
            schedule.next = now + schedule.period;
            yield persistSchedules();
        }
    });
}
function warn(message) {
    console.warn(`[ScheduledEventEmitter]: ${message}`);
}


/***/ }),

/***/ 1784:
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "I": () => (/* binding */ ScheduleType)
/* harmony export */ });
var ScheduleType;
(function (ScheduleType) {
    ScheduleType["once"] = "once";
    ScheduleType["interval"] = "interval";
})(ScheduleType || (ScheduleType = {}));


/***/ }),

/***/ 209:
/***/ ((module) => {

(function webpackUniversalModuleDefinition(root, factory) {
	if(true)
		module.exports = factory();
	else {}
})(self, function() {
return /******/ (() => { // webpackBootstrap
/******/ 	var __webpack_modules__ = ({

/***/ "./node_modules/adblockpluscore/data/subscriptions.json":
/*!**************************************************************!*\
  !*** ./node_modules/adblockpluscore/data/subscriptions.json ***!
  \**************************************************************/
/***/ ((module) => {

"use strict";
module.exports = JSON.parse('[{"id":"B7D76369-DD19-4602-80E8-2E32DDB490AC","type":"ads","languages":["id","ms"],"title":"ABPindo+EasyList","homepage":"http://abpindo.blogspot.com/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","A4A32212-E6BD-45F6-AD0F-E0FD18E8537B"],"url":"https://easylist-downloads.adblockplus.org/v3/full/abpindo+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/abpindo+easylist.txt"},{"id":"1C571EC7-6E52-47CC-B04A-4B3008D0AEBE","type":"ads","languages":["vi"],"title":"ABPVN List+EasyList","homepage":"http://abpvn.com/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","03648752-31EE-4FD0-85C1-20B07C5551C3"],"url":"https://easylist-downloads.adblockplus.org/v3/full/abpvn+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/abpvn+easylist.txt"},{"id":"E22C3B40-DC90-49D7-8BF5-E60904AB159A","type":"ads","languages":["bg"],"title":"Bulgarian list+EasyList","homepage":"https://stanev.org/abp/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","1638B159-F64A-4307-84E7-16AB08ED409E"],"url":"https://easylist-downloads.adblockplus.org/v3/full/bulgarian_list+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/bulgarian_list+easylist.txt"},{"id":"96932CD9-6DDF-4D97-B92F-FDF747B6FAA2","type":"ads","languages":["no","nb","nn","da","is","fo","kl","sv","fi"],"title":"Dandelion Sprout\'s Nordic Filters+EasyList","homepage":"https://github.com/DandelionSprout/adfilt","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","6D489E8D-E61C-444C-BBC5-44741773ADC2"],"url":"https://easylist-downloads.adblockplus.org/v3/full/dandelion_sprouts_nordic_filters+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/dandelion_sprouts_nordic_filters+easylist.txt"},{"id":"8C13E995-8F06-4927-BEA7-6C845FB7EEBF","type":"ads","languages":["en"],"title":"EasyList","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylist.txt"},{"id":"9BD3EA2F-889D-4CC3-B680-CF484F2BD1B9","type":"ads","languages":["zh"],"title":"EasyList China+EasyList","homepage":"https://github.com/easylist/easylistchina/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","1D7F590C-B752-4BA0-9473-6A26DE1326B1"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistchina+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistchina+easylist.txt"},{"id":"4B6CE485-30AB-4213-AD17-504B3F2D2825","type":"ads","languages":["cs","sk"],"title":"EasyList Czech and Slovak+EasyList","homepage":"https://adblock.sk/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","2D8C4D88-34A0-4259-9098-30D28BA674BC"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistczechslovak+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistczechslovak+easylist.txt"},{"id":"A4B88FB6-E5E5-417F-8A49-20B8244995FD","type":"ads","languages":["nl"],"title":"EasyList Dutch+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","CB94E27D-6CD1-4DB9-83D9-6B7F1A3555F6"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistdutch+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistdutch+easylist.txt"},{"id":"0CD3D105-D3B3-4652-8489-94163DE9A08F","type":"ads","languages":["de"],"title":"EasyList Germany+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","4337FB2B-A95C-44D5-B78D-11AD40F7711B"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistgermany+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistgermany+easylist.txt"},{"id":"07549D8B-F06F-4D9D-A567-929AA59E9D1D","type":"ads","languages":["he"],"title":"EasyList Hebrew+EasyList","homepage":"https://github.com/easylist/EasyListHebrew","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","AE0D9320-665E-407D-B692-1A85AE481F34"],"url":"https://easylist-downloads.adblockplus.org/v3/full/israellist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/israellist+easylist.txt"},{"id":"BBC07C05-66F1-42EC-BD4D-7AD495FAC84B","type":"ads","languages":["it"],"title":"EasyList Italy+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","2F0A4F0D-DF16-40D0-B0E0-5EB6791EC119"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistitaly+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistitaly+easylist.txt"},{"id":"CBE50FA2-DE3F-480C-B1D7-04289391C033","type":"ads","languages":["lt"],"title":"EasyList Lithuania+EasyList","homepage":"https://github.com/EasyList-Lithuania/easylist_lithuania","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","E89B3C08-2DED-40EA-8EE1-339B90D7B451"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistlithuania+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistlithuania+easylist.txt"},{"id":"3D2C09D0-DF1C-4C8E-9947-A23DCEAF8F8B","type":"ads","languages":["pl"],"title":"EasyList Polish+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","9F743FCD-801B-41D0-830F-5A4EA995216E"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistpolish+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistpolish+easylist.txt"},{"id":"14DF7BE6-9675-4E07-987A-D8A1000F9FEF","type":"ads","languages":["pt"],"title":"EasyList Portuguese+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","A41441EE-BF7C-4A48-9A43-42CCEA2B2A1D"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistportuguese+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistportuguese+easylist.txt"},{"id":"C3D13A19-3E8D-41F5-AD64-0F3B36DDE128","type":"ads","languages":["es"],"title":"EasyList Spanish+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","C8C1AA76-15B4-4CA3-8A9C-AD38D6AFCAEC"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easylistspanish+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easylistspanish+easylist.txt"},{"id":"25A31255-AB36-48A4-9086-06192DE71119","type":"ads","languages":["bn","gu","hi","pa","as","mr","ml","te","kn","or","ne","si"],"title":"IndianList+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","9FAA2906-CD5C-4520-BDC4-4E098B7EA228"],"url":"https://easylist-downloads.adblockplus.org/v3/full/indianlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/indianlist+easylist.txt"},{"id":"2708BCB7-2E45-41BC-B517-1730CF532F89","type":"ads","languages":["ko"],"title":"KoreanList+EasyList","homepage":"https://easylist.to/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","BCE2062F-0D99-4861-A1F7-E3DFEA6DAB69"],"url":"https://easylist-downloads.adblockplus.org/v3/full/koreanlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/koreanlist+easylist.txt"},{"id":"950C88EA-2DD1-42E3-B2A2-2DF2ED15563A","type":"ads","languages":["lv"],"title":"Latvian List+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=99-latvian-list","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","51893C6C-F39E-43C5-A2EF-9545E388A2CE"],"url":"https://easylist-downloads.adblockplus.org/v3/full/latvianlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/latvianlist+easylist.txt"},{"id":"684A25C6-6B5D-458A-8A2B-BAC0A12B0B15","type":"ads","languages":["ar"],"title":"Liste AR+Liste FR+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=98","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","8D421590-1A68-4B68-BE50-04E17C09460E","3D60E303-1141-4775-B800-834177922876"],"url":"https://easylist-downloads.adblockplus.org/v3/full/liste_ar+liste_fr+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/liste_ar+liste_fr+easylist.txt"},{"id":"2CEA1481-C29C-44F1-A084-A2A019533797","type":"ads","languages":["fr"],"title":"Liste FR+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=98","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","8D421590-1A68-4B68-BE50-04E17C09460E"],"url":"https://easylist-downloads.adblockplus.org/v3/full/liste_fr+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/liste_fr+easylist.txt"},{"id":"EEEF75EC-B2B4-49F4-BC49-17B08266F334","type":"ads","languages":["ro"],"title":"ROList+EasyList","homepage":"https://zoso.ro/rolist/","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","99166908-5FDA-4F9E-8C4C-70BB4DEEFC08"],"url":"https://easylist-downloads.adblockplus.org/v3/full/rolist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/rolist+easylist.txt"},{"id":"1B5F78CA-8B30-4BDF-B0A3-451CB2202984","type":"ads","languages":["ru","uk"],"title":"RuAdList+EasyList","homepage":"https://forums.lanik.us/viewforum.php?f=102","includes":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF","879ECB9D-8935-4506-939E-5BBB7DD09402"],"url":"https://easylist-downloads.adblockplus.org/v3/full/ruadlist+easylist.txt","mv2_url":"https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt"},{"id":"0798B6A2-94A4-4ADF-89ED-BEC112FC4C7F","type":"allowing","title":"Allow nonintrusive advertising","homepage":"https://acceptableads.com/","url":"https://easylist-downloads.adblockplus.org/v3/full/exceptionrules.txt","mv2_url":"https://easylist-downloads.adblockplus.org/exceptionrules.txt"},{"id":"D4028CDD-3D39-4624-ACC7-8140F4EC3238","type":"circumvention","title":"ABP filters","homepage":"https://github.com/abp-filters/abp-filters-anti-cv","url":"https://easylist-downloads.adblockplus.org/v3/full/abp-filters-anti-cv.txt","mv2_url":"https://easylist-downloads.adblockplus.org/abp-filters-anti-cv.txt"},{"id":"2090F374-29D9-4202-B2CE-139D6492D95E","type":"cookies","title":"I don\'t care about cookies","homepage":"https://www.i-dont-care-about-cookies.eu/","url":"https://easylist-downloads.adblockplus.org/v3/full/i_dont_care_about_cookies.txt","mv2_url":"https://easylist-downloads.adblockplus.org/i_dont_care_about_cookies.txt"},{"id":"5BD2BB73-459D-4A74-AF9D-A10157268350","type":"notifications","title":"Fanboy\'s Notifications Blocking List","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/fanboy-notifications.txt","mv2_url":"https://easylist-downloads.adblockplus.org/fanboy-notifications.txt"},{"id":"D72B6F06-52B2-4FED-96A2-1BF59CDD7AEC","type":"privacy","title":"EasyPrivacy","homepage":"https://easylist.to/","requires":["8C13E995-8F06-4927-BEA7-6C845FB7EEBF"],"url":"https://easylist-downloads.adblockplus.org/v3/full/easyprivacy.txt","mv2_url":"https://easylist-downloads.adblockplus.org/easyprivacy.txt"},{"id":"0A679439-445F-4DE7-84B9-88341F6DA520","type":"social","title":"Fanboy\'s Social Blocking List","homepage":"https://easylist.to/","url":"https://easylist-downloads.adblockplus.org/v3/full/fanboy-social.txt","mv2_url":"https://easylist-downloads.adblockplus.org/fanboy-social.txt"}]');

/***/ }),

/***/ "./node_modules/adblockpluscore/data/publicSuffixList.js":
/*!***************************************************************!*\
  !*** ./node_modules/adblockpluscore/data/publicSuffixList.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, exports) => {

exports.publicSuffixes = {
  "0.bg": 1,
  "001www.com": 1,
  "0e.vc": 1,
  "0emm.com": 2,
  "1.azurestaticapps.net": 1,
  "1.bg": 1,
  "123hjemmeside.dk": 1,
  "123hjemmeside.no": 1,
  "123homepage.it": 1,
  "123kotisivu.fi": 1,
  "123minsida.se": 1,
  "123miweb.es": 1,
  "123paginaweb.pt": 1,
  "123sait.ru": 1,
  "123siteweb.fr": 1,
  "123webseite.at": 1,
  "123webseite.de": 1,
  "123website.be": 1,
  "123website.ch": 1,
  "123website.lu": 1,
  "123website.nl": 1,
  "12hp.at": 1,
  "12hp.ch": 1,
  "12hp.de": 1,
  "1337.pictures": 1,
  "16-b.it": 1,
  "1kapp.com": 1,
  "2.azurestaticapps.net": 1,
  "2.bg": 1,
  "2000.hu": 1,
  "2038.io": 1,
  "2ix.at": 1,
  "2ix.ch": 1,
  "2ix.de": 1,
  "3.bg": 1,
  "32-b.it": 1,
  "3utilities.com": 1,
  "4.bg": 1,
  "4lima.at": 1,
  "4lima.ch": 1,
  "4lima.de": 1,
  "4u.com": 1,
  "5.bg": 1,
  "5g.in": 1,
  "6.bg": 1,
  "611.to": 1,
  "64-b.it": 1,
  "6g.in": 1,
  "7.bg": 1,
  "8.bg": 1,
  "9.bg": 1,
  "9guacu.br": 1,
  "a.bg": 1,
  "a.prod.fastly.net": 1,
  "a.run.app": 1,
  "a.se": 1,
  "a.ssl.fastly.net": 1,
  "aa.no": 1,
  "aaa.pro": 1,
  "aarborte.no": 1,
  "ab.ca": 1,
  "abashiri.hokkaido.jp": 1,
  "abc.br": 1,
  "abeno.osaka.jp": 1,
  "abiko.chiba.jp": 1,
  "abira.hokkaido.jp": 1,
  "abkhazia.su": 1,
  "abo.pa": 1,
  "abr.it": 1,
  "abruzzo.it": 1,
  "abu.yamaguchi.jp": 1,
  "ac.ae": 1,
  "ac.at": 1,
  "ac.be": 1,
  "ac.ci": 1,
  "ac.cn": 1,
  "ac.cr": 1,
  "ac.cy": 1,
  "ac.fj": 1,
  "ac.gn": 1,
  "ac.gov.br": 1,
  "ac.id": 1,
  "ac.il": 1,
  "ac.im": 1,
  "ac.in": 1,
  "ac.ir": 1,
  "ac.jp": 1,
  "ac.ke": 1,
  "ac.kr": 1,
  "ac.leg.br": 1,
  "ac.lk": 1,
  "ac.ls": 1,
  "ac.ma": 1,
  "ac.me": 1,
  "ac.mu": 1,
  "ac.mw": 1,
  "ac.mz": 1,
  "ac.ni": 1,
  "ac.nz": 1,
  "ac.pa": 1,
  "ac.pr": 1,
  "ac.rs": 1,
  "ac.ru": 1,
  "ac.rw": 1,
  "ac.se": 1,
  "ac.sz": 1,
  "ac.th": 1,
  "ac.tj": 1,
  "ac.tz": 1,
  "ac.ug": 1,
  "ac.uk": 1,
  "ac.vn": 1,
  "ac.za": 1,
  "ac.zm": 1,
  "ac.zw": 1,
  "aca.pro": 1,
  "academia.bo": 1,
  "academy.museum": 1,
  "accesscam.org": 1,
  "accident-investigation.aero": 1,
  "accident-prevention.aero": 1,
  "acct.pro": 1,
  "achi.nagano.jp": 1,
  "act.au": 1,
  "act.edu.au": 1,
  "activetrail.biz": 1,
  "ad.jp": 1,
  "adachi.tokyo.jp": 1,
  "adimo.co.uk": 1,
  "adm.br": 1,
  "adobeaemcloud.com": 1,
  "adobeaemcloud.net": 1,
  "adult.ht": 1,
  "adv.br": 1,
  "adv.mz": 1,
  "advisor.ws": 2,
  "adygeya.ru": 1,
  "adygeya.su": 1,
  "ae.org": 1,
  "aejrie.no": 1,
  "aero.mv": 1,
  "aero.tt": 1,
  "aerobatic.aero": 1,
  "aeroclub.aero": 1,
  "aerodrome.aero": 1,
  "aeroport.fr": 1,
  "affinitylottery.org.uk": 1,
  "afjord.no": 1,
  "africa.com": 1,
  "ag.it": 1,
  "aga.niigata.jp": 1,
  "agano.niigata.jp": 1,
  "agdenes.no": 1,
  "agematsu.nagano.jp": 1,
  "agents.aero": 1,
  "agr.br": 1,
  "agrar.hu": 1,
  "agric.za": 1,
  "agriculture.museum": 1,
  "agrigento.it": 1,
  "agro.bo": 1,
  "agro.pl": 1,
  "aguni.okinawa.jp": 1,
  "ah.cn": 1,
  "ah.no": 1,
  "ai.in": 1,
  "aibetsu.hokkaido.jp": 1,
  "aichi.jp": 1,
  "aid.pl": 1,
  "aikawa.kanagawa.jp": 1,
  "ainan.ehime.jp": 1,
  "aioi.hyogo.jp": 1,
  "aip.ee": 1,
  "air-surveillance.aero": 1,
  "air-traffic-control.aero": 1,
  "air.museum": 1,
  "aircraft.aero": 1,
  "airguard.museum": 1,
  "airkitapps-au.com": 1,
  "airkitapps.com": 1,
  "airkitapps.eu": 1,
  "airline.aero": 1,
  "airport.aero": 1,
  "airtraffic.aero": 1,
  "aisai.aichi.jp": 1,
  "aisho.shiga.jp": 1,
  "aivencloud.com": 1,
  "aizubange.fukushima.jp": 1,
  "aizumi.tokushima.jp": 1,
  "aizumisato.fukushima.jp": 1,
  "aizuwakamatsu.fukushima.jp": 1,
  "aju.br": 1,
  "ak.us": 1,
  "akabira.hokkaido.jp": 1,
  "akagi.shimane.jp": 1,
  "akaiwa.okayama.jp": 1,
  "akashi.hyogo.jp": 1,
  "aki.kochi.jp": 1,
  "akiruno.tokyo.jp": 1,
  "akishima.tokyo.jp": 1,
  "akita.akita.jp": 1,
  "akita.jp": 1,
  "akkeshi.hokkaido.jp": 1,
  "aknoluokta.no": 1,
  "ako.hyogo.jp": 1,
  "akrehamn.no": 1,
  "aktyubinsk.su": 1,
  "akune.kagoshima.jp": 1,
  "al.eu.org": 1,
  "al.gov.br": 1,
  "al.it": 1,
  "al.leg.br": 1,
  "al.no": 1,
  "al.us": 1,
  "alabama.museum": 1,
  "alaheadju.no": 1,
  "aland.fi": 1,
  "alaska.museum": 1,
  "alces.network": 2,
  "alessandria.it": 1,
  "alesund.no": 1,
  "algard.no": 1,
  "alp1.ae.flow.ch": 1,
  "alpha-myqnapcloud.com": 1,
  "alpha.bounty-full.com": 1,
  "alstahaug.no": 1,
  "alt.za": 1,
  "alta.no": 1,
  "altervista.org": 1,
  "alto-adige.it": 1,
  "altoadige.it": 1,
  "alvdal.no": 1,
  "alwaysdata.net": 1,
  "am.br": 1,
  "am.gov.br": 1,
  "am.in": 1,
  "am.leg.br": 1,
  "ama.aichi.jp": 1,
  "ama.shimane.jp": 1,
  "amagasaki.hyogo.jp": 1,
  "amakusa.kumamoto.jp": 1,
  "amami.kagoshima.jp": 1,
  "amber.museum": 1,
  "ambulance.aero": 1,
  "ambulance.museum": 1,
  "american.museum": 1,
  "americana.museum": 1,
  "americanantiques.museum": 1,
  "americanart.museum": 1,
  "ami.ibaraki.jp": 1,
  "amli.no": 1,
  "amot.no": 1,
  "amscompute.com": 1,
  "amsterdam.museum": 1,
  "amusement.aero": 1,
  "an.it": 1,
  "anamizu.ishikawa.jp": 1,
  "anan.nagano.jp": 1,
  "anan.tokushima.jp": 1,
  "anani.br": 1,
  "ancona.it": 1,
  "and.museum": 1,
  "andasuolo.no": 1,
  "andebu.no": 1,
  "ando.nara.jp": 1,
  "andoy.no": 1,
  "andria-barletta-trani.it": 1,
  "andria-trani-barletta.it": 1,
  "andriabarlettatrani.it": 1,
  "andriatranibarletta.it": 1,
  "angry.jp": 1,
  "anjo.aichi.jp": 1,
  "ann-arbor.mi.us": 1,
  "annaka.gunma.jp": 1,
  "annefrank.museum": 1,
  "anpachi.gifu.jp": 1,
  "anthro.museum": 1,
  "anthropology.museum": 1,
  "antiques.museum": 1,
  "ao.it": 1,
  "aogaki.hyogo.jp": 1,
  "aogashima.tokyo.jp": 1,
  "aoki.nagano.jp": 1,
  "aomori.aomori.jp": 1,
  "aomori.jp": 1,
  "aosta-valley.it": 1,
  "aosta.it": 1,
  "aostavalley.it": 1,
  "aoste.it": 1,
  "ap-northeast-1.elasticbeanstalk.com": 1,
  "ap-northeast-2.elasticbeanstalk.com": 1,
  "ap-northeast-3.elasticbeanstalk.com": 1,
  "ap-south-1.elasticbeanstalk.com": 1,
  "ap-southeast-1.elasticbeanstalk.com": 1,
  "ap-southeast-2.elasticbeanstalk.com": 1,
  "ap.gov.br": 1,
  "ap.gov.pl": 1,
  "ap.it": 1,
  "ap.leg.br": 1,
  "aparecida.br": 1,
  "api.gov.uk": 1,
  "api.stdlib.com": 1,
  "apigee.io": 1,
  "app.banzaicloud.io": 1,
  "app.br": 1,
  "app.gp": 1,
  "app.lmpm.com": 1,
  "app.os.fedoraproject.org": 1,
  "app.os.stg.fedoraproject.org": 1,
  "app.render.com": 1,
  "appchizi.com": 1,
  "appengine.flow.ch": 1,
  "applinzi.com": 1,
  "apps.fbsbx.com": 1,
  "apps.lair.io": 1,
  "appspacehosted.com": 1,
  "appspaceusercontent.com": 1,
  "appspot.com": 1,
  "appudo.net": 1,
  "aq.it": 1,
  "aquarium.museum": 1,
  "aquila.it": 1,
  "ar.com": 1,
  "ar.it": 1,
  "ar.us": 1,
  "arai.shizuoka.jp": 1,
  "arakawa.saitama.jp": 1,
  "arakawa.tokyo.jp": 1,
  "arao.kumamoto.jp": 1,
  "arboretum.museum": 1,
  "archaeological.museum": 1,
  "archaeology.museum": 1,
  "architecture.museum": 1,
  "ardal.no": 1,
  "aremark.no": 1,
  "arendal.no": 1,
  "arezzo.it": 1,
  "ariake.saga.jp": 1,
  "arida.wakayama.jp": 1,
  "aridagawa.wakayama.jp": 1,
  "arita.saga.jp": 1,
  "arkhangelsk.su": 1,
  "armenia.su": 1,
  "arna.no": 1,
  "arq.br": 1,
  "art.br": 1,
  "art.do": 1,
  "art.dz": 1,
  "art.ht": 1,
  "art.museum": 1,
  "art.pl": 1,
  "art.sn": 1,
  "artanddesign.museum": 1,
  "artcenter.museum": 1,
  "artdeco.museum": 1,
  "arte.bo": 1,
  "arteducation.museum": 1,
  "artgallery.museum": 1,
  "arts.co": 1,
  "arts.museum": 1,
  "arts.nf": 1,
  "arts.ro": 1,
  "arts.ve": 1,
  "artsandcrafts.museum": 1,
  "arvo.network": 1,
  "as.us": 1,
  "asago.hyogo.jp": 1,
  "asahi.chiba.jp": 1,
  "asahi.ibaraki.jp": 1,
  "asahi.mie.jp": 1,
  "asahi.nagano.jp": 1,
  "asahi.toyama.jp": 1,
  "asahi.yamagata.jp": 1,
  "asahikawa.hokkaido.jp": 1,
  "asaka.saitama.jp": 1,
  "asakawa.fukushima.jp": 1,
  "asakuchi.okayama.jp": 1,
  "asaminami.hiroshima.jp": 1,
  "ascoli-piceno.it": 1,
  "ascolipiceno.it": 1,
  "aseral.no": 1,
  "ashgabad.su": 1,
  "ashibetsu.hokkaido.jp": 1,
  "ashikaga.tochigi.jp": 1,
  "ashiya.fukuoka.jp": 1,
  "ashiya.hyogo.jp": 1,
  "ashoro.hokkaido.jp": 1,
  "asker.no": 1,
  "askim.no": 1,
  "askoy.no": 1,
  "askvoll.no": 1,
  "asmatart.museum": 1,
  "asn.au": 1,
  "asn.lv": 1,
  "asnes.no": 1,
  "aso.kumamoto.jp": 1,
  "ass.km": 1,
  "assabu.hokkaido.jp": 1,
  "assassination.museum": 1,
  "assisi.museum": 1,
  "assn.lk": 1,
  "asso.bj": 1,
  "asso.ci": 1,
  "asso.dz": 1,
  "asso.eu.org": 1,
  "asso.fr": 1,
  "asso.gp": 1,
  "asso.ht": 1,
  "asso.km": 1,
  "asso.mc": 1,
  "asso.nc": 1,
  "asso.re": 1,
  "association.aero": 1,
  "association.museum": 1,
  "asti.it": 1,
  "astronomy.museum": 1,
  "asuke.aichi.jp": 1,
  "at-band-camp.net": 1,
  "at.eu.org": 1,
  "at.it": 1,
  "at.md": 1,
  "at.vg": 1,
  "atami.shizuoka.jp": 1,
  "ath.cx": 1,
  "atl.jelastic.vps-host.net": 1,
  "atlanta.museum": 1,
  "atm.pl": 1,
  "ato.br": 1,
  "atsugi.kanagawa.jp": 1,
  "atsuma.hokkaido.jp": 1,
  "au.eu.org": 1,
  "audnedaln.no": 1,
  "augustow.pl": 1,
  "aukra.no": 1,
  "aure.no": 1,
  "aurland.no": 1,
  "aurskog-holand.no": 1,
  "aus.basketball": 1,
  "austevoll.no": 1,
  "austin.museum": 1,
  "australia.museum": 1,
  "austrheim.no": 1,
  "authgear-staging.com": 1,
  "authgearapps.com": 1,
  "author.aero": 1,
  "auto.pl": 1,
  "automotive.museum": 1,
  "av.it": 1,
  "av.tr": 1,
  "avellino.it": 1,
  "averoy.no": 1,
  "aviation.museum": 1,
  "avocat.fr": 1,
  "avocat.pro": 1,
  "avoues.fr": 1,
  "awaji.hyogo.jp": 1,
  "awdev.ca": 2,
  "awsglobalaccelerator.com": 1,
  "awsmppl.com": 1,
  "axis.museum": 1,
  "aya.miyazaki.jp": 1,
  "ayabe.kyoto.jp": 1,
  "ayagawa.kagawa.jp": 1,
  "ayase.kanagawa.jp": 1,
  "az.us": 1,
  "azerbaijan.su": 1,
  "azimuth.network": 1,
  "azumino.nagano.jp": 1,
  "azure-mobile.net": 1,
  "azurecontainer.io": 2,
  "azurestaticapps.net": 1,
  "azurewebsites.net": 1,
  "b-data.io": 1,
  "b.bg": 1,
  "b.br": 1,
  "b.se": 1,
  "b.ssl.fastly.net": 1,
  "ba.gov.br": 1,
  "ba.it": 1,
  "ba.leg.br": 1,
  "babia-gora.pl": 1,
  "babyblue.jp": 1,
  "babymilk.jp": 1,
  "backdrop.jp": 1,
  "backplaneapp.io": 1,
  "backyards.banzaicloud.io": 2,
  "badaddja.no": 1,
  "badajoz.museum": 1,
  "baghdad.museum": 1,
  "bahcavuotna.no": 1,
  "bahccavuotna.no": 1,
  "bahn.museum": 1,
  "baidar.no": 1,
  "bajddar.no": 1,
  "balashov.su": 1,
  "balat.no": 1,
  "bale.museum": 1,
  "balena-devices.com": 1,
  "balestrand.no": 1,
  "ballangen.no": 1,
  "ballooning.aero": 1,
  "balsan-sudtirol.it": 1,
  "balsan-suedtirol.it": 1,
  "balsan.it": 1,
  "balsfjord.no": 1,
  "baltimore.museum": 1,
  "bambina.jp": 1,
  "bamble.no": 1,
  "bandai.fukushima.jp": 1,
  "bando.ibaraki.jp": 1,
  "banzai.cloud": 2,
  "bar.pro": 1,
  "bar0.net": 1,
  "bar1.net": 1,
  "bar2.net": 1,
  "barcelona.museum": 1,
  "bardu.no": 1,
  "bari.it": 1,
  "barletta-trani-andria.it": 1,
  "barlettatraniandria.it": 1,
  "barreau.bj": 1,
  "barrel-of-knowledge.info": 1,
  "barrell-of-knowledge.info": 1,
  "barsy.bg": 1,
  "barsy.ca": 1,
  "barsy.club": 1,
  "barsy.co.uk": 1,
  "barsy.de": 1,
  "barsy.eu": 1,
  "barsy.in": 1,
  "barsy.info": 1,
  "barsy.io": 1,
  "barsy.me": 1,
  "barsy.menu": 1,
  "barsy.mobi": 1,
  "barsy.net": 1,
  "barsy.online": 1,
  "barsy.org": 1,
  "barsy.pro": 1,
  "barsy.pub": 1,
  "barsy.ro": 1,
  "barsy.shop": 1,
  "barsy.site": 1,
  "barsy.support": 1,
  "barsy.uk": 1,
  "barsycenter.com": 1,
  "barsyonline.co.uk": 1,
  "barsyonline.com": 1,
  "barueri.br": 1,
  "barum.no": 1,
  "bas.it": 1,
  "base.ec": 1,
  "base.shop": 1,
  "baseball.museum": 1,
  "basel.museum": 1,
  "bashkiria.ru": 1,
  "bashkiria.su": 1,
  "basicserver.io": 1,
  "basilicata.it": 1,
  "baths.museum": 1,
  "bato.tochigi.jp": 1,
  "batsfjord.no": 1,
  "bauern.museum": 1,
  "bbs.tr": 1,
  "bc.ca": 1,
  "bc.platform.sh": 1,
  "bci.dnstrace.pro": 1,
  "bd": 2,
  "bd.se": 1,
  "be.ax": 1,
  "be.eu.org": 1,
  "be.gy": 1,
  "beagleboard.io": 1,
  "bearalvahki.no": 1,
  "beardu.no": 1,
  "beauxarts.museum": 1,
  "bedzin.pl": 1,
  "beeldengeluid.museum": 1,
  "beep.pl": 1,
  "beget.app": 2,
  "beiarn.no": 1,
  "bel.tr": 1,
  "belau.pw": 1,
  "belem.br": 1,
  "bellevue.museum": 1,
  "belluno.it": 1,
  "benevento.it": 1,
  "beppu.oita.jp": 1,
  "berg.no": 1,
  "bergamo.it": 1,
  "bergbau.museum": 1,
  "bergen.no": 1,
  "berkeley.museum": 1,
  "berlevag.no": 1,
  "berlin.museum": 1,
  "bern.museum": 1,
  "beskidy.pl": 1,
  "bet.ar": 1,
  "beta.bounty-full.com": 1,
  "beta.tailscale.net": 1,
  "betainabox.com": 1,
  "better-than.tv": 1,
  "bg.eu.org": 1,
  "bg.it": 1,
  "bhz.br": 1,
  "bi.it": 1,
  "bialowieza.pl": 1,
  "bialystok.pl": 1,
  "bib.br": 1,
  "bib.ve": 1,
  "bibai.hokkaido.jp": 1,
  "bible.museum": 1,
  "biei.hokkaido.jp": 1,
  "bielawa.pl": 1,
  "biella.it": 1,
  "bieszczady.pl": 1,
  "bievat.no": 1,
  "bifuka.hokkaido.jp": 1,
  "bihar.in": 1,
  "bihoro.hokkaido.jp": 1,
  "bilbao.museum": 1,
  "bill.museum": 1,
  "bindal.no": 1,
  "bio.br": 1,
  "bip.sh": 1,
  "bir.ru": 1,
  "biratori.hokkaido.jp": 1,
  "birdart.museum": 1,
  "birkenes.no": 1,
  "birthplace.museum": 1,
  "bitbridge.net": 1,
  "bitbucket.io": 1,
  "bitter.jp": 1,
  "biz.at": 1,
  "biz.az": 1,
  "biz.bb": 1,
  "biz.cy": 1,
  "biz.dk": 1,
  "biz.et": 1,
  "biz.fj": 1,
  "biz.gl": 1,
  "biz.id": 1,
  "biz.in": 1,
  "biz.ki": 1,
  "biz.ls": 1,
  "biz.mv": 1,
  "biz.mw": 1,
  "biz.my": 1,
  "biz.ni": 1,
  "biz.nr": 1,
  "biz.pk": 1,
  "biz.pl": 1,
  "biz.pr": 1,
  "biz.ss": 1,
  "biz.tj": 1,
  "biz.tr": 1,
  "biz.tt": 1,
  "biz.ua": 1,
  "biz.vn": 1,
  "biz.wf": 1,
  "biz.zm": 1,
  "bizen.okayama.jp": 1,
  "bj.cn": 1,
  "bjarkoy.no": 1,
  "bjerkreim.no": 1,
  "bjugn.no": 1,
  "bl.it": 1,
  "blackbaudcdn.net": 1,
  "blog.bo": 1,
  "blog.br": 1,
  "blog.gt": 1,
  "blog.kg": 1,
  "blog.vu": 1,
  "blogdns.com": 1,
  "blogdns.net": 1,
  "blogdns.org": 1,
  "blogsite.org": 1,
  "blogsite.xyz": 1,
  "blogspot.ae": 1,
  "blogspot.al": 1,
  "blogspot.am": 1,
  "blogspot.ba": 1,
  "blogspot.be": 1,
  "blogspot.bg": 1,
  "blogspot.bj": 1,
  "blogspot.ca": 1,
  "blogspot.cf": 1,
  "blogspot.ch": 1,
  "blogspot.cl": 1,
  "blogspot.co.at": 1,
  "blogspot.co.id": 1,
  "blogspot.co.il": 1,
  "blogspot.co.ke": 1,
  "blogspot.co.nz": 1,
  "blogspot.co.uk": 1,
  "blogspot.co.za": 1,
  "blogspot.com": 1,
  "blogspot.com.ar": 1,
  "blogspot.com.au": 1,
  "blogspot.com.br": 1,
  "blogspot.com.by": 1,
  "blogspot.com.co": 1,
  "blogspot.com.cy": 1,
  "blogspot.com.ee": 1,
  "blogspot.com.eg": 1,
  "blogspot.com.es": 1,
  "blogspot.com.mt": 1,
  "blogspot.com.ng": 1,
  "blogspot.com.tr": 1,
  "blogspot.com.uy": 1,
  "blogspot.cv": 1,
  "blogspot.cz": 1,
  "blogspot.de": 1,
  "blogspot.dk": 1,
  "blogspot.fi": 1,
  "blogspot.fr": 1,
  "blogspot.gr": 1,
  "blogspot.hk": 1,
  "blogspot.hr": 1,
  "blogspot.hu": 1,
  "blogspot.ie": 1,
  "blogspot.in": 1,
  "blogspot.is": 1,
  "blogspot.it": 1,
  "blogspot.jp": 1,
  "blogspot.kr": 1,
  "blogspot.li": 1,
  "blogspot.lt": 1,
  "blogspot.lu": 1,
  "blogspot.md": 1,
  "blogspot.mk": 1,
  "blogspot.mr": 1,
  "blogspot.mx": 1,
  "blogspot.my": 1,
  "blogspot.nl": 1,
  "blogspot.no": 1,
  "blogspot.pe": 1,
  "blogspot.pt": 1,
  "blogspot.qa": 1,
  "blogspot.re": 1,
  "blogspot.ro": 1,
  "blogspot.rs": 1,
  "blogspot.ru": 1,
  "blogspot.se": 1,
  "blogspot.sg": 1,
  "blogspot.si": 1,
  "blogspot.sk": 1,
  "blogspot.sn": 1,
  "blogspot.td": 1,
  "blogspot.tw": 1,
  "blogspot.ug": 1,
  "blogspot.vn": 1,
  "blogsyte.com": 1,
  "bloxcms.com": 1,
  "bluebite.io": 1,
  "blush.jp": 1,
  "bmd.br": 1,
  "bmoattachments.org": 1,
  "bn.it": 1,
  "bnr.la": 1,
  "bo.it": 1,
  "bo.nordland.no": 1,
  "bo.telemark.no": 1,
  "boavista.br": 1,
  "bodo.no": 1,
  "bokn.no": 1,
  "boldlygoingnowhere.org": 1,
  "boleslawiec.pl": 1,
  "bolivia.bo": 1,
  "bologna.it": 1,
  "bolt.hu": 1,
  "bolzano-altoadige.it": 1,
  "bolzano.it": 1,
  "bomlo.no": 1,
  "bonn.museum": 1,
  "boo.jp": 1,
  "bookonline.app": 1,
  "boomla.net": 1,
  "boston.museum": 1,
  "botanical.museum": 1,
  "botanicalgarden.museum": 1,
  "botanicgarden.museum": 1,
  "botany.museum": 1,
  "bounceme.net": 1,
  "bounty-full.com": 1,
  "boutir.com": 1,
  "boxfuse.io": 1,
  "boy.jp": 1,
  "boyfriend.jp": 1,
  "bozen-sudtirol.it": 1,
  "bozen-suedtirol.it": 1,
  "bozen.it": 1,
  "bplaced.com": 1,
  "bplaced.de": 1,
  "bplaced.net": 1,
  "br.com": 1,
  "br.it": 1,
  "brand.se": 1,
  "brandywinevalley.museum": 1,
  "brasil.museum": 1,
  "brasilia.me": 1,
  "bremanger.no": 1,
  "brescia.it": 1,
  "brindisi.it": 1,
  "bristol.museum": 1,
  "british.museum": 1,
  "britishcolumbia.museum": 1,
  "broadcast.museum": 1,
  "broke-it.net": 1,
  "broker.aero": 1,
  "bronnoy.no": 1,
  "bronnoysund.no": 1,
  "browsersafetymark.io": 1,
  "brumunddal.no": 1,
  "brunel.museum": 1,
  "brussel.museum": 1,
  "brussels.museum": 1,
  "bruxelles.museum": 1,
  "bryansk.su": 1,
  "bryne.no": 1,
  "bs.it": 1,
  "bsb.br": 1,
  "bss.design": 1,
  "bt.it": 1,
  "bu.no": 1,
  "budejju.no": 1,
  "build.run": 2,
  "builder.code.com": 2,
  "building.museum": 1,
  "builtwithdark.com": 1,
  "bukhara.su": 1,
  "bulsan-sudtirol.it": 1,
  "bulsan-suedtirol.it": 1,
  "bulsan.it": 1,
  "bungoono.oita.jp": 1,
  "bungotakada.oita.jp": 1,
  "bunkyo.tokyo.jp": 1,
  "burghof.museum": 1,
  "bus.museum": 1,
  "busan.kr": 1,
  "bushey.museum": 1,
  "business.in": 1,
  "but.jp": 1,
  "buyshop.jp": 1,
  "buyshouses.net": 1,
  "buzen.fukuoka.jp": 1,
  "bydgoszcz.pl": 1,
  "byen.site": 1,
  "bygland.no": 1,
  "bykle.no": 1,
  "bytom.pl": 1,
  "bz.it": 1,
  "bzz.dapps.earth": 2,
  "c.bg": 1,
  "c.cdn77.org": 1,
  "c.la": 1,
  "c.se": 1,
  "c66.me": 1,
  "ca-central-1.elasticbeanstalk.com": 1,
  "ca.eu.org": 1,
  "ca.in": 1,
  "ca.it": 1,
  "ca.na": 1,
  "ca.reclaim.cloud": 1,
  "ca.us": 1,
  "caa.aero": 1,
  "caa.li": 1,
  "cable-modem.org": 1,
  "cadaques.museum": 1,
  "cafjs.com": 1,
  "cagliari.it": 1,
  "cahcesuolo.no": 1,
  "cal.it": 1,
  "calabria.it": 1,
  "california.museum": 1,
  "caltanissetta.it": 1,
  "cam.it": 1,
  "cambridge.museum": 1,
  "camdvr.org": 1,
  "campaign.gov.uk": 1,
  "campania.it": 1,
  "campidano-medio.it": 1,
  "campidanomedio.it": 1,
  "campinagrande.br": 1,
  "campinas.br": 1,
  "campobasso.it": 1,
  "can.museum": 1,
  "canada.museum": 1,
  "candypop.jp": 1,
  "capebreton.museum": 1,
  "capoo.jp": 1,
  "caracal.mythic-beasts.com": 1,
  "carbonia-iglesias.it": 1,
  "carboniaiglesias.it": 1,
  "cargo.aero": 1,
  "carrara-massa.it": 1,
  "carraramassa.it": 1,
  "carrd.co": 1,
  "carrier.museum": 1,
  "cartoonart.museum": 1,
  "casacam.net": 1,
  "casadelamoneda.museum": 1,
  "caserta.it": 1,
  "casino.hu": 1,
  "castle.museum": 1,
  "castres.museum": 1,
  "cat.ax": 1,
  "catania.it": 1,
  "catanzaro.it": 1,
  "catering.aero": 1,
  "catfood.jp": 1,
  "catholic.edu.au": 1,
  "caxias.br": 1,
  "cb.it": 1,
  "cbg.ru": 1,
  "cc.ak.us": 1,
  "cc.al.us": 1,
  "cc.ar.us": 1,
  "cc.as.us": 1,
  "cc.az.us": 1,
  "cc.ca.us": 1,
  "cc.co.us": 1,
  "cc.ct.us": 1,
  "cc.dc.us": 1,
  "cc.de.us": 1,
  "cc.fl.us": 1,
  "cc.ga.us": 1,
  "cc.gu.us": 1,
  "cc.hi.us": 1,
  "cc.hn": 1,
  "cc.ia.us": 1,
  "cc.id.us": 1,
  "cc.il.us": 1,
  "cc.in.us": 1,
  "cc.ks.us": 1,
  "cc.ky.us": 1,
  "cc.la.us": 1,
  "cc.ma.us": 1,
  "cc.md.us": 1,
  "cc.me.us": 1,
  "cc.mi.us": 1,
  "cc.mn.us": 1,
  "cc.mo.us": 1,
  "cc.ms.us": 1,
  "cc.mt.us": 1,
  "cc.na": 1,
  "cc.nc.us": 1,
  "cc.nd.us": 1,
  "cc.ne.us": 1,
  "cc.nh.us": 1,
  "cc.nj.us": 1,
  "cc.nm.us": 1,
  "cc.nv.us": 1,
  "cc.ny.us": 1,
  "cc.oh.us": 1,
  "cc.ok.us": 1,
  "cc.or.us": 1,
  "cc.pa.us": 1,
  "cc.pr.us": 1,
  "cc.ri.us": 1,
  "cc.sc.us": 1,
  "cc.sd.us": 1,
  "cc.tn.us": 1,
  "cc.tx.us": 1,
  "cc.ua": 1,
  "cc.ut.us": 1,
  "cc.va.us": 1,
  "cc.vi.us": 1,
  "cc.vt.us": 1,
  "cc.wa.us": 1,
  "cc.wi.us": 1,
  "cc.wv.us": 1,
  "cc.wy.us": 1,
  "cci.fr": 1,
  "cd.eu.org": 1,
  "cdn-edges.net": 1,
  "cdn.prod.atlassian-dev.net": 1,
  "cdn77-ssl.net": 1,
  "ce.gov.br": 1,
  "ce.it": 1,
  "ce.leg.br": 1,
  "cechire.com": 1,
  "celtic.museum": 1,
  "center.museum": 1,
  "centralus.azurestaticapps.net": 1,
  "certification.aero": 1,
  "certmgr.org": 1,
  "cesena-forli.it": 1,
  "cesenaforli.it": 1,
  "cf-ipfs.com": 1,
  "ch.eu.org": 1,
  "ch.it": 1,
  "ch.tc": 1,
  "ch.trendhosting.cloud": 1,
  "chambagri.fr": 1,
  "championship.aero": 1,
  "channelsdvr.net": 1,
  "charter.aero": 1,
  "chattanooga.museum": 1,
  "cheap.jp": 1,
  "cheltenham.museum": 1,
  "cherkassy.ua": 1,
  "cherkasy.ua": 1,
  "chernigov.ua": 1,
  "chernihiv.ua": 1,
  "chernivtsi.ua": 1,
  "chernovtsy.ua": 1,
  "chesapeakebay.museum": 1,
  "chiba.jp": 1,
  "chicago.museum": 1,
  "chicappa.jp": 1,
  "chichibu.saitama.jp": 1,
  "chieti.it": 1,
  "chigasaki.kanagawa.jp": 1,
  "chihayaakasaka.osaka.jp": 1,
  "chijiwa.nagasaki.jp": 1,
  "chikugo.fukuoka.jp": 1,
  "chikuho.fukuoka.jp": 1,
  "chikuhoku.nagano.jp": 1,
  "chikujo.fukuoka.jp": 1,
  "chikuma.nagano.jp": 1,
  "chikusei.ibaraki.jp": 1,
  "chikushino.fukuoka.jp": 1,
  "chikuzen.fukuoka.jp": 1,
  "children.museum": 1,
  "childrens.museum": 1,
  "childrensgarden.museum": 1,
  "chillout.jp": 1,
  "chimkent.su": 1,
  "chino.nagano.jp": 1,
  "chippubetsu.hokkaido.jp": 1,
  "chips.jp": 1,
  "chiropractic.museum": 1,
  "chirurgiens-dentistes-en-france.fr": 1,
  "chirurgiens-dentistes.fr": 1,
  "chiryu.aichi.jp": 1,
  "chita.aichi.jp": 1,
  "chitose.hokkaido.jp": 1,
  "chiyoda.gunma.jp": 1,
  "chiyoda.tokyo.jp": 1,
  "chizu.tottori.jp": 1,
  "chocolate.museum": 1,
  "chofu.tokyo.jp": 1,
  "chonan.chiba.jp": 1,
  "chosei.chiba.jp": 1,
  "choshi.chiba.jp": 1,
  "chowder.jp": 1,
  "choyo.kumamoto.jp": 1,
  "christiansburg.museum": 1,
  "chtr.k12.ma.us": 1,
  "chu.jp": 1,
  "chungbuk.kr": 1,
  "chungnam.kr": 1,
  "chuo.chiba.jp": 1,
  "chuo.fukuoka.jp": 1,
  "chuo.osaka.jp": 1,
  "chuo.tokyo.jp": 1,
  "chuo.yamanashi.jp": 1,
  "ci.it": 1,
  "ciao.jp": 1,
  "ciencia.bo": 1,
  "cieszyn.pl": 1,
  "cim.br": 1,
  "cincinnati.museum": 1,
  "cinema.museum": 1,
  "circus.museum": 1,
  "ciscofreak.com": 1,
  "cistron.nl": 1,
  "city.hu": 1,
  "city.kawasaki.jp": 0,
  "city.kitakyushu.jp": 0,
  "city.kobe.jp": 0,
  "city.nagoya.jp": 0,
  "city.sapporo.jp": 0,
  "city.sendai.jp": 0,
  "city.yokohama.jp": 0,
  "civilaviation.aero": 1,
  "civilisation.museum": 1,
  "civilization.museum": 1,
  "civilwar.museum": 1,
  "ck": 2,
  "ck.ua": 1,
  "cl.it": 1,
  "clan.rip": 1,
  "clerk.app": 1,
  "clerkstage.app": 1,
  "cleverapps.io": 1,
  "clicketcloud.com": 1,
  "clickrising.net": 1,
  "clinton.museum": 1,
  "clock.museum": 1,
  "cloud-fr1.unispace.io": 1,
  "cloud.fedoraproject.org": 1,
  "cloud.goog": 1,
  "cloud.interhostsolutions.be": 1,
  "cloud.jelastic.open.tim.it": 1,
  "cloud.metacentrum.cz": 2,
  "cloud.nospamproxy.com": 1,
  "cloud66.ws": 1,
  "cloud66.zone": 1,
  "cloudaccess.host": 1,
  "cloudaccess.net": 1,
  "cloudapp.net": 1,
  "cloudapps.digital": 1,
  "cloudcontrolapp.com": 1,
  "cloudcontrolled.com": 1,
  "cloudera.site": 2,
  "cloudflare-ipfs.com": 1,
  "cloudfront.net": 1,
  "cloudfunctions.net": 1,
  "cloudjiffy.net": 1,
  "cloudns.asia": 1,
  "cloudns.biz": 1,
  "cloudns.cc": 1,
  "cloudns.club": 1,
  "cloudns.eu": 1,
  "cloudns.in": 1,
  "cloudns.info": 1,
  "cloudns.org": 1,
  "cloudns.pro": 1,
  "cloudns.pw": 1,
  "cloudns.us": 1,
  "cloudsite.builders": 1,
  "cloudycluster.net": 1,
  "club.aero": 1,
  "club.tw": 1,
  "cn-north-1.eb.amazonaws.com.cn": 1,
  "cn-northwest-1.eb.amazonaws.com.cn": 1,
  "cn.com": 1,
  "cn.eu.org": 1,
  "cn.in": 1,
  "cn.it": 1,
  "cn.ua": 1,
  "cn.vu": 1,
  "cng.br": 1,
  "cnpy.gdn": 1,
  "cns.joyent.com": 2,
  "cnt.br": 1,
  "co.ae": 1,
  "co.ag": 1,
  "co.am": 1,
  "co.ao": 1,
  "co.at": 1,
  "co.bb": 1,
  "co.bi": 1,
  "co.bn": 1,
  "co.business": 1,
  "co.bw": 1,
  "co.ca": 1,
  "co.ci": 1,
  "co.cl": 1,
  "co.cm": 1,
  "co.com": 1,
  "co.cr": 1,
  "co.cz": 1,
  "co.dk": 1,
  "co.education": 1,
  "co.events": 1,
  "co.financial": 1,
  "co.gg": 1,
  "co.gl": 1,
  "co.gy": 1,
  "co.hu": 1,
  "co.id": 1,
  "co.il": 1,
  "co.im": 1,
  "co.in": 1,
  "co.ir": 1,
  "co.it": 1,
  "co.je": 1,
  "co.jp": 1,
  "co.ke": 1,
  "co.kr": 1,
  "co.krd": 1,
  "co.lc": 1,
  "co.ls": 1,
  "co.ma": 1,
  "co.me": 1,
  "co.mg": 1,
  "co.mu": 1,
  "co.mw": 1,
  "co.mz": 1,
  "co.na": 1,
  "co.network": 1,
  "co.ni": 1,
  "co.nl": 1,
  "co.no": 1,
  "co.nz": 1,
  "co.om": 1,
  "co.pl": 1,
  "co.place": 1,
  "co.pn": 1,
  "co.pw": 1,
  "co.ro": 1,
  "co.rs": 1,
  "co.rw": 1,
  "co.st": 1,
  "co.sz": 1,
  "co.technology": 1,
  "co.th": 1,
  "co.tj": 1,
  "co.tm": 1,
  "co.tt": 1,
  "co.tz": 1,
  "co.ua": 1,
  "co.ug": 1,
  "co.uk": 1,
  "co.us": 1,
  "co.uz": 1,
  "co.ve": 1,
  "co.vi": 1,
  "co.za": 1,
  "co.zm": 1,
  "co.zw": 1,
  "coal.museum": 1,
  "coastaldefence.museum": 1,
  "cocotte.jp": 1,
  "code.run": 2,
  "codeberg.page": 1,
  "codespot.com": 1,
  "cody.museum": 1,
  "cog.mi.us": 1,
  "col.ng": 1,
  "coldwar.museum": 1,
  "collection.museum": 1,
  "collegefan.org": 1,
  "colonialwilliamsburg.museum": 1,
  "coloradoplateau.museum": 1,
  "columbia.museum": 1,
  "columbus.museum": 1,
  "com.ac": 1,
  "com.af": 1,
  "com.ag": 1,
  "com.ai": 1,
  "com.al": 1,
  "com.am": 1,
  "com.ar": 1,
  "com.au": 1,
  "com.aw": 1,
  "com.az": 1,
  "com.ba": 1,
  "com.bb": 1,
  "com.bh": 1,
  "com.bi": 1,
  "com.bm": 1,
  "com.bn": 1,
  "com.bo": 1,
  "com.br": 1,
  "com.bs": 1,
  "com.bt": 1,
  "com.by": 1,
  "com.bz": 1,
  "com.ci": 1,
  "com.cm": 1,
  "com.cn": 1,
  "com.co": 1,
  "com.cu": 1,
  "com.cv": 1,
  "com.cw": 1,
  "com.cy": 1,
  "com.de": 1,
  "com.dm": 1,
  "com.do": 1,
  "com.dz": 1,
  "com.ec": 1,
  "com.ee": 1,
  "com.eg": 1,
  "com.es": 1,
  "com.et": 1,
  "com.fj": 1,
  "com.fm": 1,
  "com.fr": 1,
  "com.ge": 1,
  "com.gh": 1,
  "com.gi": 1,
  "com.gl": 1,
  "com.gn": 1,
  "com.gp": 1,
  "com.gr": 1,
  "com.gt": 1,
  "com.gu": 1,
  "com.gy": 1,
  "com.hk": 1,
  "com.hn": 1,
  "com.hr": 1,
  "com.ht": 1,
  "com.im": 1,
  "com.in": 1,
  "com.io": 1,
  "com.iq": 1,
  "com.is": 1,
  "com.jo": 1,
  "com.kg": 1,
  "com.ki": 1,
  "com.km": 1,
  "com.kp": 1,
  "com.kw": 1,
  "com.ky": 1,
  "com.kz": 1,
  "com.la": 1,
  "com.lb": 1,
  "com.lc": 1,
  "com.lk": 1,
  "com.lr": 1,
  "com.lv": 1,
  "com.ly": 1,
  "com.mg": 1,
  "com.mk": 1,
  "com.ml": 1,
  "com.mo": 1,
  "com.ms": 1,
  "com.mt": 1,
  "com.mu": 1,
  "com.mv": 1,
  "com.mw": 1,
  "com.mx": 1,
  "com.my": 1,
  "com.na": 1,
  "com.nf": 1,
  "com.ng": 1,
  "com.ni": 1,
  "com.nr": 1,
  "com.om": 1,
  "com.pa": 1,
  "com.pe": 1,
  "com.pf": 1,
  "com.ph": 1,
  "com.pk": 1,
  "com.pl": 1,
  "com.pr": 1,
  "com.ps": 1,
  "com.pt": 1,
  "com.py": 1,
  "com.qa": 1,
  "com.re": 1,
  "com.ro": 1,
  "com.ru": 1,
  "com.sa": 1,
  "com.sb": 1,
  "com.sc": 1,
  "com.sd": 1,
  "com.se": 1,
  "com.sg": 1,
  "com.sh": 1,
  "com.sl": 1,
  "com.sn": 1,
  "com.so": 1,
  "com.ss": 1,
  "com.st": 1,
  "com.sv": 1,
  "com.sy": 1,
  "com.tj": 1,
  "com.tm": 1,
  "com.tn": 1,
  "com.to": 1,
  "com.tr": 1,
  "com.tt": 1,
  "com.tw": 1,
  "com.ua": 1,
  "com.ug": 1,
  "com.uy": 1,
  "com.uz": 1,
  "com.vc": 1,
  "com.ve": 1,
  "com.vi": 1,
  "com.vn": 1,
  "com.vu": 1,
  "com.ws": 1,
  "com.ye": 1,
  "com.zm": 1,
  "commune.am": 1,
  "communication.museum": 1,
  "communications.museum": 1,
  "community-pro.de": 1,
  "community-pro.net": 1,
  "community.museum": 1,
  "como.it": 1,
  "compute-1.amazonaws.com": 2,
  "compute.amazonaws.com": 2,
  "compute.amazonaws.com.cn": 2,
  "compute.estate": 2,
  "computer.museum": 1,
  "computerhistory.museum": 1,
  "conf.au": 1,
  "conf.lv": 1,
  "conf.se": 1,
  "conference.aero": 1,
  "conn.uk": 1,
  "consulado.st": 1,
  "consultant.aero": 1,
  "consulting.aero": 1,
  "contagem.br": 1,
  "contemporary.museum": 1,
  "contemporaryart.museum": 1,
  "control.aero": 1,
  "convent.museum": 1,
  "coolblog.jp": 1,
  "coop.ar": 1,
  "coop.br": 1,
  "coop.ht": 1,
  "coop.in": 1,
  "coop.km": 1,
  "coop.mv": 1,
  "coop.mw": 1,
  "coop.py": 1,
  "coop.rw": 1,
  "coop.tt": 1,
  "cooperativa.bo": 1,
  "copenhagen.museum": 1,
  "copro.uk": 1,
  "corporation.museum": 1,
  "corvette.museum": 1,
  "cosenza.it": 1,
  "costume.museum": 1,
  "couchpotatofries.org": 1,
  "council.aero": 1,
  "countryestate.museum": 1,
  "county.museum": 1,
  "coz.br": 1,
  "cpa.pro": 1,
  "cq.cn": 1,
  "cr.it": 1,
  "cr.ua": 1,
  "crafting.xyz": 1,
  "crafts.museum": 1,
  "cranbrook.museum": 1,
  "cranky.jp": 1,
  "crd.co": 1,
  "creation.museum": 1,
  "cremona.it": 1,
  "crew.aero": 1,
  "cri.br": 1,
  "cri.nz": 1,
  "crimea.ua": 1,
  "crotone.it": 1,
  "cryptonomic.net": 2,
  "cs.in": 1,
  "cs.it": 1,
  "cs.keliweb.cloud": 1,
  "csx.cc": 1,
  "ct.it": 1,
  "ct.us": 1,
  "cuiaba.br": 1,
  "cultural.museum": 1,
  "culturalcenter.museum": 1,
  "culture.museum": 1,
  "cuneo.it": 1,
  "cupcake.is": 1,
  "curitiba.br": 1,
  "curv.dev": 1,
  "cust.dev.thingdust.io": 1,
  "cust.disrec.thingdust.io": 1,
  "cust.prod.thingdust.io": 1,
  "cust.retrosnub.co.uk": 1,
  "cust.testing.thingdust.io": 1,
  "custom.metacentrum.cz": 1,
  "customer-oci.com": 2,
  "customer.mythic-beasts.com": 1,
  "customer.speedpartner.de": 1,
  "cutegirl.jp": 1,
  "cv.ua": 1,
  "cx.ua": 1,
  "cy.eu.org": 1,
  "cya.gg": 1,
  "cyber.museum": 1,
  "cymru.museum": 1,
  "cyon.link": 1,
  "cyon.site": 1,
  "cz.eu.org": 1,
  "cz.it": 1,
  "czeladz.pl": 1,
  "czest.pl": 1,
  "d.bg": 1,
  "d.gv.vc": 1,
  "d.se": 1,
  "daa.jp": 1,
  "daegu.kr": 1,
  "daejeon.kr": 1,
  "daemon.panel.gg": 1,
  "dagestan.ru": 1,
  "dagestan.su": 1,
  "daigo.ibaraki.jp": 1,
  "daisen.akita.jp": 1,
  "daito.osaka.jp": 1,
  "daiwa.hiroshima.jp": 1,
  "dali.museum": 1,
  "dallas.museum": 1,
  "damnserver.com": 1,
  "daplie.me": 1,
  "dapps.earth": 2,
  "database.museum": 1,
  "database.run": 2,
  "date.fukushima.jp": 1,
  "date.hokkaido.jp": 1,
  "dattolocal.com": 1,
  "dattolocal.net": 1,
  "dattorelay.com": 1,
  "dattoweb.com": 1,
  "davvenjarga.no": 1,
  "davvesiida.no": 1,
  "dazaifu.fukuoka.jp": 1,
  "dc.us": 1,
  "dd-dns.de": 1,
  "ddns.me": 1,
  "ddns.net": 1,
  "ddns5.com": 1,
  "ddnsfree.com": 1,
  "ddnsgeek.com": 1,
  "ddnsking.com": 1,
  "ddnslive.com": 1,
  "ddnss.de": 1,
  "ddnss.org": 1,
  "ddr.museum": 1,
  "de.com": 1,
  "de.cool": 1,
  "de.eu.org": 1,
  "de.gt": 1,
  "de.ls": 1,
  "de.md": 1,
  "de.trendhosting.cloud": 1,
  "de.us": 1,
  "deatnu.no": 1,
  "debian.net": 1,
  "deca.jp": 1,
  "deci.jp": 1,
  "decorativearts.museum": 1,
  "dedibox.fr": 1,
  "dedyn.io": 1,
  "def.br": 1,
  "definima.io": 1,
  "definima.net": 1,
  "delaware.museum": 1,
  "delhi.in": 1,
  "dell-ogliastra.it": 1,
  "dellogliastra.it": 1,
  "delmenhorst.museum": 1,
  "demo.datacenter.fi": 1,
  "demo.datadetect.com": 1,
  "demo.jelastic.com": 1,
  "democracia.bo": 1,
  "demon.nl": 1,
  "denmark.museum": 1,
  "deno-staging.dev": 1,
  "deno.dev": 1,
  "dep.no": 1,
  "deporte.bo": 1,
  "depot.museum": 1,
  "des.br": 1,
  "desa.id": 1,
  "design.aero": 1,
  "design.museum": 1,
  "det.br": 1,
  "deta.app": 1,
  "deta.dev": 1,
  "detroit.museum": 1,
  "dev-builder.code.com": 2,
  "dev-myqnapcloud.com": 1,
  "dev.adobeaemcloud.com": 2,
  "dev.br": 1,
  "dev.static.land": 1,
  "dev.vu": 1,
  "devcdnaccesso.com": 2,
  "developer.app": 2,
  "development.run": 1,
  "devices.resinstaging.io": 1,
  "df.gov.br": 1,
  "df.leg.br": 1,
  "dgca.aero": 1,
  "dh.bytemark.co.uk": 1,
  "diadem.cloud": 1,
  "dielddanuorri.no": 1,
  "digick.jp": 1,
  "digitaloceanspaces.com": 2,
  "diher.solutions": 2,
  "dinosaur.museum": 1,
  "direct.quickconnect.cn": 1,
  "direct.quickconnect.to": 1,
  "discordsays.com": 1,
  "discordsez.com": 1,
  "discourse.group": 1,
  "discourse.team": 1,
  "discovery.museum": 1,
  "diskstation.eu": 1,
  "diskstation.me": 1,
  "diskstation.org": 1,
  "diskussionsbereich.de": 1,
  "ditchyourip.com": 1,
  "divtasvuodna.no": 1,
  "divttasvuotna.no": 1,
  "dk.eu.org": 1,
  "dlugoleka.pl": 1,
  "dn.ua": 1,
  "dnepropetrovsk.ua": 1,
  "dni.us": 1,
  "dnipropetrovsk.ua": 1,
  "dnsalias.com": 1,
  "dnsalias.net": 1,
  "dnsalias.org": 1,
  "dnsdojo.com": 1,
  "dnsdojo.net": 1,
  "dnsdojo.org": 1,
  "dnsfor.me": 1,
  "dnshome.de": 1,
  "dnsiskinky.com": 1,
  "dnsking.ch": 1,
  "dnsup.net": 1,
  "dnsupdate.info": 1,
  "dnsupdater.de": 1,
  "does-it.net": 1,
  "doesntexist.com": 1,
  "doesntexist.org": 1,
  "dolls.museum": 1,
  "donetsk.ua": 1,
  "donna.no": 1,
  "donostia.museum": 1,
  "dontexist.com": 1,
  "dontexist.net": 1,
  "dontexist.org": 1,
  "doomdns.com": 1,
  "doomdns.org": 1,
  "dopaas.com": 1,
  "doshi.yamanashi.jp": 1,
  "dovre.no": 1,
  "dp.ua": 1,
  "dr.in": 1,
  "dr.na": 1,
  "dr.tr": 1,
  "drammen.no": 1,
  "drangedal.no": 1,
  "dray-dns.de": 1,
  "drayddns.com": 1,
  "draydns.de": 1,
  "dreamhosters.com": 1,
  "drobak.no": 1,
  "drr.ac": 1,
  "drud.io": 1,
  "drud.us": 1,
  "dscloud.biz": 1,
  "dscloud.me": 1,
  "dscloud.mobi": 1,
  "dsmynas.com": 1,
  "dsmynas.net": 1,
  "dsmynas.org": 1,
  "dst.mi.us": 1,
  "duckdns.org": 1,
  "durham.museum": 1,
  "dvrcam.info": 1,
  "dvrdns.org": 1,
  "dweb.link": 2,
  "dy.fi": 1,
  "dyn-berlin.de": 1,
  "dyn-ip24.de": 1,
  "dyn-o-saur.com": 1,
  "dyn-vpn.de": 1,
  "dyn.cosidns.de": 1,
  "dyn.ddnss.de": 1,
  "dyn.home-webserver.de": 1,
  "dyn53.io": 1,
  "dynalias.com": 1,
  "dynalias.net": 1,
  "dynalias.org": 1,
  "dynamic-dns.info": 1,
  "dynamisches-dns.de": 1,
  "dynathome.net": 1,
  "dyndns-at-home.com": 1,
  "dyndns-at-work.com": 1,
  "dyndns-blog.com": 1,
  "dyndns-free.com": 1,
  "dyndns-home.com": 1,
  "dyndns-ip.com": 1,
  "dyndns-mail.com": 1,
  "dyndns-office.com": 1,
  "dyndns-pics.com": 1,
  "dyndns-remote.com": 1,
  "dyndns-server.com": 1,
  "dyndns-web.com": 1,
  "dyndns-wiki.com": 1,
  "dyndns-work.com": 1,
  "dyndns.biz": 1,
  "dyndns.dappnode.io": 1,
  "dyndns.ddnss.de": 1,
  "dyndns.info": 1,
  "dyndns.org": 1,
  "dyndns.tv": 1,
  "dyndns.ws": 1,
  "dyndns1.de": 1,
  "dynns.com": 1,
  "dynserv.org": 1,
  "dynu.net": 1,
  "dynv6.net": 1,
  "dynvpn.de": 1,
  "dyroy.no": 1,
  "e.bg": 1,
  "e.se": 1,
  "e12.ve": 1,
  "e164.arpa": 1,
  "e4.cz": 1,
  "east-kazakhstan.su": 1,
  "eastafrica.museum": 1,
  "eastasia.azurestaticapps.net": 1,
  "eastcoast.museum": 1,
  "eastus2.azurestaticapps.net": 1,
  "easypanel.app": 1,
  "easypanel.host": 1,
  "eating-organic.net": 1,
  "eaton.mi.us": 1,
  "ebetsu.hokkaido.jp": 1,
  "ebina.kanagawa.jp": 1,
  "ebino.miyazaki.jp": 1,
  "ebiz.tw": 1,
  "echizen.fukui.jp": 1,
  "ecn.br": 1,
  "eco.br": 1,
  "ecologia.bo": 1,
  "ecommerce-shop.pl": 1,
  "economia.bo": 1,
  "ed.ao": 1,
  "ed.ci": 1,
  "ed.cr": 1,
  "ed.jp": 1,
  "ed.pw": 1,
  "edgeapp.net": 1,
  "edgecompute.app": 1,
  "edgestack.me": 1,
  "editorx.io": 1,
  "edogawa.tokyo.jp": 1,
  "edu.ac": 1,
  "edu.af": 1,
  "edu.al": 1,
  "edu.ar": 1,
  "edu.au": 1,
  "edu.az": 1,
  "edu.ba": 1,
  "edu.bb": 1,
  "edu.bh": 1,
  "edu.bi": 1,
  "edu.bm": 1,
  "edu.bn": 1,
  "edu.bo": 1,
  "edu.br": 1,
  "edu.bs": 1,
  "edu.bt": 1,
  "edu.bz": 1,
  "edu.ci": 1,
  "edu.cn": 1,
  "edu.co": 1,
  "edu.cu": 1,
  "edu.cv": 1,
  "edu.cw": 1,
  "edu.dm": 1,
  "edu.do": 1,
  "edu.dz": 1,
  "edu.ec": 1,
  "edu.ee": 1,
  "edu.eg": 1,
  "edu.es": 1,
  "edu.et": 1,
  "edu.eu.org": 1,
  "edu.fm": 1,
  "edu.gd": 1,
  "edu.ge": 1,
  "edu.gh": 1,
  "edu.gi": 1,
  "edu.gl": 1,
  "edu.gn": 1,
  "edu.gp": 1,
  "edu.gr": 1,
  "edu.gt": 1,
  "edu.gu": 1,
  "edu.gy": 1,
  "edu.hk": 1,
  "edu.hn": 1,
  "edu.ht": 1,
  "edu.in": 1,
  "edu.iq": 1,
  "edu.is": 1,
  "edu.it": 1,
  "edu.jo": 1,
  "edu.kg": 1,
  "edu.ki": 1,
  "edu.km": 1,
  "edu.kn": 1,
  "edu.kp": 1,
  "edu.krd": 1,
  "edu.kw": 1,
  "edu.ky": 1,
  "edu.kz": 1,
  "edu.la": 1,
  "edu.lb": 1,
  "edu.lc": 1,
  "edu.lk": 1,
  "edu.lr": 1,
  "edu.ls": 1,
  "edu.lv": 1,
  "edu.ly": 1,
  "edu.me": 1,
  "edu.mg": 1,
  "edu.mk": 1,
  "edu.ml": 1,
  "edu.mn": 1,
  "edu.mo": 1,
  "edu.ms": 1,
  "edu.mt": 1,
  "edu.mv": 1,
  "edu.mw": 1,
  "edu.mx": 1,
  "edu.my": 1,
  "edu.mz": 1,
  "edu.ng": 1,
  "edu.ni": 1,
  "edu.nr": 1,
  "edu.om": 1,
  "edu.pa": 1,
  "edu.pe": 1,
  "edu.pf": 1,
  "edu.ph": 1,
  "edu.pk": 1,
  "edu.pl": 1,
  "edu.pn": 1,
  "edu.pr": 1,
  "edu.ps": 1,
  "edu.pt": 1,
  "edu.py": 1,
  "edu.qa": 1,
  "edu.rs": 1,
  "edu.ru": 1,
  "edu.sa": 1,
  "edu.sb": 1,
  "edu.sc": 1,
  "edu.scot": 1,
  "edu.sd": 1,
  "edu.sg": 1,
  "edu.sl": 1,
  "edu.sn": 1,
  "edu.so": 1,
  "edu.ss": 1,
  "edu.st": 1,
  "edu.sv": 1,
  "edu.sy": 1,
  "edu.tj": 1,
  "edu.tm": 1,
  "edu.to": 1,
  "edu.tr": 1,
  "edu.tt": 1,
  "edu.tw": 1,
  "edu.ua": 1,
  "edu.uy": 1,
  "edu.vc": 1,
  "edu.ve": 1,
  "edu.vn": 1,
  "edu.vu": 1,
  "edu.ws": 1,
  "edu.ye": 1,
  "edu.za": 1,
  "edu.zm": 1,
  "education.museum": 1,
  "educational.museum": 1,
  "educator.aero": 1,
  "edugit.io": 1,
  "ee.eu.org": 1,
  "eero-stage.online": 1,
  "eero.online": 1,
  "egersund.no": 1,
  "egoism.jp": 1,
  "egyptian.museum": 1,
  "ehime.jp": 1,
  "eid.no": 1,
  "eidfjord.no": 1,
  "eidsberg.no": 1,
  "eidskog.no": 1,
  "eidsvoll.no": 1,
  "eigersund.no": 1,
  "eiheiji.fukui.jp": 1,
  "eisenbahn.museum": 1,
  "ekloges.cy": 1,
  "elasticbeanstalk.com": 1,
  "elb.amazonaws.com": 2,
  "elb.amazonaws.com.cn": 2,
  "elblag.pl": 1,
  "elburg.museum": 1,
  "elementor.cloud": 1,
  "elementor.cool": 1,
  "elk.pl": 1,
  "elvendrell.museum": 1,
  "elverum.no": 1,
  "emb.kw": 1,
  "embaixada.st": 1,
  "embetsu.hokkaido.jp": 1,
  "embroidery.museum": 1,
  "emergency.aero": 1,
  "emilia-romagna.it": 1,
  "emiliaromagna.it": 1,
  "emp.br": 1,
  "empresa.bo": 1,
  "emr.it": 1,
  "en-root.fr": 1,
  "en.it": 1,
  "ena.gifu.jp": 1,
  "encoreapi.com": 1,
  "encr.app": 1,
  "encyclopedic.museum": 1,
  "endofinternet.net": 1,
  "endofinternet.org": 1,
  "endoftheinternet.org": 1,
  "enebakk.no": 1,
  "enf.br": 1,
  "eng.br": 1,
  "eng.pro": 1,
  "engerdal.no": 1,
  "engine.aero": 1,
  "engineer.aero": 1,
  "england.museum": 1,
  "eniwa.hokkaido.jp": 1,
  "enna.it": 1,
  "ens.tn": 1,
  "enscaled.sg": 1,
  "ent.platform.sh": 1,
  "enterprisecloud.nu": 1,
  "entertainment.aero": 1,
  "entomology.museum": 1,
  "environment.museum": 1,
  "environmentalconservation.museum": 1,
  "epilepsy.museum": 1,
  "equipment.aero": 1,
  "er": 2,
  "er.in": 1,
  "erimo.hokkaido.jp": 1,
  "erotica.hu": 1,
  "erotika.hu": 1,
  "es-1.axarnet.cloud": 1,
  "es.ax": 1,
  "es.eu.org": 1,
  "es.gov.br": 1,
  "es.kr": 1,
  "es.leg.br": 1,
  "esan.hokkaido.jp": 1,
  "esashi.hokkaido.jp": 1,
  "esp.br": 1,
  "essex.museum": 1,
  "est-a-la-maison.com": 1,
  "est-a-la-masion.com": 1,
  "est-le-patron.com": 1,
  "est-mon-blogueur.com": 1,
  "est.pr": 1,
  "estate.museum": 1,
  "etajima.hiroshima.jp": 1,
  "etc.br": 1,
  "ethnology.museum": 1,
  "eti.br": 1,
  "etne.no": 1,
  "etnedal.no": 1,
  "eu-1.evennode.com": 1,
  "eu-2.evennode.com": 1,
  "eu-3.evennode.com": 1,
  "eu-4.evennode.com": 1,
  "eu-central-1.elasticbeanstalk.com": 1,
  "eu-west-1.elasticbeanstalk.com": 1,
  "eu-west-2.elasticbeanstalk.com": 1,
  "eu-west-3.elasticbeanstalk.com": 1,
  "eu.ax": 1,
  "eu.com": 1,
  "eu.encoway.cloud": 1,
  "eu.int": 1,
  "eu.meteorapp.com": 1,
  "eu.org": 1,
  "eu.platform.sh": 1,
  "eu.pythonanywhere.com": 1,
  "eun.eg": 1,
  "eurodir.ru": 1,
  "evenassi.no": 1,
  "evenes.no": 1,
  "evje-og-hornnes.no": 1,
  "ex.futurecms.at": 2,
  "ex.ortsinfo.at": 2,
  "exchange.aero": 1,
  "exeter.museum": 1,
  "exhibition.museum": 1,
  "exnet.su": 1,
  "experts-comptables.fr": 1,
  "express.aero": 1,
  "ezproxy.kuleuven.be": 1,
  "f.bg": 1,
  "f.se": 1,
  "fakefur.jp": 1,
  "fam.pk": 1,
  "family.museum": 1,
  "familyds.com": 1,
  "familyds.net": 1,
  "familyds.org": 1,
  "fantasyleague.cc": 1,
  "far.br": 1,
  "farm.museum": 1,
  "farmequipment.museum": 1,
  "farmers.museum": 1,
  "farmstead.museum": 1,
  "farsund.no": 1,
  "fashionstore.jp": 1,
  "fastly-terrarium.com": 1,
  "fastlylb.net": 1,
  "faststacks.net": 1,
  "fastvps-server.com": 1,
  "fastvps.host": 1,
  "fastvps.site": 1,
  "fauske.no": 1,
  "fbx-os.fr": 1,
  "fbxos.fr": 1,
  "fc.it": 1,
  "fe.it": 1,
  "fed.us": 1,
  "federation.aero": 1,
  "fedje.no": 1,
  "fedorainfracloud.org": 1,
  "fedorapeople.org": 1,
  "feira.br": 1,
  "fem.jp": 1,
  "fentiger.mythic-beasts.com": 1,
  "fermo.it": 1,
  "ferrara.it": 1,
  "feste-ip.net": 1,
  "fet.no": 1,
  "fetsund.no": 1,
  "fg.it": 1,
  "fh-muenster.io": 1,
  "fh.se": 1,
  "fhs.no": 1,
  "fhsk.se": 1,
  "fhv.se": 1,
  "fi.cloudplatform.fi": 1,
  "fi.cr": 1,
  "fi.eu.org": 1,
  "fi.it": 1,
  "fie.ee": 1,
  "field.museum": 1,
  "figueres.museum": 1,
  "filatelia.museum": 1,
  "filegear-au.me": 1,
  "filegear-de.me": 1,
  "filegear-gb.me": 1,
  "filegear-ie.me": 1,
  "filegear-jp.me": 1,
  "filegear-sg.me": 1,
  "filegear.me": 1,
  "film.hu": 1,
  "film.museum": 1,
  "fin.ci": 1,
  "fin.ec": 1,
  "fin.tn": 1,
  "fineart.museum": 1,
  "finearts.museum": 1,
  "finland.museum": 1,
  "finnoy.no": 1,
  "firebaseapp.com": 1,
  "firenet.ch": 2,
  "firenze.it": 1,
  "firewall-gateway.com": 1,
  "firewall-gateway.de": 1,
  "firewall-gateway.net": 1,
  "firewalledreplit.co": 1,
  "fireweb.app": 1,
  "firm.co": 1,
  "firm.dk": 1,
  "firm.ht": 1,
  "firm.in": 1,
  "firm.nf": 1,
  "firm.ng": 1,
  "firm.ro": 1,
  "firm.ve": 1,
  "fitjar.no": 1,
  "fj.cn": 1,
  "fjaler.no": 1,
  "fjell.no": 1,
  "fk": 2,
  "fl.us": 1,
  "fla.no": 1,
  "flakstad.no": 1,
  "flanders.museum": 1,
  "flap.id": 1,
  "flatanger.no": 1,
  "fldrv.com": 1,
  "flekkefjord.no": 1,
  "flesberg.no": 1,
  "flier.jp": 1,
  "flight.aero": 1,
  "flog.br": 1,
  "floppy.jp": 1,
  "flora.no": 1,
  "florence.it": 1,
  "florida.museum": 1,
  "floripa.br": 1,
  "floro.no": 1,
  "flt.cloud.muni.cz": 1,
  "fly.dev": 1,
  "flynnhosting.net": 1,
  "fm.br": 1,
  "fm.it": 1,
  "fm.no": 1,
  "fnc.fr-par.scw.cloud": 1,
  "fnd.br": 1,
  "fnwk.site": 1,
  "foggia.it": 1,
  "folionetwork.site": 1,
  "folkebibl.no": 1,
  "folldal.no": 1,
  "fool.jp": 1,
  "for-better.biz": 1,
  "for-more.biz": 1,
  "for-our.info": 1,
  "for-some.biz": 1,
  "for-the.biz": 1,
  "force.museum": 1,
  "forde.no": 1,
  "forgeblocks.com": 1,
  "forgot.her.name": 1,
  "forgot.his.name": 1,
  "forli-cesena.it": 1,
  "forlicesena.it": 1,
  "forsand.no": 1,
  "fortal.br": 1,
  "forte.id": 1,
  "fortmissoula.museum": 1,
  "fortworth.museum": 1,
  "forum.hu": 1,
  "forumz.info": 1,
  "fosnes.no": 1,
  "fot.br": 1,
  "foundation.museum": 1,
  "foz.br": 1,
  "fr-1.paas.massivegrid.net": 1,
  "fr-par-1.baremetal.scw.cloud": 1,
  "fr-par-2.baremetal.scw.cloud": 1,
  "fr.eu.org": 1,
  "fr.it": 1,
  "fra1-de.cloudjiffy.net": 1,
  "framer.app": 1,
  "framer.media": 1,
  "framer.photos": 1,
  "framer.website": 1,
  "framer.wiki": 1,
  "framercanvas.com": 1,
  "frana.no": 1,
  "francaise.museum": 1,
  "frankfurt.museum": 1,
  "franziskaner.museum": 1,
  "fredrikstad.no": 1,
  "free.hr": 1,
  "freebox-os.com": 1,
  "freebox-os.fr": 1,
  "freeboxos.com": 1,
  "freeboxos.fr": 1,
  "freeddns.org": 1,
  "freeddns.us": 1,
  "freedesktop.org": 1,
  "freemasonry.museum": 1,
  "freemyip.com": 1,
  "freesite.host": 1,
  "freetls.fastly.net": 1,
  "frei.no": 1,
  "freiburg.museum": 1,
  "frenchkiss.jp": 1,
  "fribourg.museum": 1,
  "friuli-v-giulia.it": 1,
  "friuli-ve-giulia.it": 1,
  "friuli-vegiulia.it": 1,
  "friuli-venezia-giulia.it": 1,
  "friuli-veneziagiulia.it": 1,
  "friuli-vgiulia.it": 1,
  "friuliv-giulia.it": 1,
  "friulive-giulia.it": 1,
  "friulivegiulia.it": 1,
  "friulivenezia-giulia.it": 1,
  "friuliveneziagiulia.it": 1,
  "friulivgiulia.it": 1,
  "frog.museum": 1,
  "frogn.no": 1,
  "froland.no": 1,
  "from-ak.com": 1,
  "from-al.com": 1,
  "from-ar.com": 1,
  "from-az.net": 1,
  "from-ca.com": 1,
  "from-co.net": 1,
  "from-ct.com": 1,
  "from-dc.com": 1,
  "from-de.com": 1,
  "from-fl.com": 1,
  "from-ga.com": 1,
  "from-hi.com": 1,
  "from-ia.com": 1,
  "from-id.com": 1,
  "from-il.com": 1,
  "from-in.com": 1,
  "from-ks.com": 1,
  "from-ky.com": 1,
  "from-la.net": 1,
  "from-ma.com": 1,
  "from-md.com": 1,
  "from-me.org": 1,
  "from-mi.com": 1,
  "from-mn.com": 1,
  "from-mo.com": 1,
  "from-ms.com": 1,
  "from-mt.com": 1,
  "from-nc.com": 1,
  "from-nd.com": 1,
  "from-ne.com": 1,
  "from-nh.com": 1,
  "from-nj.com": 1,
  "from-nm.com": 1,
  "from-nv.com": 1,
  "from-ny.net": 1,
  "from-oh.com": 1,
  "from-ok.com": 1,
  "from-or.com": 1,
  "from-pa.com": 1,
  "from-pr.com": 1,
  "from-ri.com": 1,
  "from-sc.com": 1,
  "from-sd.com": 1,
  "from-tn.com": 1,
  "from-tx.com": 1,
  "from-ut.com": 1,
  "from-va.com": 1,
  "from-vt.com": 1,
  "from-wa.com": 1,
  "from-wi.com": 1,
  "from-wv.com": 1,
  "from-wy.com": 1,
  "from.hr": 1,
  "frosinone.it": 1,
  "frosta.no": 1,
  "froya.no": 1,
  "frusky.de": 2,
  "fst.br": 1,
  "ftpaccess.cc": 1,
  "fuchu.hiroshima.jp": 1,
  "fuchu.tokyo.jp": 1,
  "fuchu.toyama.jp": 1,
  "fudai.iwate.jp": 1,
  "fuefuki.yamanashi.jp": 1,
  "fuel.aero": 1,
  "fuettertdasnetz.de": 1,
  "fuji.shizuoka.jp": 1,
  "fujieda.shizuoka.jp": 1,
  "fujiidera.osaka.jp": 1,
  "fujikawa.shizuoka.jp": 1,
  "fujikawa.yamanashi.jp": 1,
  "fujikawaguchiko.yamanashi.jp": 1,
  "fujimi.nagano.jp": 1,
  "fujimi.saitama.jp": 1,
  "fujimino.saitama.jp": 1,
  "fujinomiya.shizuoka.jp": 1,
  "fujioka.gunma.jp": 1,
  "fujisato.akita.jp": 1,
  "fujisawa.iwate.jp": 1,
  "fujisawa.kanagawa.jp": 1,
  "fujishiro.ibaraki.jp": 1,
  "fujiyoshida.yamanashi.jp": 1,
  "fukagawa.hokkaido.jp": 1,
  "fukaya.saitama.jp": 1,
  "fukuchi.fukuoka.jp": 1,
  "fukuchiyama.kyoto.jp": 1,
  "fukudomi.saga.jp": 1,
  "fukui.fukui.jp": 1,
  "fukui.jp": 1,
  "fukumitsu.toyama.jp": 1,
  "fukuoka.jp": 1,
  "fukuroi.shizuoka.jp": 1,
  "fukusaki.hyogo.jp": 1,
  "fukushima.fukushima.jp": 1,
  "fukushima.hokkaido.jp": 1,
  "fukushima.jp": 1,
  "fukuyama.hiroshima.jp": 1,
  "funabashi.chiba.jp": 1,
  "funagata.yamagata.jp": 1,
  "funahashi.toyama.jp": 1,
  "functions.fnc.fr-par.scw.cloud": 1,
  "fundacio.museum": 1,
  "fuoisku.no": 1,
  "fuossko.no": 1,
  "furano.hokkaido.jp": 1,
  "furniture.museum": 1,
  "furubira.hokkaido.jp": 1,
  "furudono.fukushima.jp": 1,
  "furukawa.miyagi.jp": 1,
  "fusa.no": 1,
  "fuso.aichi.jp": 1,
  "fussa.tokyo.jp": 1,
  "futaba.fukushima.jp": 1,
  "futsu.nagasaki.jp": 1,
  "futtsu.chiba.jp": 1,
  "futurecms.at": 2,
  "futurehosting.at": 1,
  "futuremailing.at": 1,
  "fvg.it": 1,
  "fylkesbibl.no": 1,
  "fyresdal.no": 1,
  "g.bg": 1,
  "g.se": 1,
  "g.vbrplsbx.io": 1,
  "g12.br": 1,
  "ga.us": 1,
  "gaivuotna.no": 1,
  "gallery.museum": 1,
  "galsa.no": 1,
  "gamagori.aichi.jp": 1,
  "game-host.org": 1,
  "game-server.cc": 1,
  "game.tw": 1,
  "games.hu": 1,
  "gamo.shiga.jp": 1,
  "gamvik.no": 1,
  "gangaviika.no": 1,
  "gangwon.kr": 1,
  "garden.museum": 1,
  "gateway.dev": 2,
  "gateway.museum": 1,
  "gaular.no": 1,
  "gausdal.no": 1,
  "gb.net": 1,
  "gc.ca": 1,
  "gd.cn": 1,
  "gda.pl": 1,
  "gdansk.pl": 1,
  "gdynia.pl": 1,
  "ge.it": 1,
  "geek.nz": 1,
  "geekgalaxy.com": 1,
  "geelvinck.museum": 1,
  "gehirn.ne.jp": 1,
  "geisei.kochi.jp": 1,
  "gemological.museum": 1,
  "gen.in": 1,
  "gen.mi.us": 1,
  "gen.ng": 1,
  "gen.nz": 1,
  "gen.tr": 1,
  "genkai.saga.jp": 1,
  "genoa.it": 1,
  "genova.it": 1,
  "gentapps.com": 1,
  "gentlentapis.com": 1,
  "geo.br": 1,
  "geology.museum": 1,
  "geometre-expert.fr": 1,
  "georgia.museum": 1,
  "georgia.su": 1,
  "getmyip.com": 1,
  "gets-it.net": 1,
  "gg.ax": 1,
  "ggf.br": 1,
  "ghost.io": 1,
  "giehtavuoatna.no": 1,
  "giessen.museum": 1,
  "gifu.gifu.jp": 1,
  "gifu.jp": 1,
  "giize.com": 1,
  "gildeskal.no": 1,
  "ginan.gifu.jp": 1,
  "ginowan.okinawa.jp": 1,
  "ginoza.okinawa.jp": 1,
  "girlfriend.jp": 1,
  "girly.jp": 1,
  "giske.no": 1,
  "git-pages.rit.edu": 1,
  "git-repos.de": 1,
  "gitapp.si": 1,
  "github.io": 1,
  "githubpreview.dev": 1,
  "githubusercontent.com": 1,
  "gitlab.io": 1,
  "gitpage.si": 1,
  "gjemnes.no": 1,
  "gjerdrum.no": 1,
  "gjerstad.no": 1,
  "gjesdal.no": 1,
  "gjovik.no": 1,
  "glas.museum": 1,
  "glass.museum": 1,
  "gleeze.com": 1,
  "gliding.aero": 1,
  "glitch.me": 1,
  "gliwice.pl": 1,
  "global.prod.fastly.net": 1,
  "global.ssl.fastly.net": 1,
  "glogow.pl": 1,
  "gloomy.jp": 1,
  "gloppen.no": 1,
  "glug.org.uk": 1,
  "gmina.pl": 1,
  "gniezno.pl": 1,
  "go.ci": 1,
  "go.cr": 1,
  "go.dyndns.org": 1,
  "go.gov.br": 1,
  "go.id": 1,
  "go.it": 1,
  "go.jp": 1,
  "go.ke": 1,
  "go.kr": 1,
  "go.leg.br": 1,
  "go.pw": 1,
  "go.th": 1,
  "go.tj": 1,
  "go.tz": 1,
  "go.ug": 1,
  "gob.ar": 1,
  "gob.bo": 1,
  "gob.cl": 1,
  "gob.do": 1,
  "gob.ec": 1,
  "gob.es": 1,
  "gob.gt": 1,
  "gob.hn": 1,
  "gob.mx": 1,
  "gob.ni": 1,
  "gob.pa": 1,
  "gob.pe": 1,
  "gob.pk": 1,
  "gob.sv": 1,
  "gob.ve": 1,
  "gobo.wakayama.jp": 1,
  "godo.gifu.jp": 1,
  "goiania.br": 1,
  "goip.de": 1,
  "gojome.akita.jp": 1,
  "gok.pk": 1,
  "gokase.miyazaki.jp": 1,
  "gol.no": 1,
  "golffan.us": 1,
  "gon.pk": 1,
  "gonna.jp": 1,
  "gonohe.aomori.jp": 1,
  "googleapis.com": 1,
  "googlecode.com": 1,
  "gop.pk": 1,
  "gorge.museum": 1,
  "gorizia.it": 1,
  "gorlice.pl": 1,
  "gos.pk": 1,
  "gose.nara.jp": 1,
  "gosen.niigata.jp": 1,
  "goshiki.hyogo.jp": 1,
  "gotdns.ch": 1,
  "gotdns.com": 1,
  "gotdns.org": 1,
  "gotemba.shizuoka.jp": 1,
  "goto.nagasaki.jp": 1,
  "gotpantheon.com": 1,
  "gotsu.shimane.jp": 1,
  "goupile.fr": 1,
  "gouv.bj": 1,
  "gouv.ci": 1,
  "gouv.fr": 1,
  "gouv.ht": 1,
  "gouv.km": 1,
  "gouv.ml": 1,
  "gouv.sn": 1,
  "gov.ac": 1,
  "gov.ae": 1,
  "gov.af": 1,
  "gov.al": 1,
  "gov.ar": 1,
  "gov.as": 1,
  "gov.au": 1,
  "gov.az": 1,
  "gov.ba": 1,
  "gov.bb": 1,
  "gov.bf": 1,
  "gov.bh": 1,
  "gov.bm": 1,
  "gov.bn": 1,
  "gov.br": 1,
  "gov.bs": 1,
  "gov.bt": 1,
  "gov.by": 1,
  "gov.bz": 1,
  "gov.cd": 1,
  "gov.cl": 1,
  "gov.cm": 1,
  "gov.cn": 1,
  "gov.co": 1,
  "gov.cu": 1,
  "gov.cx": 1,
  "gov.cy": 1,
  "gov.dm": 1,
  "gov.do": 1,
  "gov.dz": 1,
  "gov.ec": 1,
  "gov.ee": 1,
  "gov.eg": 1,
  "gov.et": 1,
  "gov.fj": 1,
  "gov.gd": 1,
  "gov.ge": 1,
  "gov.gh": 1,
  "gov.gi": 1,
  "gov.gn": 1,
  "gov.gr": 1,
  "gov.gu": 1,
  "gov.gy": 1,
  "gov.hk": 1,
  "gov.ie": 1,
  "gov.il": 1,
  "gov.in": 1,
  "gov.iq": 1,
  "gov.ir": 1,
  "gov.is": 1,
  "gov.it": 1,
  "gov.jo": 1,
  "gov.kg": 1,
  "gov.ki": 1,
  "gov.km": 1,
  "gov.kn": 1,
  "gov.kp": 1,
  "gov.kw": 1,
  "gov.kz": 1,
  "gov.la": 1,
  "gov.lb": 1,
  "gov.lc": 1,
  "gov.lk": 1,
  "gov.lr": 1,
  "gov.ls": 1,
  "gov.lt": 1,
  "gov.lv": 1,
  "gov.ly": 1,
  "gov.ma": 1,
  "gov.me": 1,
  "gov.mg": 1,
  "gov.mk": 1,
  "gov.ml": 1,
  "gov.mn": 1,
  "gov.mo": 1,
  "gov.mr": 1,
  "gov.ms": 1,
  "gov.mu": 1,
  "gov.mv": 1,
  "gov.mw": 1,
  "gov.my": 1,
  "gov.mz": 1,
  "gov.nc.tr": 1,
  "gov.ng": 1,
  "gov.nl": 1,
  "gov.nr": 1,
  "gov.om": 1,
  "gov.ph": 1,
  "gov.pk": 1,
  "gov.pl": 1,
  "gov.pn": 1,
  "gov.pr": 1,
  "gov.ps": 1,
  "gov.pt": 1,
  "gov.py": 1,
  "gov.qa": 1,
  "gov.rs": 1,
  "gov.ru": 1,
  "gov.rw": 1,
  "gov.sa": 1,
  "gov.sb": 1,
  "gov.sc": 1,
  "gov.scot": 1,
  "gov.sd": 1,
  "gov.sg": 1,
  "gov.sh": 1,
  "gov.sl": 1,
  "gov.so": 1,
  "gov.ss": 1,
  "gov.sx": 1,
  "gov.sy": 1,
  "gov.tj": 1,
  "gov.tl": 1,
  "gov.tm": 1,
  "gov.tn": 1,
  "gov.to": 1,
  "gov.tr": 1,
  "gov.tt": 1,
  "gov.tw": 1,
  "gov.ua": 1,
  "gov.uk": 1,
  "gov.vc": 1,
  "gov.ve": 1,
  "gov.vn": 1,
  "gov.ws": 1,
  "gov.ye": 1,
  "gov.za": 1,
  "gov.zm": 1,
  "gov.zw": 1,
  "government.aero": 1,
  "govt.nz": 1,
  "gr.com": 1,
  "gr.eu.org": 1,
  "gr.it": 1,
  "gr.jp": 1,
  "grajewo.pl": 1,
  "gran.no": 1,
  "grandrapids.museum": 1,
  "grane.no": 1,
  "granvin.no": 1,
  "graphox.us": 1,
  "gratangen.no": 1,
  "graz.museum": 1,
  "greater.jp": 1,
  "greta.fr": 1,
  "grimstad.no": 1,
  "griw.gov.pl": 1,
  "groks-the.info": 1,
  "groks-this.info": 1,
  "grondar.za": 1,
  "grong.no": 1,
  "grosseto.it": 1,
  "groundhandling.aero": 1,
  "group.aero": 1,
  "grozny.ru": 1,
  "grozny.su": 1,
  "grp.lk": 1,
  "gru.br": 1,
  "grue.no": 1,
  "gs.aa.no": 1,
  "gs.ah.no": 1,
  "gs.bu.no": 1,
  "gs.cn": 1,
  "gs.fm.no": 1,
  "gs.hl.no": 1,
  "gs.hm.no": 1,
  "gs.jan-mayen.no": 1,
  "gs.mr.no": 1,
  "gs.nl.no": 1,
  "gs.nt.no": 1,
  "gs.of.no": 1,
  "gs.ol.no": 1,
  "gs.oslo.no": 1,
  "gs.rl.no": 1,
  "gs.sf.no": 1,
  "gs.st.no": 1,
  "gs.svalbard.no": 1,
  "gs.tm.no": 1,
  "gs.tr.no": 1,
  "gs.va.no": 1,
  "gs.vf.no": 1,
  "gsj.bz": 1,
  "gsm.pl": 1,
  "gu.us": 1,
  "guam.gu": 1,
  "gub.uy": 1,
  "guernsey.museum": 1,
  "gujarat.in": 1,
  "gujo.gifu.jp": 1,
  "gulen.no": 1,
  "gunma.jp": 1,
  "guovdageaidnu.no": 1,
  "gushikami.okinawa.jp": 1,
  "gv.ao": 1,
  "gv.at": 1,
  "gv.vc": 1,
  "gwangju.kr": 1,
  "gx.cn": 1,
  "gyeongbuk.kr": 1,
  "gyeonggi.kr": 1,
  "gyeongnam.kr": 1,
  "gyokuto.kumamoto.jp": 1,
  "gz.cn": 1,
  "h.bg": 1,
  "h.se": 1,
  "ha.cn": 1,
  "ha.no": 1,
  "habikino.osaka.jp": 1,
  "habmer.no": 1,
  "haboro.hokkaido.jp": 1,
  "hacca.jp": 1,
  "hachijo.tokyo.jp": 1,
  "hachinohe.aomori.jp": 1,
  "hachioji.tokyo.jp": 1,
  "hachirogata.akita.jp": 1,
  "hadano.kanagawa.jp": 1,
  "hadsel.no": 1,
  "haebaru.okinawa.jp": 1,
  "haga.tochigi.jp": 1,
  "hagebostad.no": 1,
  "hagi.yamaguchi.jp": 1,
  "haibara.shizuoka.jp": 1,
  "hakata.fukuoka.jp": 1,
  "hakodate.hokkaido.jp": 1,
  "hakone.kanagawa.jp": 1,
  "hakuba.nagano.jp": 1,
  "hakui.ishikawa.jp": 1,
  "hakusan.ishikawa.jp": 1,
  "halden.no": 1,
  "half.host": 1,
  "halloffame.museum": 1,
  "halsa.no": 1,
  "ham-radio-op.net": 1,
  "hamada.shimane.jp": 1,
  "hamamatsu.shizuoka.jp": 1,
  "hamar.no": 1,
  "hamaroy.no": 1,
  "hamatama.saga.jp": 1,
  "hamatonbetsu.hokkaido.jp": 1,
  "hamburg.museum": 1,
  "hammarfeasta.no": 1,
  "hammerfest.no": 1,
  "hamura.tokyo.jp": 1,
  "hanamaki.iwate.jp": 1,
  "hanamigawa.chiba.jp": 1,
  "hanawa.fukushima.jp": 1,
  "handa.aichi.jp": 1,
  "handcrafted.jp": 1,
  "handson.museum": 1,
  "hanggliding.aero": 1,
  "hannan.osaka.jp": 1,
  "hanno.saitama.jp": 1,
  "hanyu.saitama.jp": 1,
  "hapmir.no": 1,
  "happou.akita.jp": 1,
  "hara.nagano.jp": 1,
  "haram.no": 1,
  "hareid.no": 1,
  "harima.hyogo.jp": 1,
  "harstad.no": 1,
  "harvestcelebration.museum": 1,
  "hasama.oita.jp": 1,
  "hasami.nagasaki.jp": 1,
  "hashbang.sh": 1,
  "hashikami.aomori.jp": 1,
  "hashima.gifu.jp": 1,
  "hashimoto.wakayama.jp": 1,
  "hasuda.saitama.jp": 1,
  "hasura-app.io": 1,
  "hasura.app": 1,
  "hasvik.no": 1,
  "hatogaya.saitama.jp": 1,
  "hatoyama.saitama.jp": 1,
  "hatsukaichi.hiroshima.jp": 1,
  "hattfjelldal.no": 1,
  "haugesund.no": 1,
  "hawaii.museum": 1,
  "hayakawa.yamanashi.jp": 1,
  "hayashima.okayama.jp": 1,
  "hazu.aichi.jp": 1,
  "hb.cldmail.ru": 1,
  "hb.cn": 1,
  "he.cn": 1,
  "health-carereform.com": 1,
  "health.museum": 1,
  "health.nz": 1,
  "health.vn": 1,
  "heavy.jp": 1,
  "heguri.nara.jp": 1,
  "heimatunduhren.museum": 1,
  "hekinan.aichi.jp": 1,
  "hellas.museum": 1,
  "helsinki.museum": 1,
  "hembygdsforbund.museum": 1,
  "hemne.no": 1,
  "hemnes.no": 1,
  "hemsedal.no": 1,
  "hepforge.org": 1,
  "her.jp": 1,
  "herad.no": 1,
  "here-for-more.info": 1,
  "heritage.museum": 1,
  "herokuapp.com": 1,
  "herokussl.com": 1,
  "heroy.more-og-romsdal.no": 1,
  "heroy.nordland.no": 1,
  "heteml.net": 1,
  "hi.cn": 1,
  "hi.us": 1,
  "hicam.net": 1,
  "hichiso.gifu.jp": 1,
  "hida.gifu.jp": 1,
  "hidaka.hokkaido.jp": 1,
  "hidaka.kochi.jp": 1,
  "hidaka.saitama.jp": 1,
  "hidaka.wakayama.jp": 1,
  "hidora.com": 1,
  "higashi.fukuoka.jp": 1,
  "higashi.fukushima.jp": 1,
  "higashi.okinawa.jp": 1,
  "higashiagatsuma.gunma.jp": 1,
  "higashichichibu.saitama.jp": 1,
  "higashihiroshima.hiroshima.jp": 1,
  "higashiizu.shizuoka.jp": 1,
  "higashiizumo.shimane.jp": 1,
  "higashikagawa.kagawa.jp": 1,
  "higashikagura.hokkaido.jp": 1,
  "higashikawa.hokkaido.jp": 1,
  "higashikurume.tokyo.jp": 1,
  "higashimatsushima.miyagi.jp": 1,
  "higashimatsuyama.saitama.jp": 1,
  "higashimurayama.tokyo.jp": 1,
  "higashinaruse.akita.jp": 1,
  "higashine.yamagata.jp": 1,
  "higashiomi.shiga.jp": 1,
  "higashiosaka.osaka.jp": 1,
  "higashishirakawa.gifu.jp": 1,
  "higashisumiyoshi.osaka.jp": 1,
  "higashitsuno.kochi.jp": 1,
  "higashiura.aichi.jp": 1,
  "higashiyama.kyoto.jp": 1,
  "higashiyamato.tokyo.jp": 1,
  "higashiyodogawa.osaka.jp": 1,
  "higashiyoshino.nara.jp": 1,
  "hiho.jp": 1,
  "hiji.oita.jp": 1,
  "hikari.yamaguchi.jp": 1,
  "hikawa.shimane.jp": 1,
  "hikimi.shimane.jp": 1,
  "hikone.shiga.jp": 1,
  "himeji.hyogo.jp": 1,
  "himeshima.oita.jp": 1,
  "himi.toyama.jp": 1,
  "hino.tokyo.jp": 1,
  "hino.tottori.jp": 1,
  "hinode.tokyo.jp": 1,
  "hinohara.tokyo.jp": 1,
  "hioki.kagoshima.jp": 1,
  "hippy.jp": 1,
  "hirado.nagasaki.jp": 1,
  "hiraizumi.iwate.jp": 1,
  "hirakata.osaka.jp": 1,
  "hiranai.aomori.jp": 1,
  "hirara.okinawa.jp": 1,
  "hirata.fukushima.jp": 1,
  "hiratsuka.kanagawa.jp": 1,
  "hiraya.nagano.jp": 1,
  "hirogawa.wakayama.jp": 1,
  "hirokawa.fukuoka.jp": 1,
  "hirono.fukushima.jp": 1,
  "hirono.iwate.jp": 1,
  "hiroo.hokkaido.jp": 1,
  "hirosaki.aomori.jp": 1,
  "hiroshima.jp": 1,
  "hisayama.fukuoka.jp": 1,
  "histoire.museum": 1,
  "historical.museum": 1,
  "historicalsociety.museum": 1,
  "historichouses.museum": 1,
  "historisch.museum": 1,
  "historisches.museum": 1,
  "history.museum": 1,
  "historyofscience.museum": 1,
  "hita.oita.jp": 1,
  "hitachi.ibaraki.jp": 1,
  "hitachinaka.ibaraki.jp": 1,
  "hitachiomiya.ibaraki.jp": 1,
  "hitachiota.ibaraki.jp": 1,
  "hitra.no": 1,
  "hizen.saga.jp": 1,
  "hjartdal.no": 1,
  "hjelmeland.no": 1,
  "hk.cn": 1,
  "hk.com": 1,
  "hk.org": 1,
  "hl.cn": 1,
  "hl.no": 1,
  "hlx.live": 1,
  "hlx.page": 1,
  "hlx3.page": 1,
  "hm.no": 1,
  "hn.cn": 1,
  "hobby-site.com": 1,
  "hobby-site.org": 1,
  "hobol.no": 1,
  "hof.no": 1,
  "hofu.yamaguchi.jp": 1,
  "hokkaido.jp": 1,
  "hokksund.no": 1,
  "hokuryu.hokkaido.jp": 1,
  "hokuto.hokkaido.jp": 1,
  "hokuto.yamanashi.jp": 1,
  "hol.no": 1,
  "hole.no": 1,
  "holmestrand.no": 1,
  "holtalen.no": 1,
  "holy.jp": 1,
  "home-webserver.de": 1,
  "home.dyndns.org": 1,
  "homebuilt.aero": 1,
  "homedns.org": 1,
  "homeftp.net": 1,
  "homeftp.org": 1,
  "homeip.net": 1,
  "homelink.one": 1,
  "homelinux.com": 1,
  "homelinux.net": 1,
  "homelinux.org": 1,
  "homeoffice.gov.uk": 1,
  "homesecuritymac.com": 1,
  "homesecuritypc.com": 1,
  "homesklep.pl": 1,
  "homeunix.com": 1,
  "homeunix.net": 1,
  "homeunix.org": 1,
  "honai.ehime.jp": 1,
  "honbetsu.hokkaido.jp": 1,
  "honefoss.no": 1,
  "hongo.hiroshima.jp": 1,
  "honjo.akita.jp": 1,
  "honjo.saitama.jp": 1,
  "honjyo.akita.jp": 1,
  "hoplix.shop": 1,
  "hopto.me": 1,
  "hopto.org": 1,
  "hornindal.no": 1,
  "horokanai.hokkaido.jp": 1,
  "horology.museum": 1,
  "horonobe.hokkaido.jp": 1,
  "horten.no": 1,
  "hosp.uk": 1,
  "hostedpi.com": 1,
  "hosting-cluster.nl": 1,
  "hosting.myjino.ru": 2,
  "hosting.ovh.net": 2,
  "hostyhosting.io": 1,
  "hotel.hu": 1,
  "hotel.lk": 1,
  "hotel.tz": 1,
  "hotelwithflight.com": 1,
  "house.museum": 1,
  "hoyanger.no": 1,
  "hoylandet.no": 1,
  "hr.eu.org": 1,
  "hra.health": 1,
  "hs.kr": 1,
  "hs.run": 1,
  "hs.zone": 1,
  "httpbin.org": 1,
  "hu.com": 1,
  "hu.eu.org": 1,
  "hu.net": 1,
  "huissier-justice.fr": 1,
  "humanities.museum": 1,
  "hungry.jp": 1,
  "hurdal.no": 1,
  "hurum.no": 1,
  "hvaler.no": 1,
  "hyllestad.no": 1,
  "hyogo.jp": 1,
  "hyuga.miyazaki.jp": 1,
  "hzc.io": 1,
  "i.bg": 1,
  "i.ng": 1,
  "i.ph": 1,
  "i.se": 1,
  "i234.me": 1,
  "ia.us": 1,
  "iamallama.com": 1,
  "ibara.okayama.jp": 1,
  "ibaraki.ibaraki.jp": 1,
  "ibaraki.jp": 1,
  "ibaraki.osaka.jp": 1,
  "ibestad.no": 1,
  "ibigawa.gifu.jp": 1,
  "ibxos.it": 1,
  "ic.gov.pl": 1,
  "ichiba.tokushima.jp": 1,
  "ichihara.chiba.jp": 1,
  "ichikai.tochigi.jp": 1,
  "ichikawa.chiba.jp": 1,
  "ichikawa.hyogo.jp": 1,
  "ichikawamisato.yamanashi.jp": 1,
  "ichinohe.iwate.jp": 1,
  "ichinomiya.aichi.jp": 1,
  "ichinomiya.chiba.jp": 1,
  "ichinoseki.iwate.jp": 1,
  "icurus.jp": 1,
  "id.au": 1,
  "id.firewalledreplit.co": 1,
  "id.forgerock.io": 1,
  "id.ir": 1,
  "id.lv": 1,
  "id.ly": 1,
  "id.repl.co": 1,
  "id.us": 1,
  "ide.kyoto.jp": 1,
  "idf.il": 1,
  "idrett.no": 1,
  "idv.hk": 1,
  "idv.tw": 1,
  "ie.eu.org": 1,
  "if.ua": 1,
  "iglesias-carbonia.it": 1,
  "iglesiascarbonia.it": 1,
  "iheya.okinawa.jp": 1,
  "iida.nagano.jp": 1,
  "iide.yamagata.jp": 1,
  "iijima.nagano.jp": 1,
  "iitate.fukushima.jp": 1,
  "iiyama.nagano.jp": 1,
  "iizuka.fukuoka.jp": 1,
  "iizuna.nagano.jp": 1,
  "ikaruga.nara.jp": 1,
  "ikata.ehime.jp": 1,
  "ikawa.akita.jp": 1,
  "ikeda.fukui.jp": 1,
  "ikeda.gifu.jp": 1,
  "ikeda.hokkaido.jp": 1,
  "ikeda.nagano.jp": 1,
  "ikeda.osaka.jp": 1,
  "iki.fi": 1,
  "iki.nagasaki.jp": 1,
  "ikoma.nara.jp": 1,
  "ikusaka.nagano.jp": 1,
  "il.eu.org": 1,
  "il.us": 1,
  "ilawa.pl": 1,
  "iliadboxos.it": 1,
  "illustration.museum": 1,
  "ilovecollege.info": 1,
  "im.it": 1,
  "imabari.ehime.jp": 1,
  "imageandsound.museum": 1,
  "imakane.hokkaido.jp": 1,
  "imari.saga.jp": 1,
  "imb.br": 1,
  "imizu.toyama.jp": 1,
  "imperia.it": 1,
  "impertrix.com": 1,
  "impertrixcdn.com": 1,
  "in-addr.arpa": 1,
  "in-berlin.de": 1,
  "in-brb.de": 1,
  "in-butter.de": 1,
  "in-dsl.de": 1,
  "in-dsl.net": 1,
  "in-dsl.org": 1,
  "in-the-band.net": 1,
  "in-vpn.de": 1,
  "in-vpn.net": 1,
  "in-vpn.org": 1,
  "in.eu.org": 1,
  "in.futurecms.at": 2,
  "in.na": 1,
  "in.net": 1,
  "in.ni": 1,
  "in.rs": 1,
  "in.th": 1,
  "in.ua": 1,
  "in.us": 1,
  "ina.ibaraki.jp": 1,
  "ina.nagano.jp": 1,
  "ina.saitama.jp": 1,
  "inabe.mie.jp": 1,
  "inagawa.hyogo.jp": 1,
  "inagi.tokyo.jp": 1,
  "inami.toyama.jp": 1,
  "inami.wakayama.jp": 1,
  "inashiki.ibaraki.jp": 1,
  "inatsuki.fukuoka.jp": 1,
  "inawashiro.fukushima.jp": 1,
  "inazawa.aichi.jp": 1,
  "inc.hk": 1,
  "incheon.kr": 1,
  "ind.br": 1,
  "ind.gt": 1,
  "ind.in": 1,
  "ind.kw": 1,
  "ind.tn": 1,
  "independent-commission.uk": 1,
  "independent-inquest.uk": 1,
  "independent-inquiry.uk": 1,
  "independent-panel.uk": 1,
  "independent-review.uk": 1,
  "inderoy.no": 1,
  "indian.museum": 1,
  "indiana.museum": 1,
  "indianapolis.museum": 1,
  "indianmarket.museum": 1,
  "indie.porn": 1,
  "indigena.bo": 1,
  "industria.bo": 1,
  "ine.kyoto.jp": 1,
  "inf.br": 1,
  "inf.cu": 1,
  "inf.mk": 1,
  "inf.ua": 1,
  "info.at": 1,
  "info.au": 1,
  "info.az": 1,
  "info.bb": 1,
  "info.bo": 1,
  "info.co": 1,
  "info.cx": 1,
  "info.ec": 1,
  "info.et": 1,
  "info.fj": 1,
  "info.gu": 1,
  "info.ht": 1,
  "info.hu": 1,
  "info.in": 1,
  "info.ke": 1,
  "info.ki": 1,
  "info.la": 1,
  "info.ls": 1,
  "info.mv": 1,
  "info.na": 1,
  "info.nf": 1,
  "info.ni": 1,
  "info.nr": 1,
  "info.pk": 1,
  "info.pl": 1,
  "info.pr": 1,
  "info.ro": 1,
  "info.sd": 1,
  "info.tn": 1,
  "info.tr": 1,
  "info.tt": 1,
  "info.tz": 1,
  "info.ve": 1,
  "info.vn": 1,
  "info.zm": 1,
  "ing.pa": 1,
  "ingatlan.hu": 1,
  "ino.kochi.jp": 1,
  "instance.datadetect.com": 1,
  "instances.spawn.cc": 1,
  "instantcloud.cn": 1,
  "insurance.aero": 1,
  "int.ar": 1,
  "int.az": 1,
  "int.bo": 1,
  "int.ci": 1,
  "int.co": 1,
  "int.cv": 1,
  "int.eu.org": 1,
  "int.in": 1,
  "int.is": 1,
  "int.la": 1,
  "int.lk": 1,
  "int.mv": 1,
  "int.mw": 1,
  "int.ni": 1,
  "int.pt": 1,
  "int.ru": 1,
  "int.tj": 1,
  "int.tt": 1,
  "int.ve": 1,
  "int.vn": 1,
  "intelligence.museum": 1,
  "interactive.museum": 1,
  "internet-dns.de": 1,
  "internet.in": 1,
  "intl.tn": 1,
  "inuyama.aichi.jp": 1,
  "inzai.chiba.jp": 1,
  "io.in": 1,
  "io.kg": 1,
  "iobb.net": 1,
  "iopsys.se": 1,
  "ip.linodeusercontent.com": 1,
  "ip6.arpa": 1,
  "ipifony.net": 1,
  "iraq.museum": 1,
  "iris.arpa": 1,
  "iron.museum": 1,
  "iruma.saitama.jp": 1,
  "is-a-anarchist.com": 1,
  "is-a-blogger.com": 1,
  "is-a-bookkeeper.com": 1,
  "is-a-bruinsfan.org": 1,
  "is-a-bulls-fan.com": 1,
  "is-a-candidate.org": 1,
  "is-a-caterer.com": 1,
  "is-a-celticsfan.org": 1,
  "is-a-chef.com": 1,
  "is-a-chef.net": 1,
  "is-a-chef.org": 1,
  "is-a-conservative.com": 1,
  "is-a-cpa.com": 1,
  "is-a-cubicle-slave.com": 1,
  "is-a-democrat.com": 1,
  "is-a-designer.com": 1,
  "is-a-doctor.com": 1,
  "is-a-financialadvisor.com": 1,
  "is-a-geek.com": 1,
  "is-a-geek.net": 1,
  "is-a-geek.org": 1,
  "is-a-green.com": 1,
  "is-a-guru.com": 1,
  "is-a-hard-worker.com": 1,
  "is-a-hunter.com": 1,
  "is-a-knight.org": 1,
  "is-a-landscaper.com": 1,
  "is-a-lawyer.com": 1,
  "is-a-liberal.com": 1,
  "is-a-libertarian.com": 1,
  "is-a-linux-user.org": 1,
  "is-a-llama.com": 1,
  "is-a-musician.com": 1,
  "is-a-nascarfan.com": 1,
  "is-a-nurse.com": 1,
  "is-a-painter.com": 1,
  "is-a-patsfan.org": 1,
  "is-a-personaltrainer.com": 1,
  "is-a-photographer.com": 1,
  "is-a-player.com": 1,
  "is-a-republican.com": 1,
  "is-a-rockstar.com": 1,
  "is-a-socialist.com": 1,
  "is-a-soxfan.org": 1,
  "is-a-student.com": 1,
  "is-a-teacher.com": 1,
  "is-a-techie.com": 1,
  "is-a-therapist.com": 1,
  "is-an-accountant.com": 1,
  "is-an-actor.com": 1,
  "is-an-actress.com": 1,
  "is-an-anarchist.com": 1,
  "is-an-artist.com": 1,
  "is-an-engineer.com": 1,
  "is-an-entertainer.com": 1,
  "is-by.us": 1,
  "is-certified.com": 1,
  "is-found.org": 1,
  "is-gone.com": 1,
  "is-into-anime.com": 1,
  "is-into-cars.com": 1,
  "is-into-cartoons.com": 1,
  "is-into-games.com": 1,
  "is-leet.com": 1,
  "is-lost.org": 1,
  "is-not-certified.com": 1,
  "is-saved.org": 1,
  "is-slick.com": 1,
  "is-uberleet.com": 1,
  "is-very-bad.org": 1,
  "is-very-evil.org": 1,
  "is-very-good.org": 1,
  "is-very-nice.org": 1,
  "is-very-sweet.org": 1,
  "is-with-theband.com": 1,
  "is.eu.org": 1,
  "is.gov.pl": 1,
  "is.it": 1,
  "isa-geek.com": 1,
  "isa-geek.net": 1,
  "isa-geek.org": 1,
  "isa-hockeynut.com": 1,
  "isa.kagoshima.jp": 1,
  "isa.us": 1,
  "isahaya.nagasaki.jp": 1,
  "ise.mie.jp": 1,
  "isehara.kanagawa.jp": 1,
  "isen.kagoshima.jp": 1,
  "isernia.it": 1,
  "iserv.dev": 1,
  "iservschule.de": 1,
  "isesaki.gunma.jp": 1,
  "ishigaki.okinawa.jp": 1,
  "ishikari.hokkaido.jp": 1,
  "ishikawa.fukushima.jp": 1,
  "ishikawa.jp": 1,
  "ishikawa.okinawa.jp": 1,
  "ishinomaki.miyagi.jp": 1,
  "isla.pr": 1,
  "isleofman.museum": 1,
  "isshiki.aichi.jp": 1,
  "issmarterthanyou.com": 1,
  "isteingeek.de": 1,
  "istmein.de": 1,
  "isumi.chiba.jp": 1,
  "it.ao": 1,
  "it.eu.org": 1,
  "it1.eur.aruba.jenv-aruba.cloud": 1,
  "it1.jenv-aruba.cloud": 1,
  "itabashi.tokyo.jp": 1,
  "itako.ibaraki.jp": 1,
  "itakura.gunma.jp": 1,
  "itami.hyogo.jp": 1,
  "itano.tokushima.jp": 1,
  "itayanagi.aomori.jp": 1,
  "itcouldbewor.se": 1,
  "itigo.jp": 1,
  "ito.shizuoka.jp": 1,
  "itoigawa.niigata.jp": 1,
  "itoman.okinawa.jp": 1,
  "its.me": 1,
  "ivano-frankivsk.ua": 1,
  "ivanovo.su": 1,
  "iveland.no": 1,
  "ivgu.no": 1,
  "iwade.wakayama.jp": 1,
  "iwafune.tochigi.jp": 1,
  "iwaizumi.iwate.jp": 1,
  "iwaki.fukushima.jp": 1,
  "iwakuni.yamaguchi.jp": 1,
  "iwakura.aichi.jp": 1,
  "iwama.ibaraki.jp": 1,
  "iwamizawa.hokkaido.jp": 1,
  "iwanai.hokkaido.jp": 1,
  "iwanuma.miyagi.jp": 1,
  "iwata.shizuoka.jp": 1,
  "iwate.iwate.jp": 1,
  "iwate.jp": 1,
  "iwatsuki.saitama.jp": 1,
  "iwi.nz": 1,
  "iyo.ehime.jp": 1,
  "iz.hr": 1,
  "izena.okinawa.jp": 1,
  "izu.shizuoka.jp": 1,
  "izumi.kagoshima.jp": 1,
  "izumi.osaka.jp": 1,
  "izumiotsu.osaka.jp": 1,
  "izumisano.osaka.jp": 1,
  "izumizaki.fukushima.jp": 1,
  "izumo.shimane.jp": 1,
  "izumozaki.niigata.jp": 1,
  "izunokuni.shizuoka.jp": 1,
  "j.bg": 1,
  "j.layershift.co.uk": 1,
  "j.scaleforce.com.cy": 1,
  "j.scaleforce.net": 1,
  "jab.br": 1,
  "jambyl.su": 1,
  "jamison.museum": 1,
  "jampa.br": 1,
  "jan-mayen.no": 1,
  "jaworzno.pl": 1,
  "jc.neen.it": 1,
  "jcloud-ver-jpc.ik-server.com": 1,
  "jcloud.ik-server.com": 1,
  "jcloud.kz": 1,
  "jdevcloud.com": 1,
  "jdf.br": 1,
  "jed.wafaicloud.com": 1,
  "jefferson.museum": 1,
  "jeju.kr": 1,
  "jelastic.dogado.eu": 1,
  "jelastic.regruhosting.ru": 1,
  "jelastic.saveincloud.net": 1,
  "jelastic.team": 1,
  "jelastic.tsukaeru.net": 1,
  "jele.cloud": 1,
  "jele.club": 1,
  "jele.host": 1,
  "jele.io": 1,
  "jele.site": 1,
  "jelenia-gora.pl": 1,
  "jellybean.jp": 1,
  "jeonbuk.kr": 1,
  "jeonnam.kr": 1,
  "jerusalem.museum": 1,
  "jessheim.no": 1,
  "jevnaker.no": 1,
  "jewelry.museum": 1,
  "jewish.museum": 1,
  "jewishart.museum": 1,
  "jfk.museum": 1,
  "jgora.pl": 1,
  "jinsekikogen.hiroshima.jp": 1,
  "jl.cn": 1,
  "jls-sto1.elastx.net": 1,
  "jls-sto2.elastx.net": 1,
  "jls-sto3.elastx.net": 1,
  "jm": 2,
  "joboji.iwate.jp": 1,
  "jobs.tt": 1,
  "joetsu.niigata.jp": 1,
  "jogasz.hu": 1,
  "johana.toyama.jp": 1,
  "joinville.br": 1,
  "jolster.no": 1,
  "jondal.no": 1,
  "jor.br": 1,
  "jorpeland.no": 1,
  "joso.ibaraki.jp": 1,
  "jotelulu.cloud": 1,
  "journal.aero": 1,
  "journalism.museum": 1,
  "journalist.aero": 1,
  "joyo.kyoto.jp": 1,
  "jozi.biz": 1,
  "jp.eu.org": 1,
  "jp.kg": 1,
  "jp.md": 1,
  "jp.net": 1,
  "jpn.com": 1,
  "js.cn": 1,
  "js.org": 1,
  "js.wpenginepowered.com": 1,
  "ju.mp": 1,
  "judaica.museum": 1,
  "judygarland.museum": 1,
  "juedisches.museum": 1,
  "juif.museum": 1,
  "jur.pro": 1,
  "jus.br": 1,
  "jx.cn": 1,
  "k.bg": 1,
  "k.se": 1,
  "k12.ak.us": 1,
  "k12.al.us": 1,
  "k12.ar.us": 1,
  "k12.as.us": 1,
  "k12.az.us": 1,
  "k12.ca.us": 1,
  "k12.co.us": 1,
  "k12.ct.us": 1,
  "k12.dc.us": 1,
  "k12.de.us": 1,
  "k12.ec": 1,
  "k12.fl.us": 1,
  "k12.ga.us": 1,
  "k12.gu.us": 1,
  "k12.ia.us": 1,
  "k12.id.us": 1,
  "k12.il": 1,
  "k12.il.us": 1,
  "k12.in.us": 1,
  "k12.ks.us": 1,
  "k12.ky.us": 1,
  "k12.la.us": 1,
  "k12.ma.us": 1,
  "k12.md.us": 1,
  "k12.me.us": 1,
  "k12.mi.us": 1,
  "k12.mn.us": 1,
  "k12.mo.us": 1,
  "k12.ms.us": 1,
  "k12.mt.us": 1,
  "k12.nc.us": 1,
  "k12.ne.us": 1,
  "k12.nh.us": 1,
  "k12.nj.us": 1,
  "k12.nm.us": 1,
  "k12.nv.us": 1,
  "k12.ny.us": 1,
  "k12.oh.us": 1,
  "k12.ok.us": 1,
  "k12.or.us": 1,
  "k12.pa.us": 1,
  "k12.pr.us": 1,
  "k12.sc.us": 1,
  "k12.tn.us": 1,
  "k12.tr": 1,
  "k12.tx.us": 1,
  "k12.ut.us": 1,
  "k12.va.us": 1,
  "k12.vi": 1,
  "k12.vi.us": 1,
  "k12.vt.us": 1,
  "k12.wa.us": 1,
  "k12.wi.us": 1,
  "k12.wy.us": 1,
  "k8s.fr-par.scw.cloud": 1,
  "k8s.nl-ams.scw.cloud": 1,
  "k8s.pl-waw.scw.cloud": 1,
  "k8s.scw.cloud": 1,
  "kaas.gg": 1,
  "kadena.okinawa.jp": 1,
  "kadogawa.miyazaki.jp": 1,
  "kadoma.osaka.jp": 1,
  "kafjord.no": 1,
  "kaga.ishikawa.jp": 1,
  "kagami.kochi.jp": 1,
  "kagamiishi.fukushima.jp": 1,
  "kagamino.okayama.jp": 1,
  "kagawa.jp": 1,
  "kagoshima.jp": 1,
  "kagoshima.kagoshima.jp": 1,
  "kaho.fukuoka.jp": 1,
  "kahoku.ishikawa.jp": 1,
  "kahoku.yamagata.jp": 1,
  "kai.yamanashi.jp": 1,
  "kainan.tokushima.jp": 1,
  "kainan.wakayama.jp": 1,
  "kaisei.kanagawa.jp": 1,
  "kaita.hiroshima.jp": 1,
  "kaizuka.osaka.jp": 1,
  "kakamigahara.gifu.jp": 1,
  "kakegawa.shizuoka.jp": 1,
  "kakinoki.shimane.jp": 1,
  "kakogawa.hyogo.jp": 1,
  "kakuda.miyagi.jp": 1,
  "kalisz.pl": 1,
  "kalmykia.ru": 1,
  "kalmykia.su": 1,
  "kaluga.su": 1,
  "kamagaya.chiba.jp": 1,
  "kamaishi.iwate.jp": 1,
  "kamakura.kanagawa.jp": 1,
  "kameoka.kyoto.jp": 1,
  "kameyama.mie.jp": 1,
  "kami.kochi.jp": 1,
  "kami.miyagi.jp": 1,
  "kamiamakusa.kumamoto.jp": 1,
  "kamifurano.hokkaido.jp": 1,
  "kamigori.hyogo.jp": 1,
  "kamiichi.toyama.jp": 1,
  "kamiizumi.saitama.jp": 1,
  "kamijima.ehime.jp": 1,
  "kamikawa.hokkaido.jp": 1,
  "kamikawa.hyogo.jp": 1,
  "kamikawa.saitama.jp": 1,
  "kamikitayama.nara.jp": 1,
  "kamikoani.akita.jp": 1,
  "kamimine.saga.jp": 1,
  "kaminokawa.tochigi.jp": 1,
  "kaminoyama.yamagata.jp": 1,
  "kamioka.akita.jp": 1,
  "kamisato.saitama.jp": 1,
  "kamishihoro.hokkaido.jp": 1,
  "kamisu.ibaraki.jp": 1,
  "kamisunagawa.hokkaido.jp": 1,
  "kamitonda.wakayama.jp": 1,
  "kamitsue.oita.jp": 1,
  "kamo.kyoto.jp": 1,
  "kamo.niigata.jp": 1,
  "kamoenai.hokkaido.jp": 1,
  "kamogawa.chiba.jp": 1,
  "kanagawa.jp": 1,
  "kanan.osaka.jp": 1,
  "kanazawa.ishikawa.jp": 1,
  "kanegasaki.iwate.jp": 1,
  "kaneyama.fukushima.jp": 1,
  "kaneyama.yamagata.jp": 1,
  "kani.gifu.jp": 1,
  "kanie.aichi.jp": 1,
  "kanmaki.nara.jp": 1,
  "kanna.gunma.jp": 1,
  "kannami.shizuoka.jp": 1,
  "kanonji.kagawa.jp": 1,
  "kanoya.kagoshima.jp": 1,
  "kanra.gunma.jp": 1,
  "kanuma.tochigi.jp": 1,
  "kanzaki.saga.jp": 1,
  "kapsi.fi": 1,
  "karacol.su": 1,
  "karaganda.su": 1,
  "karasjohka.no": 1,
  "karasjok.no": 1,
  "karasuyama.tochigi.jp": 1,
  "karate.museum": 1,
  "karatsu.saga.jp": 1,
  "karelia.su": 1,
  "karikatur.museum": 1,
  "kariwa.niigata.jp": 1,
  "kariya.aichi.jp": 1,
  "karlsoy.no": 1,
  "karmoy.no": 1,
  "karpacz.pl": 1,
  "kartuzy.pl": 1,
  "karuizawa.nagano.jp": 1,
  "karumai.iwate.jp": 1,
  "kasahara.gifu.jp": 1,
  "kasai.hyogo.jp": 1,
  "kasama.ibaraki.jp": 1,
  "kasamatsu.gifu.jp": 1,
  "kasaoka.okayama.jp": 1,
  "kashiba.nara.jp": 1,
  "kashihara.nara.jp": 1,
  "kashima.ibaraki.jp": 1,
  "kashima.saga.jp": 1,
  "kashiwa.chiba.jp": 1,
  "kashiwara.osaka.jp": 1,
  "kashiwazaki.niigata.jp": 1,
  "kasserver.com": 1,
  "kasuga.fukuoka.jp": 1,
  "kasuga.hyogo.jp": 1,
  "kasugai.aichi.jp": 1,
  "kasukabe.saitama.jp": 1,
  "kasumigaura.ibaraki.jp": 1,
  "kasuya.fukuoka.jp": 1,
  "kaszuby.pl": 1,
  "katagami.akita.jp": 1,
  "katano.osaka.jp": 1,
  "katashina.gunma.jp": 1,
  "katori.chiba.jp": 1,
  "katowice.pl": 1,
  "katsuragi.nara.jp": 1,
  "katsuragi.wakayama.jp": 1,
  "katsushika.tokyo.jp": 1,
  "katsuura.chiba.jp": 1,
  "katsuyama.fukui.jp": 1,
  "kautokeino.no": 1,
  "kawaba.gunma.jp": 1,
  "kawachinagano.osaka.jp": 1,
  "kawagoe.mie.jp": 1,
  "kawagoe.saitama.jp": 1,
  "kawaguchi.saitama.jp": 1,
  "kawahara.tottori.jp": 1,
  "kawai.iwate.jp": 1,
  "kawai.nara.jp": 1,
  "kawaiishop.jp": 1,
  "kawajima.saitama.jp": 1,
  "kawakami.nagano.jp": 1,
  "kawakami.nara.jp": 1,
  "kawakita.ishikawa.jp": 1,
  "kawamata.fukushima.jp": 1,
  "kawaminami.miyazaki.jp": 1,
  "kawanabe.kagoshima.jp": 1,
  "kawanehon.shizuoka.jp": 1,
  "kawanishi.hyogo.jp": 1,
  "kawanishi.nara.jp": 1,
  "kawanishi.yamagata.jp": 1,
  "kawara.fukuoka.jp": 1,
  "kawasaki.jp": 2,
  "kawasaki.miyagi.jp": 1,
  "kawatana.nagasaki.jp": 1,
  "kawaue.gifu.jp": 1,
  "kawazu.shizuoka.jp": 1,
  "kayabe.hokkaido.jp": 1,
  "kazimierz-dolny.pl": 1,
  "kazo.saitama.jp": 1,
  "kazuno.akita.jp": 1,
  "keisen.fukuoka.jp": 1,
  "keliweb.cloud": 1,
  "kembuchi.hokkaido.jp": 1,
  "kep.tr": 1,
  "kepno.pl": 1,
  "ketrzyn.pl": 1,
  "keymachine.de": 1,
  "kg.kr": 1,
  "kh": 2,
  "kh.ua": 1,
  "khakassia.su": 1,
  "kharkiv.ua": 1,
  "kharkov.ua": 1,
  "kherson.ua": 1,
  "khmelnitskiy.ua": 1,
  "khmelnytskyi.ua": 1,
  "khplay.nl": 1,
  "kibichuo.okayama.jp": 1,
  "kicks-ass.net": 1,
  "kicks-ass.org": 1,
  "kids.museum": 1,
  "kids.us": 1,
  "kiev.ua": 1,
  "kiho.mie.jp": 1,
  "kihoku.ehime.jp": 1,
  "kijo.miyazaki.jp": 1,
  "kikirara.jp": 1,
  "kikonai.hokkaido.jp": 1,
  "kikuchi.kumamoto.jp": 1,
  "kikugawa.shizuoka.jp": 1,
  "kilatiron.com": 1,
  "kill.jp": 1,
  "kilo.jp": 1,
  "kimino.wakayama.jp": 1,
  "kimitsu.chiba.jp": 1,
  "kimobetsu.hokkaido.jp": 1,
  "kin.okinawa.jp": 1,
  "kinghost.net": 1,
  "kinko.kagoshima.jp": 1,
  "kinokawa.wakayama.jp": 1,
  "kira.aichi.jp": 1,
  "kirkenes.no": 1,
  "kirovograd.ua": 1,
  "kiryu.gunma.jp": 1,
  "kisarazu.chiba.jp": 1,
  "kishiwada.osaka.jp": 1,
  "kiso.nagano.jp": 1,
  "kisofukushima.nagano.jp": 1,
  "kisosaki.mie.jp": 1,
  "kita.kyoto.jp": 1,
  "kita.osaka.jp": 1,
  "kita.tokyo.jp": 1,
  "kitaaiki.nagano.jp": 1,
  "kitaakita.akita.jp": 1,
  "kitadaito.okinawa.jp": 1,
  "kitagata.gifu.jp": 1,
  "kitagata.saga.jp": 1,
  "kitagawa.kochi.jp": 1,
  "kitagawa.miyazaki.jp": 1,
  "kitahata.saga.jp": 1,
  "kitahiroshima.hokkaido.jp": 1,
  "kitakami.iwate.jp": 1,
  "kitakata.fukushima.jp": 1,
  "kitakata.miyazaki.jp": 1,
  "kitakyushu.jp": 2,
  "kitami.hokkaido.jp": 1,
  "kitamoto.saitama.jp": 1,
  "kitanakagusuku.okinawa.jp": 1,
  "kitashiobara.fukushima.jp": 1,
  "kitaura.miyazaki.jp": 1,
  "kitayama.wakayama.jp": 1,
  "kiwa.mie.jp": 1,
  "kiwi.nz": 1,
  "kiyama.saga.jp": 1,
  "kiyokawa.kanagawa.jp": 1,
  "kiyosato.hokkaido.jp": 1,
  "kiyose.tokyo.jp": 1,
  "kiyosu.aichi.jp": 1,
  "kizu.kyoto.jp": 1,
  "klabu.no": 1,
  "klepp.no": 1,
  "klodzko.pl": 1,
  "km.ua": 1,
  "kmpsp.gov.pl": 1,
  "knightpoint.systems": 1,
  "knowsitall.info": 1,
  "knx-server.net": 1,
  "kobayashi.miyazaki.jp": 1,
  "kobe.jp": 2,
  "kobierzyce.pl": 1,
  "kochi.jp": 1,
  "kochi.kochi.jp": 1,
  "kodaira.tokyo.jp": 1,
  "koebenhavn.museum": 1,
  "koeln.museum": 1,
  "kofu.yamanashi.jp": 1,
  "koga.fukuoka.jp": 1,
  "koga.ibaraki.jp": 1,
  "koganei.tokyo.jp": 1,
  "koge.tottori.jp": 1,
  "koka.shiga.jp": 1,
  "kokonoe.oita.jp": 1,
  "kokubunji.tokyo.jp": 1,
  "kolobrzeg.pl": 1,
  "komae.tokyo.jp": 1,
  "komagane.nagano.jp": 1,
  "komaki.aichi.jp": 1,
  "komatsu.ishikawa.jp": 1,
  "komatsushima.tokushima.jp": 1,
  "komforb.se": 1,
  "kommunalforbund.se": 1,
  "kommune.no": 1,
  "komono.mie.jp": 1,
  "komoro.nagano.jp": 1,
  "komvux.se": 1,
  "konan.aichi.jp": 1,
  "konan.shiga.jp": 1,
  "kongsberg.no": 1,
  "kongsvinger.no": 1,
  "konin.pl": 1,
  "konskowola.pl": 1,
  "konsulat.gov.pl": 1,
  "konyvelo.hu": 1,
  "koobin.events": 1,
  "koori.fukushima.jp": 1,
  "kopervik.no": 1,
  "koriyama.fukushima.jp": 1,
  "koryo.nara.jp": 1,
  "kosai.shizuoka.jp": 1,
  "kosaka.akita.jp": 1,
  "kosei.shiga.jp": 1,
  "koshigaya.saitama.jp": 1,
  "koshimizu.hokkaido.jp": 1,
  "koshu.yamanashi.jp": 1,
  "kosuge.yamanashi.jp": 1,
  "kota.aichi.jp": 1,
  "koto.shiga.jp": 1,
  "koto.tokyo.jp": 1,
  "kotohira.kagawa.jp": 1,
  "kotoura.tottori.jp": 1,
  "kouhoku.saga.jp": 1,
  "kounosu.saitama.jp": 1,
  "kouyama.kagoshima.jp": 1,
  "kouzushima.tokyo.jp": 1,
  "koya.wakayama.jp": 1,
  "koza.wakayama.jp": 1,
  "kozagawa.wakayama.jp": 1,
  "kozaki.chiba.jp": 1,
  "kozow.com": 1,
  "kppsp.gov.pl": 1,
  "kr.com": 1,
  "kr.eu.org": 1,
  "kr.it": 1,
  "kr.ua": 1,
  "kraanghke.no": 1,
  "kragero.no": 1,
  "krakow.pl": 1,
  "krasnik.pl": 1,
  "krasnodar.su": 1,
  "krellian.net": 1,
  "kristiansand.no": 1,
  "kristiansund.no": 1,
  "krodsherad.no": 1,
  "krokstadelva.no": 1,
  "krym.ua": 1,
  "ks.ua": 1,
  "ks.us": 1,
  "ktistory.com": 1,
  "kuchinotsu.nagasaki.jp": 1,
  "kudamatsu.yamaguchi.jp": 1,
  "kudoyama.wakayama.jp": 1,
  "kui.hiroshima.jp": 1,
  "kuji.iwate.jp": 1,
  "kuju.oita.jp": 1,
  "kujukuri.chiba.jp": 1,
  "kuki.saitama.jp": 1,
  "kuleuven.cloud": 1,
  "kumagaya.saitama.jp": 1,
  "kumakogen.ehime.jp": 1,
  "kumamoto.jp": 1,
  "kumamoto.kumamoto.jp": 1,
  "kumano.hiroshima.jp": 1,
  "kumano.mie.jp": 1,
  "kumatori.osaka.jp": 1,
  "kumejima.okinawa.jp": 1,
  "kumenan.okayama.jp": 1,
  "kumiyama.kyoto.jp": 1,
  "kunden.ortsinfo.at": 2,
  "kunigami.okinawa.jp": 1,
  "kunimi.fukushima.jp": 1,
  "kunisaki.oita.jp": 1,
  "kunitachi.tokyo.jp": 1,
  "kunitomi.miyazaki.jp": 1,
  "kunneppu.hokkaido.jp": 1,
  "kunohe.iwate.jp": 1,
  "kunst.museum": 1,
  "kunstsammlung.museum": 1,
  "kunstunddesign.museum": 1,
  "kurashiki.okayama.jp": 1,
  "kurate.fukuoka.jp": 1,
  "kure.hiroshima.jp": 1,
  "kurgan.su": 1,
  "kuriyama.hokkaido.jp": 1,
  "kurobe.toyama.jp": 1,
  "kurogi.fukuoka.jp": 1,
  "kuroishi.aomori.jp": 1,
  "kuroiso.tochigi.jp": 1,
  "kuromatsunai.hokkaido.jp": 1,
  "kuron.jp": 1,
  "kurotaki.nara.jp": 1,
  "kurume.fukuoka.jp": 1,
  "kusatsu.gunma.jp": 1,
  "kusatsu.shiga.jp": 1,
  "kushima.miyazaki.jp": 1,
  "kushimoto.wakayama.jp": 1,
  "kushiro.hokkaido.jp": 1,
  "kustanai.ru": 1,
  "kustanai.su": 1,
  "kusu.oita.jp": 1,
  "kutchan.hokkaido.jp": 1,
  "kutno.pl": 1,
  "kuwana.mie.jp": 1,
  "kuzumaki.iwate.jp": 1,
  "kv.ua": 1,
  "kvafjord.no": 1,
  "kvalsund.no": 1,
  "kvam.no": 1,
  "kvanangen.no": 1,
  "kvinesdal.no": 1,
  "kvinnherad.no": 1,
  "kviteseid.no": 1,
  "kvitsoy.no": 1,
  "kwp.gov.pl": 1,
  "kwpsp.gov.pl": 1,
  "ky.us": 1,
  "kyiv.ua": 1,
  "kyonan.chiba.jp": 1,
  "kyotamba.kyoto.jp": 1,
  "kyotanabe.kyoto.jp": 1,
  "kyotango.kyoto.jp": 1,
  "kyoto.jp": 1,
  "kyowa.akita.jp": 1,
  "kyowa.hokkaido.jp": 1,
  "kyuragi.saga.jp": 1,
  "l-o-g-i-n.de": 1,
  "l.bg": 1,
  "l.se": 1,
  "la-spezia.it": 1,
  "la.us": 1,
  "laakesvuemie.no": 1,
  "lab.ms": 1,
  "labor.museum": 1,
  "labour.museum": 1,
  "lahppi.no": 1,
  "lajolla.museum": 1,
  "lakas.hu": 1,
  "lanbib.se": 1,
  "lancashire.museum": 1,
  "land-4-sale.us": 1,
  "landes.museum": 1,
  "landing.myjino.ru": 2,
  "langevag.no": 1,
  "lans.museum": 1,
  "lapy.pl": 1,
  "laquila.it": 1,
  "lardal.no": 1,
  "larsson.museum": 1,
  "larvik.no": 1,
  "laspezia.it": 1,
  "latina.it": 1,
  "lavagis.no": 1,
  "lavangen.no": 1,
  "law.pro": 1,
  "law.za": 1,
  "laz.it": 1,
  "lazio.it": 1,
  "lc.it": 1,
  "lcl.dev": 2,
  "lclstage.dev": 2,
  "lcube-server.de": 1,
  "le.it": 1,
  "leadpages.co": 1,
  "leangaviika.no": 1,
  "leasing.aero": 1,
  "lebesby.no": 1,
  "lebork.pl": 1,
  "lebtimnetz.de": 1,
  "lecce.it": 1,
  "lecco.it": 1,
  "leczna.pl": 1,
  "leg.br": 1,
  "legnica.pl": 1,
  "leikanger.no": 1,
  "leirfjord.no": 1,
  "leirvik.no": 1,
  "leitungsen.de": 1,
  "leka.no": 1,
  "leksvik.no": 1,
  "lel.br": 1,
  "lelux.site": 1,
  "lenug.su": 1,
  "lenvik.no": 1,
  "lerdal.no": 1,
  "lesja.no": 1,
  "levanger.no": 1,
  "lewismiller.museum": 1,
  "lezajsk.pl": 1,
  "lg.jp": 1,
  "lg.ua": 1,
  "li.it": 1,
  "lib.ak.us": 1,
  "lib.al.us": 1,
  "lib.ar.us": 1,
  "lib.as.us": 1,
  "lib.az.us": 1,
  "lib.ca.us": 1,
  "lib.co.us": 1,
  "lib.ct.us": 1,
  "lib.dc.us": 1,
  "lib.de.us": 1,
  "lib.ee": 1,
  "lib.fl.us": 1,
  "lib.ga.us": 1,
  "lib.gu.us": 1,
  "lib.hi.us": 1,
  "lib.ia.us": 1,
  "lib.id.us": 1,
  "lib.il.us": 1,
  "lib.in.us": 1,
  "lib.ks.us": 1,
  "lib.ky.us": 1,
  "lib.la.us": 1,
  "lib.ma.us": 1,
  "lib.md.us": 1,
  "lib.me.us": 1,
  "lib.mi.us": 1,
  "lib.mn.us": 1,
  "lib.mo.us": 1,
  "lib.ms.us": 1,
  "lib.mt.us": 1,
  "lib.nc.us": 1,
  "lib.nd.us": 1,
  "lib.ne.us": 1,
  "lib.nh.us": 1,
  "lib.nj.us": 1,
  "lib.nm.us": 1,
  "lib.nv.us": 1,
  "lib.ny.us": 1,
  "lib.oh.us": 1,
  "lib.ok.us": 1,
  "lib.or.us": 1,
  "lib.pa.us": 1,
  "lib.pr.us": 1,
  "lib.ri.us": 1,
  "lib.sc.us": 1,
  "lib.sd.us": 1,
  "lib.tn.us": 1,
  "lib.tx.us": 1,
  "lib.ut.us": 1,
  "lib.va.us": 1,
  "lib.vi.us": 1,
  "lib.vt.us": 1,
  "lib.wa.us": 1,
  "lib.wi.us": 1,
  "lib.wy.us": 1,
  "lier.no": 1,
  "lierne.no": 1,
  "lig.it": 1,
  "liguria.it": 1,
  "likes-pie.com": 1,
  "likescandy.com": 1,
  "lillehammer.no": 1,
  "lillesand.no": 1,
  "lima-city.at": 1,
  "lima-city.ch": 1,
  "lima-city.de": 1,
  "lima-city.rocks": 1,
  "lima.zone": 1,
  "limanowa.pl": 1,
  "lincoln.museum": 1,
  "lindas.no": 1,
  "lindesnes.no": 1,
  "linkyard-cloud.ch": 1,
  "linkyard.cloud": 1,
  "linodeobjects.com": 2,
  "linz.museum": 1,
  "littlestar.jp": 1,
  "living.museum": 1,
  "livinghistory.museum": 1,
  "livorno.it": 1,
  "lk3.ru": 1,
  "ln.cn": 1,
  "lo.it": 1,
  "loabat.no": 1,
  "localhistory.museum": 1,
  "localhost.daplie.me": 1,
  "localzone.xyz": 1,
  "lodi.it": 1,
  "lodingen.no": 1,
  "log.br": 1,
  "loginline.app": 1,
  "loginline.dev": 1,
  "loginline.io": 1,
  "loginline.services": 1,
  "loginline.site": 1,
  "loginto.me": 1,
  "logistics.aero": 1,
  "logoip.com": 1,
  "logoip.de": 1,
  "lohmus.me": 1,
  "lolipop.io": 1,
  "lolipopmc.jp": 1,
  "lolitapunk.jp": 1,
  "lom.it": 1,
  "lom.no": 1,
  "lombardia.it": 1,
  "lombardy.it": 1,
  "lomo.jp": 1,
  "lomza.pl": 1,
  "lon-1.paas.massivegrid.net": 1,
  "lon-2.paas.massivegrid.net": 1,
  "lon.wafaicloud.com": 1,
  "london.cloudapps.digital": 1,
  "london.museum": 1,
  "londrina.br": 1,
  "loppa.no": 1,
  "lorenskog.no": 1,
  "losangeles.museum": 1,
  "loseyourip.com": 1,
  "loten.no": 1,
  "louvre.museum": 1,
  "lovepop.jp": 1,
  "lovesick.jp": 1,
  "lowicz.pl": 1,
  "loyalist.museum": 1,
  "lpages.co": 1,
  "lpusercontent.com": 1,
  "lt.eu.org": 1,
  "lt.it": 1,
  "lt.ua": 1,
  "ltd.co.im": 1,
  "ltd.cy": 1,
  "ltd.gi": 1,
  "ltd.hk": 1,
  "ltd.lk": 1,
  "ltd.ng": 1,
  "ltd.ua": 1,
  "ltd.uk": 1,
  "lu.eu.org": 1,
  "lu.it": 1,
  "lubartow.pl": 1,
  "lubin.pl": 1,
  "lublin.pl": 1,
  "lucania.it": 1,
  "lucca.it": 1,
  "lucerne.museum": 1,
  "lug.org.uk": 1,
  "lugansk.ua": 1,
  "lugs.org.uk": 1,
  "lukow.pl": 1,
  "lund.no": 1,
  "lunner.no": 1,
  "luroy.no": 1,
  "luster.no": 1,
  "lutsk.ua": 1,
  "luxembourg.museum": 1,
  "luzern.museum": 1,
  "lv.eu.org": 1,
  "lv.ua": 1,
  "lviv.ua": 1,
  "lyngdal.no": 1,
  "lyngen.no": 1,
  "lynx.mythic-beasts.com": 1,
  "m.bg": 1,
  "m.se": 1,
  "ma.gov.br": 1,
  "ma.leg.br": 1,
  "ma.us": 1,
  "macapa.br": 1,
  "maceio.br": 1,
  "macerata.it": 1,
  "machida.tokyo.jp": 1,
  "mad.museum": 1,
  "madrid.museum": 1,
  "maebashi.gunma.jp": 1,
  "magazine.aero": 1,
  "magentosite.cloud": 2,
  "magnet.page": 1,
  "maibara.shiga.jp": 1,
  "mail.pl": 1,
  "main.jp": 1,
  "maintenance.aero": 1,
  "maizuru.kyoto.jp": 1,
  "makinohara.shizuoka.jp": 1,
  "makurazaki.kagoshima.jp": 1,
  "malatvuopmi.no": 1,
  "malbork.pl": 1,
  "mallorca.museum": 1,
  "malopolska.pl": 1,
  "malselv.no": 1,
  "malvik.no": 1,
  "mamurogawa.yamagata.jp": 1,
  "manaus.br": 1,
  "manchester.museum": 1,
  "mandal.no": 1,
  "mangyshlak.su": 1,
  "maniwa.okayama.jp": 1,
  "manno.kagawa.jp": 1,
  "mansion.museum": 1,
  "mansions.museum": 1,
  "mantova.it": 1,
  "manx.museum": 1,
  "maori.nz": 1,
  "map.fastly.net": 1,
  "map.fastlylb.net": 1,
  "mar.it": 1,
  "marburg.museum": 1,
  "marche.it": 1,
  "marine.ru": 1,
  "maringa.br": 1,
  "maritime.museum": 1,
  "maritimo.museum": 1,
  "marker.no": 1,
  "marnardal.no": 1,
  "marugame.kagawa.jp": 1,
  "marumori.miyagi.jp": 1,
  "maryland.museum": 1,
  "marylhurst.museum": 1,
  "masaki.ehime.jp": 1,
  "masfjorden.no": 1,
  "mashike.hokkaido.jp": 1,
  "mashiki.kumamoto.jp": 1,
  "mashiko.tochigi.jp": 1,
  "masoy.no": 1,
  "massa-carrara.it": 1,
  "massacarrara.it": 1,
  "masuda.shimane.jp": 1,
  "mat.br": 1,
  "matera.it": 1,
  "matsubara.osaka.jp": 1,
  "matsubushi.saitama.jp": 1,
  "matsuda.kanagawa.jp": 1,
  "matsudo.chiba.jp": 1,
  "matsue.shimane.jp": 1,
  "matsukawa.nagano.jp": 1,
  "matsumae.hokkaido.jp": 1,
  "matsumoto.kagoshima.jp": 1,
  "matsumoto.nagano.jp": 1,
  "matsuno.ehime.jp": 1,
  "matsusaka.mie.jp": 1,
  "matsushige.tokushima.jp": 1,
  "matsushima.miyagi.jp": 1,
  "matsuura.nagasaki.jp": 1,
  "matsuyama.ehime.jp": 1,
  "matsuzaki.shizuoka.jp": 1,
  "matta-varjjat.no": 1,
  "mayfirst.info": 1,
  "mayfirst.org": 1,
  "mazeplay.com": 1,
  "mazowsze.pl": 1,
  "mazury.pl": 1,
  "mb.ca": 1,
  "mb.it": 1,
  "mc.ax": 1,
  "mc.eu.org": 1,
  "mc.it": 1,
  "mcdir.me": 1,
  "mcdir.ru": 1,
  "mcpe.me": 1,
  "mcpre.ru": 1,
  "md.ci": 1,
  "md.us": 1,
  "me.eu.org": 1,
  "me.in": 1,
  "me.it": 1,
  "me.ke": 1,
  "me.so": 1,
  "me.ss": 1,
  "me.tc": 1,
  "me.tz": 1,
  "me.uk": 1,
  "me.us": 1,
  "me.vu": 1,
  "med.br": 1,
  "med.ec": 1,
  "med.ee": 1,
  "med.ht": 1,
  "med.ly": 1,
  "med.om": 1,
  "med.pa": 1,
  "med.pl": 1,
  "med.pro": 1,
  "med.sa": 1,
  "med.sd": 1,
  "medecin.fr": 1,
  "medecin.km": 1,
  "media.aero": 1,
  "media.hu": 1,
  "media.museum": 1,
  "media.pl": 1,
  "mediatech.by": 1,
  "mediatech.dev": 1,
  "medical.museum": 1,
  "medicina.bo": 1,
  "medio-campidano.it": 1,
  "mediocampidano.it": 1,
  "medizinhistorisches.museum": 1,
  "meeres.museum": 1,
  "meguro.tokyo.jp": 1,
  "mein-iserv.de": 1,
  "mein-vigor.de": 1,
  "meinforum.net": 1,
  "meiwa.gunma.jp": 1,
  "meiwa.mie.jp": 1,
  "mel.cloudlets.com.au": 1,
  "meland.no": 1,
  "meldal.no": 1,
  "melhus.no": 1,
  "meloy.no": 1,
  "members.linode.com": 1,
  "memorial.museum": 1,
  "memset.net": 1,
  "meraker.no": 1,
  "merseine.nu": 1,
  "mesaverde.museum": 1,
  "messerli.app": 1,
  "messina.it": 1,
  "messwithdns.com": 1,
  "meteorapp.com": 1,
  "mex.com": 1,
  "mg.gov.br": 1,
  "mg.leg.br": 1,
  "mi.it": 1,
  "mi.th": 1,
  "mi.us": 1,
  "miasa.nagano.jp": 1,
  "miasta.pl": 1,
  "mibu.tochigi.jp": 1,
  "michigan.museum": 1,
  "microlight.aero": 1,
  "midatlantic.museum": 1,
  "midori.chiba.jp": 1,
  "midori.gunma.jp": 1,
  "midsund.no": 1,
  "midtre-gauldal.no": 1,
  "mie.jp": 1,
  "mielec.pl": 1,
  "mielno.pl": 1,
  "mifune.kumamoto.jp": 1,
  "migration.run": 2,
  "mihama.aichi.jp": 1,
  "mihama.chiba.jp": 1,
  "mihama.fukui.jp": 1,
  "mihama.mie.jp": 1,
  "mihama.wakayama.jp": 1,
  "mihara.hiroshima.jp": 1,
  "mihara.kochi.jp": 1,
  "miharu.fukushima.jp": 1,
  "miho.ibaraki.jp": 1,
  "mikasa.hokkaido.jp": 1,
  "mikawa.yamagata.jp": 1,
  "miki.hyogo.jp": 1,
  "mil.ac": 1,
  "mil.ae": 1,
  "mil.al": 1,
  "mil.ar": 1,
  "mil.az": 1,
  "mil.ba": 1,
  "mil.bo": 1,
  "mil.br": 1,
  "mil.by": 1,
  "mil.cl": 1,
  "mil.cn": 1,
  "mil.co": 1,
  "mil.cy": 1,
  "mil.do": 1,
  "mil.ec": 1,
  "mil.eg": 1,
  "mil.fj": 1,
  "mil.ge": 1,
  "mil.gh": 1,
  "mil.gt": 1,
  "mil.hn": 1,
  "mil.id": 1,
  "mil.in": 1,
  "mil.iq": 1,
  "mil.jo": 1,
  "mil.kg": 1,
  "mil.km": 1,
  "mil.kr": 1,
  "mil.kz": 1,
  "mil.lv": 1,
  "mil.mg": 1,
  "mil.mv": 1,
  "mil.my": 1,
  "mil.mz": 1,
  "mil.ng": 1,
  "mil.ni": 1,
  "mil.no": 1,
  "mil.nz": 1,
  "mil.pe": 1,
  "mil.ph": 1,
  "mil.pl": 1,
  "mil.py": 1,
  "mil.qa": 1,
  "mil.ru": 1,
  "mil.rw": 1,
  "mil.sh": 1,
  "mil.st": 1,
  "mil.sy": 1,
  "mil.tj": 1,
  "mil.tm": 1,
  "mil.to": 1,
  "mil.tr": 1,
  "mil.tw": 1,
  "mil.tz": 1,
  "mil.uy": 1,
  "mil.vc": 1,
  "mil.ve": 1,
  "mil.ye": 1,
  "mil.za": 1,
  "mil.zm": 1,
  "mil.zw": 1,
  "milan.it": 1,
  "milano.it": 1,
  "military.museum": 1,
  "mill.museum": 1,
  "mima.tokushima.jp": 1,
  "mimata.miyazaki.jp": 1,
  "minakami.gunma.jp": 1,
  "minamata.kumamoto.jp": 1,
  "minami-alps.yamanashi.jp": 1,
  "minami.fukuoka.jp": 1,
  "minami.kyoto.jp": 1,
  "minami.tokushima.jp": 1,
  "minamiaiki.nagano.jp": 1,
  "minamiashigara.kanagawa.jp": 1,
  "minamiawaji.hyogo.jp": 1,
  "minamiboso.chiba.jp": 1,
  "minamidaito.okinawa.jp": 1,
  "minamiechizen.fukui.jp": 1,
  "minamifurano.hokkaido.jp": 1,
  "minamiise.mie.jp": 1,
  "minamiizu.shizuoka.jp": 1,
  "minamimaki.nagano.jp": 1,
  "minamiminowa.nagano.jp": 1,
  "minamioguni.kumamoto.jp": 1,
  "minamisanriku.miyagi.jp": 1,
  "minamitane.kagoshima.jp": 1,
  "minamiuonuma.niigata.jp": 1,
  "minamiyamashiro.kyoto.jp": 1,
  "minano.saitama.jp": 1,
  "minato.osaka.jp": 1,
  "minato.tokyo.jp": 1,
  "mincom.tn": 1,
  "mine.nu": 1,
  "miners.museum": 1,
  "mining.museum": 1,
  "miniserver.com": 1,
  "minisite.ms": 1,
  "minnesota.museum": 1,
  "mino.gifu.jp": 1,
  "minobu.yamanashi.jp": 1,
  "minoh.osaka.jp": 1,
  "minokamo.gifu.jp": 1,
  "minowa.nagano.jp": 1,
  "mintere.site": 1,
  "mircloud.host": 1,
  "mircloud.ru": 1,
  "mircloud.us": 1,
  "misaki.okayama.jp": 1,
  "misaki.osaka.jp": 1,
  "misasa.tottori.jp": 1,
  "misato.akita.jp": 1,
  "misato.miyagi.jp": 1,
  "misato.saitama.jp": 1,
  "misato.shimane.jp": 1,
  "misato.wakayama.jp": 1,
  "misawa.aomori.jp": 1,
  "misconfused.org": 1,
  "mishima.fukushima.jp": 1,
  "mishima.shizuoka.jp": 1,
  "missile.museum": 1,
  "missoula.museum": 1,
  "misugi.mie.jp": 1,
  "mitaka.tokyo.jp": 1,
  "mitake.gifu.jp": 1,
  "mitane.akita.jp": 1,
  "mito.ibaraki.jp": 1,
  "mitou.yamaguchi.jp": 1,
  "mitoyo.kagawa.jp": 1,
  "mitsue.nara.jp": 1,
  "mitsuke.niigata.jp": 1,
  "miura.kanagawa.jp": 1,
  "miyada.nagano.jp": 1,
  "miyagi.jp": 1,
  "miyake.nara.jp": 1,
  "miyako.fukuoka.jp": 1,
  "miyako.iwate.jp": 1,
  "miyakonojo.miyazaki.jp": 1,
  "miyama.fukuoka.jp": 1,
  "miyama.mie.jp": 1,
  "miyashiro.saitama.jp": 1,
  "miyawaka.fukuoka.jp": 1,
  "miyazaki.jp": 1,
  "miyazaki.miyazaki.jp": 1,
  "miyazu.kyoto.jp": 1,
  "miyoshi.aichi.jp": 1,
  "miyoshi.hiroshima.jp": 1,
  "miyoshi.saitama.jp": 1,
  "miyoshi.tokushima.jp": 1,
  "miyota.nagano.jp": 1,
  "mizuho.tokyo.jp": 1,
  "mizumaki.fukuoka.jp": 1,
  "mizunami.gifu.jp": 1,
  "mizusawa.iwate.jp": 1,
  "mjondalen.no": 1,
  "mk.eu.org": 1,
  "mk.ua": 1,
  "mlbfan.org": 1,
  "mm": 2,
  "mmafan.biz": 1,
  "mn.it": 1,
  "mn.us": 1,
  "mo-i-rana.no": 1,
  "mo-siemens.io": 1,
  "mo.cn": 1,
  "mo.it": 1,
  "mo.us": 1,
  "moareke.no": 1,
  "mobara.chiba.jp": 1,
  "mobi.gp": 1,
  "mobi.ke": 1,
  "mobi.na": 1,
  "mobi.ng": 1,
  "mobi.tt": 1,
  "mobi.tz": 1,
  "mochizuki.nagano.jp": 1,
  "mock.pstmn.io": 1,
  "mod.gi": 1,
  "modalen.no": 1,
  "modelling.aero": 1,
  "modena.it": 1,
  "modern.museum": 1,
  "mods.jp": 1,
  "modum.no": 1,
  "moka.tochigi.jp": 1,
  "mol.it": 1,
  "molde.no": 1,
  "molise.it": 1,
  "moma.museum": 1,
  "mombetsu.hokkaido.jp": 1,
  "mond.jp": 1,
  "money.museum": 1,
  "mongolian.jp": 1,
  "monmouth.museum": 1,
  "monticello.museum": 1,
  "montreal.museum": 1,
  "monza-brianza.it": 1,
  "monza-e-della-brianza.it": 1,
  "monza.it": 1,
  "monzabrianza.it": 1,
  "monzaebrianza.it": 1,
  "monzaedellabrianza.it": 1,
  "moo.jp": 1,
  "moonscale.io": 2,
  "moonscale.net": 1,
  "mordovia.ru": 1,
  "mordovia.su": 1,
  "morena.br": 1,
  "moriguchi.osaka.jp": 1,
  "morimachi.shizuoka.jp": 1,
  "morioka.iwate.jp": 1,
  "moriya.ibaraki.jp": 1,
  "moriyama.shiga.jp": 1,
  "moriyoshi.akita.jp": 1,
  "morotsuka.miyazaki.jp": 1,
  "moroyama.saitama.jp": 1,
  "moscow.museum": 1,
  "moseushi.hokkaido.jp": 1,
  "mosjoen.no": 1,
  "moskenes.no": 1,
  "moss.no": 1,
  "mosvik.no": 1,
  "motegi.tochigi.jp": 1,
  "motobu.okinawa.jp": 1,
  "motorcycle.museum": 1,
  "motosu.gifu.jp": 1,
  "motoyama.kochi.jp": 1,
  "movimiento.bo": 1,
  "mozilla-iot.org": 1,
  "mp.br": 1,
  "mr.no": 1,
  "mragowo.pl": 1,
  "ms.gov.br": 1,
  "ms.it": 1,
  "ms.kr": 1,
  "ms.leg.br": 1,
  "ms.us": 1,
  "msk.ru": 1,
  "msk.su": 1,
  "mt.eu.org": 1,
  "mt.gov.br": 1,
  "mt.it": 1,
  "mt.leg.br": 1,
  "mt.us": 1,
  "muenchen.museum": 1,
  "muenster.museum": 1,
  "mugi.tokushima.jp": 1,
  "muika.niigata.jp": 1,
  "mukawa.hokkaido.jp": 1,
  "muko.kyoto.jp": 1,
  "mulhouse.museum": 1,
  "munakata.fukuoka.jp": 1,
  "muncie.museum": 1,
  "muni.il": 1,
  "muosat.no": 1,
  "mup.gov.pl": 1,
  "murakami.niigata.jp": 1,
  "murata.miyagi.jp": 1,
  "murayama.yamagata.jp": 1,
  "murmansk.su": 1,
  "muroran.hokkaido.jp": 1,
  "muroto.kochi.jp": 1,
  "mus.br": 1,
  "mus.mi.us": 1,
  "musashimurayama.tokyo.jp": 1,
  "musashino.tokyo.jp": 1,
  "museet.museum": 1,
  "museum.mv": 1,
  "museum.mw": 1,
  "museum.no": 1,
  "museum.om": 1,
  "museum.tt": 1,
  "museumcenter.museum": 1,
  "museumvereniging.museum": 1,
  "music.museum": 1,
  "musica.ar": 1,
  "musica.bo": 1,
  "musician.io": 1,
  "mutsu.aomori.jp": 1,
  "mutsuzawa.chiba.jp": 1,
  "mutual.ar": 1,
  "mw.gov.pl": 1,
  "mx.na": 1,
  "my-firewall.org": 1,
  "my-gateway.de": 1,
  "my-router.de": 1,
  "my-vigor.de": 1,
  "my-wan.de": 1,
  "my.eu.org": 1,
  "my.id": 1,
  "myactivedirectory.com": 1,
  "myamaze.net": 1,
  "myasustor.com": 1,
  "mycd.eu": 1,
  "mycloud.by": 1,
  "mydatto.com": 1,
  "mydatto.net": 1,
  "myddns.rocks": 1,
  "mydissent.net": 1,
  "mydobiss.com": 1,
  "mydrobo.com": 1,
  "myds.me": 1,
  "myeffect.net": 1,
  "myfast.host": 1,
  "myfast.space": 1,
  "myfirewall.org": 1,
  "myforum.community": 1,
  "myfritz.net": 1,
  "myftp.biz": 1,
  "myftp.org": 1,
  "myhome-server.de": 1,
  "myiphost.com": 1,
  "myjino.ru": 1,
  "mykolaiv.ua": 1,
  "mymailer.com.tw": 1,
  "mymediapc.net": 1,
  "myoko.niigata.jp": 1,
  "mypep.link": 1,
  "mypets.ws": 1,
  "myphotos.cc": 1,
  "mypi.co": 1,
  "mypsx.net": 1,
  "myqnapcloud.com": 1,
  "mysecuritycamera.com": 1,
  "mysecuritycamera.net": 1,
  "mysecuritycamera.org": 1,
  "myshopblocks.com": 1,
  "myshopify.com": 1,
  "myspreadshop.at": 1,
  "myspreadshop.be": 1,
  "myspreadshop.ca": 1,
  "myspreadshop.ch": 1,
  "myspreadshop.co.uk": 1,
  "myspreadshop.com": 1,
  "myspreadshop.com.au": 1,
  "myspreadshop.de": 1,
  "myspreadshop.dk": 1,
  "myspreadshop.es": 1,
  "myspreadshop.fi": 1,
  "myspreadshop.fr": 1,
  "myspreadshop.ie": 1,
  "myspreadshop.it": 1,
  "myspreadshop.net": 1,
  "myspreadshop.nl": 1,
  "myspreadshop.no": 1,
  "myspreadshop.pl": 1,
  "myspreadshop.se": 1,
  "mytabit.co.il": 1,
  "mytabit.com": 1,
  "mytis.ru": 1,
  "mytuleap.com": 1,
  "myvnc.com": 1,
  "mywire.org": 1,
  "n.bg": 1,
  "n.se": 1,
  "n4t.co": 1,
  "na.it": 1,
  "na4u.ru": 1,
  "naamesjevuemie.no": 1,
  "nabari.mie.jp": 1,
  "nachikatsuura.wakayama.jp": 1,
  "nagahama.shiga.jp": 1,
  "nagai.yamagata.jp": 1,
  "nagano.jp": 1,
  "nagano.nagano.jp": 1,
  "naganohara.gunma.jp": 1,
  "nagaoka.niigata.jp": 1,
  "nagaokakyo.kyoto.jp": 1,
  "nagara.chiba.jp": 1,
  "nagareyama.chiba.jp": 1,
  "nagasaki.jp": 1,
  "nagasaki.nagasaki.jp": 1,
  "nagasu.kumamoto.jp": 1,
  "nagato.yamaguchi.jp": 1,
  "nagatoro.saitama.jp": 1,
  "nagawa.nagano.jp": 1,
  "nagi.okayama.jp": 1,
  "nagiso.nagano.jp": 1,
  "nago.okinawa.jp": 1,
  "nagoya.jp": 2,
  "naha.okinawa.jp": 1,
  "nahari.kochi.jp": 1,
  "naie.hokkaido.jp": 1,
  "naka.hiroshima.jp": 1,
  "naka.ibaraki.jp": 1,
  "nakadomari.aomori.jp": 1,
  "nakagawa.fukuoka.jp": 1,
  "nakagawa.hokkaido.jp": 1,
  "nakagawa.nagano.jp": 1,
  "nakagawa.tokushima.jp": 1,
  "nakagusuku.okinawa.jp": 1,
  "nakagyo.kyoto.jp": 1,
  "nakai.kanagawa.jp": 1,
  "nakama.fukuoka.jp": 1,
  "nakamichi.yamanashi.jp": 1,
  "nakamura.kochi.jp": 1,
  "nakaniikawa.toyama.jp": 1,
  "nakano.nagano.jp": 1,
  "nakano.tokyo.jp": 1,
  "nakanojo.gunma.jp": 1,
  "nakanoto.ishikawa.jp": 1,
  "nakasatsunai.hokkaido.jp": 1,
  "nakatane.kagoshima.jp": 1,
  "nakatombetsu.hokkaido.jp": 1,
  "nakatsugawa.gifu.jp": 1,
  "nakayama.yamagata.jp": 1,
  "nakijin.okinawa.jp": 1,
  "naklo.pl": 1,
  "nalchik.ru": 1,
  "nalchik.su": 1,
  "namaste.jp": 1,
  "namdalseid.no": 1,
  "name.az": 1,
  "name.eg": 1,
  "name.et": 1,
  "name.fj": 1,
  "name.hr": 1,
  "name.jo": 1,
  "name.mk": 1,
  "name.mv": 1,
  "name.my": 1,
  "name.na": 1,
  "name.ng": 1,
  "name.pm": 1,
  "name.pr": 1,
  "name.qa": 1,
  "name.tj": 1,
  "name.tr": 1,
  "name.tt": 1,
  "name.vn": 1,
  "namegata.ibaraki.jp": 1,
  "namegawa.saitama.jp": 1,
  "namerikawa.toyama.jp": 1,
  "namie.fukushima.jp": 1,
  "namikata.ehime.jp": 1,
  "namsos.no": 1,
  "namsskogan.no": 1,
  "nanae.hokkaido.jp": 1,
  "nanao.ishikawa.jp": 1,
  "nanbu.tottori.jp": 1,
  "nanbu.yamanashi.jp": 1,
  "nango.fukushima.jp": 1,
  "nanjo.okinawa.jp": 1,
  "nankoku.kochi.jp": 1,
  "nanmoku.gunma.jp": 1,
  "nannestad.no": 1,
  "nanporo.hokkaido.jp": 1,
  "nantan.kyoto.jp": 1,
  "nanto.toyama.jp": 1,
  "nanyo.yamagata.jp": 1,
  "naoshima.kagawa.jp": 1,
  "naples.it": 1,
  "napoli.it": 1,
  "nara.jp": 1,
  "nara.nara.jp": 1,
  "narashino.chiba.jp": 1,
  "narita.chiba.jp": 1,
  "naroy.no": 1,
  "narusawa.yamanashi.jp": 1,
  "naruto.tokushima.jp": 1,
  "narviika.no": 1,
  "narvik.no": 1,
  "nasu.tochigi.jp": 1,
  "nasushiobara.tochigi.jp": 1,
  "nat.tn": 1,
  "natal.br": 1,
  "national.museum": 1,
  "nationalfirearms.museum": 1,
  "nationalheritage.museum": 1,
  "nativeamerican.museum": 1,
  "natori.miyagi.jp": 1,
  "natural.bo": 1,
  "naturalhistory.museum": 1,
  "naturalhistorymuseum.museum": 1,
  "naturalsciences.museum": 1,
  "naturbruksgymn.se": 1,
  "nature.museum": 1,
  "naturhistorisches.museum": 1,
  "natuurwetenschappen.museum": 1,
  "naumburg.museum": 1,
  "naustdal.no": 1,
  "naval.museum": 1,
  "navigation.aero": 1,
  "navoi.su": 1,
  "navuotna.no": 1,
  "nayoro.hokkaido.jp": 1,
  "nb.ca": 1,
  "nc.tr": 1,
  "nc.us": 1,
  "nd.us": 1,
  "ne.jp": 1,
  "ne.ke": 1,
  "ne.kr": 1,
  "ne.pw": 1,
  "ne.tz": 1,
  "ne.ug": 1,
  "ne.us": 1,
  "neat-url.com": 1,
  "nebraska.museum": 1,
  "nedre-eiker.no": 1,
  "neko.am": 1,
  "nemuro.hokkaido.jp": 1,
  "nerdpol.ovh": 1,
  "nerima.tokyo.jp": 1,
  "nes.akershus.no": 1,
  "nes.buskerud.no": 1,
  "nesna.no": 1,
  "nesodden.no": 1,
  "nesoddtangen.no": 1,
  "nesseby.no": 1,
  "nesset.no": 1,
  "net-freaks.com": 1,
  "net.ac": 1,
  "net.ae": 1,
  "net.af": 1,
  "net.ag": 1,
  "net.ai": 1,
  "net.al": 1,
  "net.am": 1,
  "net.ar": 1,
  "net.au": 1,
  "net.az": 1,
  "net.ba": 1,
  "net.bb": 1,
  "net.bh": 1,
  "net.bm": 1,
  "net.bn": 1,
  "net.bo": 1,
  "net.br": 1,
  "net.bs": 1,
  "net.bt": 1,
  "net.bz": 1,
  "net.ci": 1,
  "net.cm": 1,
  "net.cn": 1,
  "net.co": 1,
  "net.cu": 1,
  "net.cw": 1,
  "net.cy": 1,
  "net.dm": 1,
  "net.do": 1,
  "net.dz": 1,
  "net.ec": 1,
  "net.eg": 1,
  "net.et": 1,
  "net.eu.org": 1,
  "net.fj": 1,
  "net.fm": 1,
  "net.ge": 1,
  "net.gg": 1,
  "net.gl": 1,
  "net.gn": 1,
  "net.gp": 1,
  "net.gr": 1,
  "net.gt": 1,
  "net.gu": 1,
  "net.gy": 1,
  "net.hk": 1,
  "net.hn": 1,
  "net.ht": 1,
  "net.id": 1,
  "net.il": 1,
  "net.im": 1,
  "net.in": 1,
  "net.iq": 1,
  "net.ir": 1,
  "net.is": 1,
  "net.je": 1,
  "net.jo": 1,
  "net.kg": 1,
  "net.ki": 1,
  "net.kn": 1,
  "net.kw": 1,
  "net.ky": 1,
  "net.kz": 1,
  "net.la": 1,
  "net.lb": 1,
  "net.lc": 1,
  "net.lk": 1,
  "net.lr": 1,
  "net.ls": 1,
  "net.lv": 1,
  "net.ly": 1,
  "net.ma": 1,
  "net.me": 1,
  "net.mk": 1,
  "net.ml": 1,
  "net.mo": 1,
  "net.ms": 1,
  "net.mt": 1,
  "net.mu": 1,
  "net.mv": 1,
  "net.mw": 1,
  "net.mx": 1,
  "net.my": 1,
  "net.mz": 1,
  "net.nf": 1,
  "net.ng": 1,
  "net.ni": 1,
  "net.nr": 1,
  "net.nz": 1,
  "net.om": 1,
  "net.pa": 1,
  "net.pe": 1,
  "net.ph": 1,
  "net.pk": 1,
  "net.pl": 1,
  "net.pn": 1,
  "net.pr": 1,
  "net.ps": 1,
  "net.pt": 1,
  "net.py": 1,
  "net.qa": 1,
  "net.ru": 1,
  "net.rw": 1,
  "net.sa": 1,
  "net.sb": 1,
  "net.sc": 1,
  "net.sd": 1,
  "net.sg": 1,
  "net.sh": 1,
  "net.sl": 1,
  "net.so": 1,
  "net.ss": 1,
  "net.st": 1,
  "net.sy": 1,
  "net.th": 1,
  "net.tj": 1,
  "net.tm": 1,
  "net.tn": 1,
  "net.to": 1,
  "net.tr": 1,
  "net.tt": 1,
  "net.tw": 1,
  "net.ua": 1,
  "net.uk": 1,
  "net.uy": 1,
  "net.uz": 1,
  "net.vc": 1,
  "net.ve": 1,
  "net.vi": 1,
  "net.vn": 1,
  "net.vu": 1,
  "net.ws": 1,
  "net.ye": 1,
  "net.za": 1,
  "net.zm": 1,
  "netlify.app": 1,
  "neues.museum": 1,
  "newhampshire.museum": 1,
  "newjersey.museum": 1,
  "newmexico.museum": 1,
  "newport.museum": 1,
  "news.hu": 1,
  "newspaper.museum": 1,
  "newyork.museum": 1,
  "neyagawa.osaka.jp": 1,
  "nf.ca": 1,
  "nflfan.org": 1,
  "nfshost.com": 1,
  "ng.eu.org": 1,
  "ngo.lk": 1,
  "ngo.ng": 1,
  "ngo.ph": 1,
  "ngo.za": 1,
  "ngrok.io": 1,
  "nh-serv.co.uk": 1,
  "nh.us": 1,
  "nhlfan.net": 1,
  "nhs.uk": 1,
  "nic.in": 1,
  "nic.tj": 1,
  "nic.za": 1,
  "nichinan.miyazaki.jp": 1,
  "nichinan.tottori.jp": 1,
  "nid.io": 1,
  "niepce.museum": 1,
  "nieruchomosci.pl": 1,
  "niigata.jp": 1,
  "niigata.niigata.jp": 1,
  "niihama.ehime.jp": 1,
  "niikappu.hokkaido.jp": 1,
  "niimi.okayama.jp": 1,
  "niiza.saitama.jp": 1,
  "nikaho.akita.jp": 1,
  "niki.hokkaido.jp": 1,
  "nikita.jp": 1,
  "nikko.tochigi.jp": 1,
  "nikolaev.ua": 1,
  "ninohe.iwate.jp": 1,
  "ninomiya.kanagawa.jp": 1,
  "nirasaki.yamanashi.jp": 1,
  "nis.za": 1,
  "nishi.fukuoka.jp": 1,
  "nishi.osaka.jp": 1,
  "nishiaizu.fukushima.jp": 1,
  "nishiarita.saga.jp": 1,
  "nishiawakura.okayama.jp": 1,
  "nishiazai.shiga.jp": 1,
  "nishigo.fukushima.jp": 1,
  "nishihara.kumamoto.jp": 1,
  "nishihara.okinawa.jp": 1,
  "nishiizu.shizuoka.jp": 1,
  "nishikata.tochigi.jp": 1,
  "nishikatsura.yamanashi.jp": 1,
  "nishikawa.yamagata.jp": 1,
  "nishimera.miyazaki.jp": 1,
  "nishinomiya.hyogo.jp": 1,
  "nishinoomote.kagoshima.jp": 1,
  "nishinoshima.shimane.jp": 1,
  "nishio.aichi.jp": 1,
  "nishiokoppe.hokkaido.jp": 1,
  "nishitosa.kochi.jp": 1,
  "nishiwaki.hyogo.jp": 1,
  "nissedal.no": 1,
  "nisshin.aichi.jp": 1,
  "niteroi.br": 1,
  "nittedal.no": 1,
  "niyodogawa.kochi.jp": 1,
  "nj.us": 1,
  "njs.jelastic.vps-host.net": 1,
  "nl-ams-1.baremetal.scw.cloud": 1,
  "nl.ca": 1,
  "nl.ci": 1,
  "nl.eu.org": 1,
  "nl.no": 1,
  "nm.cn": 1,
  "nm.us": 1,
  "no-ip.biz": 1,
  "no-ip.ca": 1,
  "no-ip.co.uk": 1,
  "no-ip.info": 1,
  "no-ip.net": 1,
  "no-ip.org": 1,
  "no.com": 1,
  "no.eu.org": 1,
  "no.it": 1,
  "nobeoka.miyazaki.jp": 1,
  "noboribetsu.hokkaido.jp": 1,
  "nobushi.jp": 1,
  "noda.chiba.jp": 1,
  "noda.iwate.jp": 1,
  "nodebalancer.linode.com": 2,
  "nodes.k8s.fr-par.scw.cloud": 1,
  "nodes.k8s.nl-ams.scw.cloud": 1,
  "nodes.k8s.pl-waw.scw.cloud": 1,
  "nog.community": 1,
  "nogata.fukuoka.jp": 1,
  "nogi.tochigi.jp": 1,
  "noheji.aomori.jp": 1,
  "noho.st": 1,
  "nohost.me": 1,
  "noip.me": 1,
  "noip.us": 1,
  "nom.ad": 1,
  "nom.ag": 1,
  "nom.br": 2,
  "nom.co": 1,
  "nom.es": 1,
  "nom.fr": 1,
  "nom.km": 1,
  "nom.mg": 1,
  "nom.nc": 1,
  "nom.ni": 1,
  "nom.pa": 1,
  "nom.pe": 1,
  "nom.pl": 1,
  "nom.re": 1,
  "nom.ro": 1,
  "nom.tm": 1,
  "nom.ve": 1,
  "nom.za": 1,
  "nombre.bo": 1,
  "nome.cv": 1,
  "nome.pt": 1,
  "nomi.ishikawa.jp": 1,
  "nonoichi.ishikawa.jp": 1,
  "noop.app": 1,
  "noor.jp": 1,
  "nord-aurdal.no": 1,
  "nord-fron.no": 1,
  "nord-odal.no": 1,
  "norddal.no": 1,
  "nordeste-idc.saveincloud.net": 1,
  "nordkapp.no": 1,
  "nordre-land.no": 1,
  "nordreisa.no": 1,
  "nore-og-uvdal.no": 1,
  "norfolk.museum": 1,
  "north-kazakhstan.su": 1,
  "north.museum": 1,
  "northflank.app": 2,
  "nose.osaka.jp": 1,
  "nosegawa.nara.jp": 1,
  "noshiro.akita.jp": 1,
  "not.br": 1,
  "notaires.fr": 1,
  "notaires.km": 1,
  "noticeable.news": 1,
  "noticias.bo": 1,
  "noto.ishikawa.jp": 1,
  "notodden.no": 1,
  "notogawa.shiga.jp": 1,
  "notteroy.no": 1,
  "nov.ru": 1,
  "nov.su": 1,
  "novara.it": 1,
  "novecore.site": 1,
  "now-dns.net": 1,
  "now-dns.org": 1,
  "now-dns.top": 1,
  "now.sh": 1,
  "nowaruda.pl": 1,
  "nozawaonsen.nagano.jp": 1,
  "np": 2,
  "nrw.museum": 1,
  "ns.ca": 1,
  "nsn.us": 1,
  "nsupdate.info": 1,
  "nsw.au": 1,
  "nsw.edu.au": 1,
  "nt.au": 1,
  "nt.ca": 1,
  "nt.edu.au": 1,
  "nt.no": 1,
  "nt.ro": 1,
  "ntdll.top": 1,
  "ntr.br": 1,
  "nu.ca": 1,
  "nu.it": 1,
  "numata.gunma.jp": 1,
  "numata.hokkaido.jp": 1,
  "numazu.shizuoka.jp": 1,
  "nuoro.it": 1,
  "nv.us": 1,
  "nx.cn": 1,
  "ny-1.paas.massivegrid.net": 1,
  "ny-2.paas.massivegrid.net": 1,
  "ny.us": 1,
  "nyaa.am": 1,
  "nyan.to": 1,
  "nyc.mn": 1,
  "nyc.museum": 1,
  "nyny.museum": 1,
  "nysa.pl": 1,
  "nyuzen.toyama.jp": 1,
  "nz.basketball": 1,
  "nz.eu.org": 1,
  "o.bg": 1,
  "o.se": 1,
  "oamishirasato.chiba.jp": 1,
  "oarai.ibaraki.jp": 1,
  "obama.fukui.jp": 1,
  "obama.nagasaki.jp": 1,
  "obanazawa.yamagata.jp": 1,
  "obihiro.hokkaido.jp": 1,
  "obira.hokkaido.jp": 1,
  "obninsk.su": 1,
  "obu.aichi.jp": 1,
  "obuse.nagano.jp": 1,
  "oceanographic.museum": 1,
  "oceanographique.museum": 1,
  "ocelot.mythic-beasts.com": 1,
  "ochi.kochi.jp": 1,
  "oci.customer-oci.com": 2,
  "ocp.customer-oci.com": 2,
  "ocs.customer-oci.com": 2,
  "od.ua": 1,
  "odate.akita.jp": 1,
  "odawara.kanagawa.jp": 1,
  "odda.no": 1,
  "odesa.ua": 1,
  "odessa.ua": 1,
  "odo.br": 1,
  "oe.yamagata.jp": 1,
  "of.by": 1,
  "of.je": 1,
  "of.no": 1,
  "off.ai": 1,
  "office-on-the.net": 1,
  "official.academy": 1,
  "official.ec": 1,
  "ofunato.iwate.jp": 1,
  "og.ao": 1,
  "og.it": 1,
  "oga.akita.jp": 1,
  "ogaki.gifu.jp": 1,
  "ogano.saitama.jp": 1,
  "ogasawara.tokyo.jp": 1,
  "ogata.akita.jp": 1,
  "ogawa.ibaraki.jp": 1,
  "ogawa.nagano.jp": 1,
  "ogawa.saitama.jp": 1,
  "ogawara.miyagi.jp": 1,
  "ogi.saga.jp": 1,
  "ogimi.okinawa.jp": 1,
  "ogliastra.it": 1,
  "ogori.fukuoka.jp": 1,
  "ogose.saitama.jp": 1,
  "oguchi.aichi.jp": 1,
  "oguni.kumamoto.jp": 1,
  "oguni.yamagata.jp": 1,
  "oh.us": 1,
  "oharu.aichi.jp": 1,
  "ohda.shimane.jp": 1,
  "ohi.fukui.jp": 1,
  "ohira.miyagi.jp": 1,
  "ohira.tochigi.jp": 1,
  "ohkura.yamagata.jp": 1,
  "ohtawara.tochigi.jp": 1,
  "oi.kanagawa.jp": 1,
  "oirase.aomori.jp": 1,
  "oirm.gov.pl": 1,
  "oishida.yamagata.jp": 1,
  "oiso.kanagawa.jp": 1,
  "oita.jp": 1,
  "oita.oita.jp": 1,
  "oizumi.gunma.jp": 1,
  "oji.nara.jp": 1,
  "ojiya.niigata.jp": 1,
  "ok.us": 1,
  "okagaki.fukuoka.jp": 1,
  "okawa.fukuoka.jp": 1,
  "okawa.kochi.jp": 1,
  "okaya.nagano.jp": 1,
  "okayama.jp": 1,
  "okayama.okayama.jp": 1,
  "okazaki.aichi.jp": 1,
  "okegawa.saitama.jp": 1,
  "oketo.hokkaido.jp": 1,
  "oki.fukuoka.jp": 1,
  "okinawa.jp": 1,
  "okinawa.okinawa.jp": 1,
  "okinoshima.shimane.jp": 1,
  "okoppe.hokkaido.jp": 1,
  "oksnes.no": 1,
  "okuizumo.shimane.jp": 1,
  "okuma.fukushima.jp": 1,
  "okutama.tokyo.jp": 1,
  "ol.no": 1,
  "olawa.pl": 1,
  "olbia-tempio.it": 1,
  "olbiatempio.it": 1,
  "olecko.pl": 1,
  "olkusz.pl": 1,
  "olsztyn.pl": 1,
  "omachi.nagano.jp": 1,
  "omachi.saga.jp": 1,
  "omaezaki.shizuoka.jp": 1,
  "omaha.museum": 1,
  "omasvuotna.no": 1,
  "ome.tokyo.jp": 1,
  "omg.lol": 1,
  "omi.nagano.jp": 1,
  "omi.niigata.jp": 1,
  "omigawa.chiba.jp": 1,
  "omihachiman.shiga.jp": 1,
  "omitama.ibaraki.jp": 1,
  "omiya.saitama.jp": 1,
  "omniwe.site": 1,
  "omotego.fukushima.jp": 1,
  "omura.nagasaki.jp": 1,
  "omuta.fukuoka.jp": 1,
  "on-acorn.io": 2,
  "on-aptible.com": 1,
  "on-k3s.io": 2,
  "on-rancher.cloud": 2,
  "on-rio.io": 2,
  "on-the-web.tv": 1,
  "on-web.fr": 1,
  "on.ca": 1,
  "onagawa.miyagi.jp": 1,
  "onavstack.net": 1,
  "oncilla.mythic-beasts.com": 1,
  "ondigitalocean.app": 1,
  "onfabrica.com": 1,
  "onflashdrive.app": 1,
  "ong.br": 1,
  "onga.fukuoka.jp": 1,
  "onjuku.chiba.jp": 1,
  "online.museum": 1,
  "online.th": 1,
  "onna.okinawa.jp": 1,
  "ono.fukui.jp": 1,
  "ono.fukushima.jp": 1,
  "ono.hyogo.jp": 1,
  "onojo.fukuoka.jp": 1,
  "onomichi.hiroshima.jp": 1,
  "onporter.run": 1,
  "onred.one": 1,
  "onrender.com": 1,
  "ontario.museum": 1,
  "onthewifi.com": 1,
  "onza.mythic-beasts.com": 1,
  "ooguy.com": 1,
  "ookuwa.nagano.jp": 1,
  "oops.jp": 1,
  "ooshika.nagano.jp": 1,
  "openair.museum": 1,
  "opencraft.hosting": 1,
  "opensocial.site": 1,
  "operaunite.com": 1,
  "opoczno.pl": 1,
  "opole.pl": 1,
  "oppdal.no": 1,
  "oppegard.no": 1,
  "or.at": 1,
  "or.bi": 1,
  "or.ci": 1,
  "or.cr": 1,
  "or.id": 1,
  "or.it": 1,
  "or.jp": 1,
  "or.ke": 1,
  "or.kr": 1,
  "or.mu": 1,
  "or.na": 1,
  "or.pw": 1,
  "or.th": 1,
  "or.tz": 1,
  "or.ug": 1,
  "or.us": 1,
  "ora.gunma.jp": 1,
  "orangecloud.tn": 1,
  "oregon.museum": 1,
  "oregontrail.museum": 1,
  "org.ac": 1,
  "org.ae": 1,
  "org.af": 1,
  "org.ag": 1,
  "org.ai": 1,
  "org.al": 1,
  "org.am": 1,
  "org.ar": 1,
  "org.au": 1,
  "org.az": 1,
  "org.ba": 1,
  "org.bb": 1,
  "org.bh": 1,
  "org.bi": 1,
  "org.bm": 1,
  "org.bn": 1,
  "org.bo": 1,
  "org.br": 1,
  "org.bs": 1,
  "org.bt": 1,
  "org.bw": 1,
  "org.bz": 1,
  "org.ci": 1,
  "org.cn": 1,
  "org.co": 1,
  "org.cu": 1,
  "org.cv": 1,
  "org.cw": 1,
  "org.cy": 1,
  "org.dm": 1,
  "org.do": 1,
  "org.dz": 1,
  "org.ec": 1,
  "org.ee": 1,
  "org.eg": 1,
  "org.es": 1,
  "org.et": 1,
  "org.fj": 1,
  "org.fm": 1,
  "org.ge": 1,
  "org.gg": 1,
  "org.gh": 1,
  "org.gi": 1,
  "org.gl": 1,
  "org.gn": 1,
  "org.gp": 1,
  "org.gr": 1,
  "org.gt": 1,
  "org.gu": 1,
  "org.gy": 1,
  "org.hk": 1,
  "org.hn": 1,
  "org.ht": 1,
  "org.hu": 1,
  "org.il": 1,
  "org.im": 1,
  "org.in": 1,
  "org.iq": 1,
  "org.ir": 1,
  "org.is": 1,
  "org.je": 1,
  "org.jo": 1,
  "org.kg": 1,
  "org.ki": 1,
  "org.km": 1,
  "org.kn": 1,
  "org.kp": 1,
  "org.kw": 1,
  "org.ky": 1,
  "org.kz": 1,
  "org.la": 1,
  "org.lb": 1,
  "org.lc": 1,
  "org.lk": 1,
  "org.lr": 1,
  "org.ls": 1,
  "org.lv": 1,
  "org.ly": 1,
  "org.ma": 1,
  "org.me": 1,
  "org.mg": 1,
  "org.mk": 1,
  "org.ml": 1,
  "org.mn": 1,
  "org.mo": 1,
  "org.ms": 1,
  "org.mt": 1,
  "org.mu": 1,
  "org.mv": 1,
  "org.mw": 1,
  "org.mx": 1,
  "org.my": 1,
  "org.mz": 1,
  "org.na": 1,
  "org.ng": 1,
  "org.ni": 1,
  "org.nr": 1,
  "org.nz": 1,
  "org.om": 1,
  "org.pa": 1,
  "org.pe": 1,
  "org.pf": 1,
  "org.ph": 1,
  "org.pk": 1,
  "org.pl": 1,
  "org.pn": 1,
  "org.pr": 1,
  "org.ps": 1,
  "org.pt": 1,
  "org.py": 1,
  "org.qa": 1,
  "org.ro": 1,
  "org.rs": 1,
  "org.ru": 1,
  "org.rw": 1,
  "org.sa": 1,
  "org.sb": 1,
  "org.sc": 1,
  "org.sd": 1,
  "org.se": 1,
  "org.sg": 1,
  "org.sh": 1,
  "org.sl": 1,
  "org.sn": 1,
  "org.so": 1,
  "org.ss": 1,
  "org.st": 1,
  "org.sv": 1,
  "org.sy": 1,
  "org.sz": 1,
  "org.tj": 1,
  "org.tm": 1,
  "org.tn": 1,
  "org.to": 1,
  "org.tr": 1,
  "org.tt": 1,
  "org.tw": 1,
  "org.ua": 1,
  "org.ug": 1,
  "org.uk": 1,
  "org.uy": 1,
  "org.uz": 1,
  "org.vc": 1,
  "org.ve": 1,
  "org.vi": 1,
  "org.vn": 1,
  "org.vu": 1,
  "org.ws": 1,
  "org.ye": 1,
  "org.yt": 1,
  "org.za": 1,
  "org.zm": 1,
  "org.zw": 1,
  "oristano.it": 1,
  "orkanger.no": 1,
  "orkdal.no": 1,
  "orland.no": 1,
  "orsites.com": 1,
  "orskog.no": 1,
  "orsta.no": 1,
  "orx.biz": 1,
  "os.hedmark.no": 1,
  "os.hordaland.no": 1,
  "osaka.jp": 1,
  "osakasayama.osaka.jp": 1,
  "osaki.miyagi.jp": 1,
  "osakikamijima.hiroshima.jp": 1,
  "osasco.br": 1,
  "osen.no": 1,
  "oseto.nagasaki.jp": 1,
  "oshima.tokyo.jp": 1,
  "oshima.yamaguchi.jp": 1,
  "oshino.yamanashi.jp": 1,
  "oshu.iwate.jp": 1,
  "oslo.no": 1,
  "osoyro.no": 1,
  "osteroy.no": 1,
  "ostre-toten.no": 1,
  "ostroda.pl": 1,
  "ostroleka.pl": 1,
  "ostrowiec.pl": 1,
  "ostrowwlkp.pl": 1,
  "ot.it": 1,
  "ota.gunma.jp": 1,
  "ota.tokyo.jp": 1,
  "otago.museum": 1,
  "otake.hiroshima.jp": 1,
  "otaki.chiba.jp": 1,
  "otaki.nagano.jp": 1,
  "otaki.saitama.jp": 1,
  "otama.fukushima.jp": 1,
  "otap.co": 2,
  "otari.nagano.jp": 1,
  "otaru.hokkaido.jp": 1,
  "other.nf": 1,
  "oto.fukuoka.jp": 1,
  "otobe.hokkaido.jp": 1,
  "otofuke.hokkaido.jp": 1,
  "otoineppu.hokkaido.jp": 1,
  "otoyo.kochi.jp": 1,
  "otsu.shiga.jp": 1,
  "otsuchi.iwate.jp": 1,
  "otsuki.kochi.jp": 1,
  "otsuki.yamanashi.jp": 1,
  "ouchi.saga.jp": 1,
  "ouda.nara.jp": 1,
  "oum.gov.pl": 1,
  "oumu.hokkaido.jp": 1,
  "outsystemscloud.com": 1,
  "overhalla.no": 1,
  "ovre-eiker.no": 1,
  "owani.aomori.jp": 1,
  "owariasahi.aichi.jp": 1,
  "own.pm": 1,
  "ownip.net": 1,
  "ownprovider.com": 1,
  "owo.codes": 2,
  "ox.rs": 1,
  "oxa.cloud": 1,
  "oxford.museum": 1,
  "oy.lc": 1,
  "oya.to": 1,
  "oyabe.toyama.jp": 1,
  "oyama.tochigi.jp": 1,
  "oyamazaki.kyoto.jp": 1,
  "oyer.no": 1,
  "oygarden.no": 1,
  "oyodo.nara.jp": 1,
  "oystre-slidre.no": 1,
  "oz.au": 1,
  "ozora.hokkaido.jp": 1,
  "ozu.ehime.jp": 1,
  "ozu.kumamoto.jp": 1,
  "p.bg": 1,
  "p.se": 1,
  "pa.gov.br": 1,
  "pa.gov.pl": 1,
  "pa.it": 1,
  "pa.leg.br": 1,
  "pa.us": 1,
  "paas.beebyte.io": 1,
  "paas.datacenter.fi": 1,
  "paas.hosted-by-previder.com": 1,
  "paas.massivegrid.com": 1,
  "pacific.museum": 1,
  "paderborn.museum": 1,
  "padova.it": 1,
  "padua.it": 1,
  "pagefrontapp.com": 1,
  "pages.dev": 1,
  "pages.it.hs-heilbronn.de": 1,
  "pages.torproject.net": 1,
  "pages.wiardweb.com": 1,
  "pagespeedmobilizer.com": 1,
  "pagexl.com": 1,
  "palace.museum": 1,
  "paleo.museum": 1,
  "palermo.it": 1,
  "palmas.br": 1,
  "palmsprings.museum": 1,
  "panama.museum": 1,
  "panel.gg": 1,
  "pantheonsite.io": 1,
  "parachuting.aero": 1,
  "paragliding.aero": 1,
  "parallel.jp": 1,
  "parasite.jp": 1,
  "paris.eu.org": 1,
  "paris.museum": 1,
  "parliament.nz": 1,
  "parma.it": 1,
  "paroch.k12.ma.us": 1,
  "parti.se": 1,
  "pasadena.museum": 1,
  "passenger-association.aero": 1,
  "patria.bo": 1,
  "pavia.it": 1,
  "paywhirl.com": 2,
  "pb.ao": 1,
  "pb.gov.br": 1,
  "pb.leg.br": 1,
  "pc.it": 1,
  "pc.pl": 1,
  "pcloud.host": 1,
  "pd.it": 1,
  "pdns.page": 1,
  "pe.ca": 1,
  "pe.gov.br": 1,
  "pe.it": 1,
  "pe.kr": 1,
  "pe.leg.br": 1,
  "pecori.jp": 1,
  "peewee.jp": 1,
  "penne.jp": 1,
  "penza.su": 1,
  "pepper.jp": 1,
  "per.la": 1,
  "per.nf": 1,
  "per.sg": 1,
  "perma.jp": 1,
  "perso.ht": 1,
  "perso.sn": 1,
  "perso.tn": 1,
  "perspecta.cloud": 1,
  "perugia.it": 1,
  "pesaro-urbino.it": 1,
  "pesarourbino.it": 1,
  "pescara.it": 1,
  "pg": 2,
  "pg.in": 1,
  "pg.it": 1,
  "pgafan.net": 1,
  "pgfog.com": 1,
  "pharmacien.fr": 1,
  "pharmaciens.km": 1,
  "pharmacy.museum": 1,
  "philadelphia.museum": 1,
  "philadelphiaarea.museum": 1,
  "philately.museum": 1,
  "phoenix.museum": 1,
  "photography.museum": 1,
  "phx.enscaled.us": 1,
  "pi.gov.br": 1,
  "pi.it": 1,
  "pi.leg.br": 1,
  "piacenza.it": 1,
  "piedmont.it": 1,
  "piemonte.it": 1,
  "pigboat.jp": 1,
  "pila.pl": 1,
  "pilot.aero": 1,
  "pilots.museum": 1,
  "pimienta.org": 1,
  "pinb.gov.pl": 1,
  "pinoko.jp": 1,
  "pippu.hokkaido.jp": 1,
  "pisa.it": 1,
  "pistoia.it": 1,
  "pisz.pl": 1,
  "pittsburgh.museum": 1,
  "piw.gov.pl": 1,
  "pixolino.com": 1,
  "pl.eu.org": 1,
  "pl.ua": 1,
  "planetarium.museum": 1,
  "plantation.museum": 1,
  "plants.museum": 1,
  "platform0.app": 1,
  "platformsh.site": 2,
  "platter-app.com": 1,
  "platter-app.dev": 1,
  "platterp.us": 1,
  "playstation-cloud.com": 1,
  "plaza.museum": 1,
  "plc.co.im": 1,
  "plc.ly": 1,
  "plc.uk": 1,
  "plesk.page": 1,
  "pleskns.com": 1,
  "plo.ps": 1,
  "plurinacional.bo": 1,
  "pmn.it": 1,
  "pn.it": 1,
  "po.gov.pl": 1,
  "po.it": 1,
  "poa.br": 1,
  "podhale.pl": 1,
  "podlasie.pl": 1,
  "podzone.net": 1,
  "podzone.org": 1,
  "point2this.com": 1,
  "pointto.us": 1,
  "poivron.org": 1,
  "pokrovsk.su": 1,
  "pol.dz": 1,
  "pol.ht": 1,
  "pol.tr": 1,
  "police.uk": 1,
  "politica.bo": 1,
  "polkowice.pl": 1,
  "poltava.ua": 1,
  "pomorskie.pl": 1,
  "pomorze.pl": 1,
  "poniatowa.pl": 1,
  "ponpes.id": 1,
  "pordenone.it": 1,
  "porsanger.no": 1,
  "porsangu.no": 1,
  "porsgrunn.no": 1,
  "port.fr": 1,
  "portal.museum": 1,
  "portland.museum": 1,
  "portlligat.museum": 1,
  "post.in": 1,
  "postman-echo.com": 1,
  "posts-and-telecommunications.museum": 1,
  "potager.org": 1,
  "potenza.it": 1,
  "powiat.pl": 1,
  "poznan.pl": 1,
  "pp.az": 1,
  "pp.ru": 1,
  "pp.se": 1,
  "pp.ua": 1,
  "ppg.br": 1,
  "pr.gov.br": 1,
  "pr.it": 1,
  "pr.leg.br": 1,
  "pr.us": 1,
  "prato.it": 1,
  "prd.fr": 1,
  "prd.km": 1,
  "prd.mg": 1,
  "prequalifyme.today": 1,
  "preservation.museum": 1,
  "presidio.museum": 1,
  "press.aero": 1,
  "press.cy": 1,
  "press.ma": 1,
  "press.museum": 1,
  "press.se": 1,
  "presse.ci": 1,
  "presse.km": 1,
  "presse.ml": 1,
  "pri.ee": 1,
  "primetel.cloud": 1,
  "principe.st": 1,
  "priv.at": 1,
  "priv.hu": 1,
  "priv.instances.scw.cloud": 1,
  "priv.me": 1,
  "priv.no": 1,
  "priv.pl": 1,
  "privatizehealthinsurance.net": 1,
  "pro.az": 1,
  "pro.br": 1,
  "pro.cy": 1,
  "pro.ec": 1,
  "pro.fj": 1,
  "pro.ht": 1,
  "pro.in": 1,
  "pro.mv": 1,
  "pro.na": 1,
  "pro.om": 1,
  "pro.pr": 1,
  "pro.tt": 1,
  "pro.typeform.com": 1,
  "pro.vn": 1,
  "prochowice.pl": 1,
  "production.aero": 1,
  "prof.pr": 1,
  "profesional.bo": 1,
  "project.museum": 1,
  "protonet.io": 1,
  "pruszkow.pl": 1,
  "prvcy.page": 1,
  "przeworsk.pl": 1,
  "psc.br": 1,
  "psi.br": 1,
  "psp.gov.pl": 1,
  "psse.gov.pl": 1,
  "pstmn.io": 1,
  "pt.eu.org": 1,
  "pt.it": 1,
  "pu.it": 1,
  "pub.instances.scw.cloud": 1,
  "pub.sa": 1,
  "publ.pt": 1,
  "public-inquiry.uk": 1,
  "public.museum": 1,
  "publishproxy.com": 1,
  "pubol.museum": 1,
  "pubtls.org": 1,
  "pueblo.bo": 1,
  "pug.it": 1,
  "puglia.it": 1,
  "pulawy.pl": 1,
  "punyu.jp": 1,
  "pup.gov.pl": 1,
  "pupu.jp": 1,
  "pussycat.jp": 1,
  "pv.it": 1,
  "pvh.br": 1,
  "pvt.ge": 1,
  "pvt.k12.ma.us": 1,
  "pya.jp": 1,
  "pyatigorsk.ru": 1,
  "pymnt.uk": 1,
  "pythonanywhere.com": 1,
  "pz.it": 1,
  "q-a.eu.org": 1,
  "q.bg": 1,
  "qa2.com": 1,
  "qbuser.com": 1,
  "qc.ca": 1,
  "qc.com": 1,
  "qcx.io": 1,
  "qh.cn": 1,
  "qld.au": 1,
  "qld.edu.au": 1,
  "qld.gov.au": 1,
  "qoto.io": 1,
  "qsl.br": 1,
  "qualifioapp.com": 1,
  "quebec.museum": 1,
  "quicksytes.com": 1,
  "quipelements.com": 2,
  "r.appspot.com": 2,
  "r.bg": 1,
  "r.cdn77.net": 1,
  "r.se": 1,
  "r2.dev": 1,
  "ra.it": 1,
  "rackmaze.com": 1,
  "rackmaze.net": 1,
  "rade.no": 1,
  "radio.am": 1,
  "radio.br": 1,
  "radio.fm": 1,
  "radom.pl": 1,
  "radoy.no": 1,
  "raffleentry.org.uk": 1,
  "rag-cloud-ch.hosteur.com": 1,
  "rag-cloud.hosteur.com": 1,
  "ragusa.it": 1,
  "rahkkeravju.no": 1,
  "raholt.no": 1,
  "railroad.museum": 1,
  "railway.museum": 1,
  "raindrop.jp": 1,
  "raisa.no": 1,
  "rakkestad.no": 1,
  "ralingen.no": 1,
  "rana.no": 1,
  "randaberg.no": 1,
  "rankoshi.hokkaido.jp": 1,
  "ranzan.saitama.jp": 1,
  "rar.ve": 1,
  "ras.ru": 1,
  "rauma.no": 1,
  "ravendb.cloud": 1,
  "ravendb.community": 1,
  "ravendb.me": 1,
  "ravendb.run": 1,
  "ravenna.it": 1,
  "ravpage.co.il": 1,
  "rawa-maz.pl": 1,
  "rc.it": 1,
  "rdv.to": 1,
  "re.it": 1,
  "re.kr": 1,
  "read-books.org": 1,
  "readmyblog.org": 1,
  "readthedocs.io": 1,
  "readymade.jp": 1,
  "realestate.pl": 1,
  "realm.cz": 1,
  "rebun.hokkaido.jp": 1,
  "rec.br": 1,
  "rec.co": 1,
  "rec.nf": 1,
  "rec.ro": 1,
  "rec.ve": 1,
  "recht.pro": 1,
  "recife.br": 1,
  "recreation.aero": 1,
  "red.sv": 1,
  "redirectme.net": 1,
  "reg.dk": 1,
  "reggio-calabria.it": 1,
  "reggio-emilia.it": 1,
  "reggiocalabria.it": 1,
  "reggioemilia.it": 1,
  "reklam.hu": 1,
  "rel.ht": 1,
  "rel.pl": 1,
  "remotewd.com": 1,
  "rendalen.no": 1,
  "rennebu.no": 1,
  "rennesoy.no": 1,
  "rep.br": 1,
  "rep.kp": 1,
  "repbody.aero": 1,
  "repl.co": 1,
  "repl.run": 1,
  "res.aero": 1,
  "res.in": 1,
  "research.aero": 1,
  "research.museum": 1,
  "reservd.com": 1,
  "reservd.dev.thingdust.io": 1,
  "reservd.disrec.thingdust.io": 1,
  "reservd.testing.thingdust.io": 1,
  "reserve-online.com": 1,
  "reserve-online.net": 1,
  "resindevice.io": 1,
  "resistance.museum": 1,
  "revista.bo": 1,
  "rg.it": 1,
  "rhcloud.com": 1,
  "ri.it": 1,
  "ri.us": 1,
  "ribeirao.br": 1,
  "ric.jelastic.vps-host.net": 1,
  "rieti.it": 1,
  "rifu.miyagi.jp": 1,
  "riik.ee": 1,
  "rikubetsu.hokkaido.jp": 1,
  "rikuzentakata.iwate.jp": 1,
  "rimini.it": 1,
  "rindal.no": 1,
  "ringebu.no": 1,
  "ringerike.no": 1,
  "ringsaker.no": 1,
  "rio.br": 1,
  "riobranco.br": 1,
  "riodejaneiro.museum": 1,
  "riopreto.br": 1,
  "rishiri.hokkaido.jp": 1,
  "rishirifuji.hokkaido.jp": 1,
  "risor.no": 1,
  "rissa.no": 1,
  "ritto.shiga.jp": 1,
  "rivne.ua": 1,
  "rj.gov.br": 1,
  "rj.leg.br": 1,
  "rl.no": 1,
  "rm.it": 1,
  "rn.gov.br": 1,
  "rn.it": 1,
  "rn.leg.br": 1,
  "ro.eu.org": 1,
  "ro.gov.br": 1,
  "ro.im": 1,
  "ro.it": 1,
  "ro.leg.br": 1,
  "roan.no": 1,
  "rochester.museum": 1,
  "rockart.museum": 1,
  "rocky.page": 1,
  "rodoy.no": 1,
  "rokunohe.aomori.jp": 1,
  "rollag.no": 1,
  "roma.it": 1,
  "roma.museum": 1,
  "rome.it": 1,
  "romsa.no": 1,
  "romskog.no": 1,
  "roros.no": 1,
  "rost.no": 1,
  "rotorcraft.aero": 1,
  "router.management": 1,
  "rovigo.it": 1,
  "rovno.ua": 1,
  "royal-commission.uk": 1,
  "royken.no": 1,
  "royrvik.no": 1,
  "rr.gov.br": 1,
  "rr.leg.br": 1,
  "rs.ba": 1,
  "rs.gov.br": 1,
  "rs.leg.br": 1,
  "rsc.cdn77.org": 1,
  "rss.my.id": 2,
  "ru.com": 1,
  "ru.eu.org": 1,
  "ru.net": 1,
  "run.app": 1,
  "ruovat.no": 1,
  "russia.museum": 1,
  "rv.ua": 1,
  "rybnik.pl": 1,
  "ryd.wafaicloud.com": 1,
  "rygge.no": 1,
  "ryokami.saitama.jp": 1,
  "ryugasaki.ibaraki.jp": 1,
  "ryuoh.shiga.jp": 1,
  "rzeszow.pl": 1,
  "rzgw.gov.pl": 1,
  "s.bg": 1,
  "s.se": 1,
  "s3-ap-northeast-1.amazonaws.com": 1,
  "s3-ap-northeast-2.amazonaws.com": 1,
  "s3-ap-south-1.amazonaws.com": 1,
  "s3-ap-southeast-1.amazonaws.com": 1,
  "s3-ap-southeast-2.amazonaws.com": 1,
  "s3-ca-central-1.amazonaws.com": 1,
  "s3-eu-central-1.amazonaws.com": 1,
  "s3-eu-west-1.amazonaws.com": 1,
  "s3-eu-west-2.amazonaws.com": 1,
  "s3-eu-west-3.amazonaws.com": 1,
  "s3-external-1.amazonaws.com": 1,
  "s3-fips-us-gov-west-1.amazonaws.com": 1,
  "s3-sa-east-1.amazonaws.com": 1,
  "s3-us-east-2.amazonaws.com": 1,
  "s3-us-gov-west-1.amazonaws.com": 1,
  "s3-us-west-1.amazonaws.com": 1,
  "s3-us-west-2.amazonaws.com": 1,
  "s3-website-ap-northeast-1.amazonaws.com": 1,
  "s3-website-ap-southeast-1.amazonaws.com": 1,
  "s3-website-ap-southeast-2.amazonaws.com": 1,
  "s3-website-eu-west-1.amazonaws.com": 1,
  "s3-website-sa-east-1.amazonaws.com": 1,
  "s3-website-us-east-1.amazonaws.com": 1,
  "s3-website-us-west-1.amazonaws.com": 1,
  "s3-website-us-west-2.amazonaws.com": 1,
  "s3-website.ap-northeast-2.amazonaws.com": 1,
  "s3-website.ap-south-1.amazonaws.com": 1,
  "s3-website.ca-central-1.amazonaws.com": 1,
  "s3-website.eu-central-1.amazonaws.com": 1,
  "s3-website.eu-west-2.amazonaws.com": 1,
  "s3-website.eu-west-3.amazonaws.com": 1,
  "s3-website.fr-par.scw.cloud": 1,
  "s3-website.nl-ams.scw.cloud": 1,
  "s3-website.pl-waw.scw.cloud": 1,
  "s3-website.us-east-2.amazonaws.com": 1,
  "s3.amazonaws.com": 1,
  "s3.ap-northeast-2.amazonaws.com": 1,
  "s3.ap-south-1.amazonaws.com": 1,
  "s3.ca-central-1.amazonaws.com": 1,
  "s3.cn-north-1.amazonaws.com.cn": 1,
  "s3.dualstack.ap-northeast-1.amazonaws.com": 1,
  "s3.dualstack.ap-northeast-2.amazonaws.com": 1,
  "s3.dualstack.ap-south-1.amazonaws.com": 1,
  "s3.dualstack.ap-southeast-1.amazonaws.com": 1,
  "s3.dualstack.ap-southeast-2.amazonaws.com": 1,
  "s3.dualstack.ca-central-1.amazonaws.com": 1,
  "s3.dualstack.eu-central-1.amazonaws.com": 1,
  "s3.dualstack.eu-west-1.amazonaws.com": 1,
  "s3.dualstack.eu-west-2.amazonaws.com": 1,
  "s3.dualstack.eu-west-3.amazonaws.com": 1,
  "s3.dualstack.sa-east-1.amazonaws.com": 1,
  "s3.dualstack.us-east-1.amazonaws.com": 1,
  "s3.dualstack.us-east-2.amazonaws.com": 1,
  "s3.eu-central-1.amazonaws.com": 1,
  "s3.eu-west-2.amazonaws.com": 1,
  "s3.eu-west-3.amazonaws.com": 1,
  "s3.fr-par.scw.cloud": 1,
  "s3.nl-ams.scw.cloud": 1,
  "s3.pl-waw.scw.cloud": 1,
  "s3.teckids.org": 1,
  "s3.us-east-2.amazonaws.com": 1,
  "s5y.io": 2,
  "sa-east-1.elasticbeanstalk.com": 1,
  "sa.au": 1,
  "sa.com": 1,
  "sa.cr": 1,
  "sa.edu.au": 1,
  "sa.gov.au": 1,
  "sa.gov.pl": 1,
  "sa.it": 1,
  "sabae.fukui.jp": 1,
  "sadist.jp": 1,
  "sado.niigata.jp": 1,
  "safety.aero": 1,
  "saga.jp": 1,
  "saga.saga.jp": 1,
  "sagae.yamagata.jp": 1,
  "sagamihara.kanagawa.jp": 1,
  "saigawa.fukuoka.jp": 1,
  "saijo.ehime.jp": 1,
  "saikai.nagasaki.jp": 1,
  "saiki.oita.jp": 1,
  "saintlouis.museum": 1,
  "saitama.jp": 1,
  "saitama.saitama.jp": 1,
  "saito.miyazaki.jp": 1,
  "saka.hiroshima.jp": 1,
  "sakado.saitama.jp": 1,
  "sakae.chiba.jp": 1,
  "sakae.nagano.jp": 1,
  "sakahogi.gifu.jp": 1,
  "sakai.fukui.jp": 1,
  "sakai.ibaraki.jp": 1,
  "sakai.osaka.jp": 1,
  "sakaiminato.tottori.jp": 1,
  "sakaki.nagano.jp": 1,
  "sakata.yamagata.jp": 1,
  "sakawa.kochi.jp": 1,
  "sakegawa.yamagata.jp": 1,
  "saku.nagano.jp": 1,
  "sakuho.nagano.jp": 1,
  "sakura.chiba.jp": 1,
  "sakura.tochigi.jp": 1,
  "sakuragawa.ibaraki.jp": 1,
  "sakurai.nara.jp": 1,
  "sakyo.kyoto.jp": 1,
  "salangen.no": 1,
  "salat.no": 1,
  "salem.museum": 1,
  "salerno.it": 1,
  "saltdal.no": 1,
  "salud.bo": 1,
  "salvador.br": 1,
  "salvadordali.museum": 1,
  "salzburg.museum": 1,
  "samegawa.fukushima.jp": 1,
  "samnanger.no": 1,
  "sampa.br": 1,
  "samukawa.kanagawa.jp": 1,
  "sanagochi.tokushima.jp": 1,
  "sanda.hyogo.jp": 1,
  "sandcats.io": 1,
  "sande.more-og-romsdal.no": 1,
  "sande.vestfold.no": 1,
  "sande.xn--mre-og-romsdal-qqb.no": 1,
  "sandefjord.no": 1,
  "sandiego.museum": 1,
  "sandnes.no": 1,
  "sandnessjoen.no": 1,
  "sandoy.no": 1,
  "sanfrancisco.museum": 1,
  "sango.nara.jp": 1,
  "sanjo.niigata.jp": 1,
  "sannan.hyogo.jp": 1,
  "sannohe.aomori.jp": 1,
  "sano.tochigi.jp": 1,
  "sanok.pl": 1,
  "santabarbara.museum": 1,
  "santacruz.museum": 1,
  "santafe.museum": 1,
  "santamaria.br": 1,
  "santoandre.br": 1,
  "sanuki.kagawa.jp": 1,
  "saobernardo.br": 1,
  "saogonca.br": 1,
  "saotome.st": 1,
  "sapporo.jp": 2,
  "sar.it": 1,
  "sardegna.it": 1,
  "sardinia.it": 1,
  "saroma.hokkaido.jp": 1,
  "sarpsborg.no": 1,
  "sarufutsu.hokkaido.jp": 1,
  "sasaguri.fukuoka.jp": 1,
  "sasayama.hyogo.jp": 1,
  "sasebo.nagasaki.jp": 1,
  "saskatchewan.museum": 1,
  "sassari.it": 1,
  "satosho.okayama.jp": 1,
  "satsumasendai.kagoshima.jp": 1,
  "satte.saitama.jp": 1,
  "satx.museum": 1,
  "sauda.no": 1,
  "sauherad.no": 1,
  "savannahga.museum": 1,
  "saves-the-whales.com": 1,
  "savona.it": 1,
  "sayama.osaka.jp": 1,
  "sayama.saitama.jp": 1,
  "sayo.hyogo.jp": 1,
  "sb.ua": 1,
  "sc.cn": 1,
  "sc.gov.br": 1,
  "sc.ke": 1,
  "sc.kr": 1,
  "sc.leg.br": 1,
  "sc.ls": 1,
  "sc.tz": 1,
  "sc.ug": 1,
  "sc.us": 1,
  "scalebook.scw.cloud": 1,
  "sch.ae": 1,
  "sch.id": 1,
  "sch.ir": 1,
  "sch.jo": 1,
  "sch.lk": 1,
  "sch.ly": 1,
  "sch.ng": 1,
  "sch.qa": 1,
  "sch.sa": 1,
  "sch.so": 1,
  "sch.ss": 1,
  "sch.tf": 1,
  "sch.uk": 2,
  "sch.wf": 1,
  "sch.zm": 1,
  "schlesisches.museum": 1,
  "schoenbrunn.museum": 1,
  "schokokeks.net": 1,
  "schokoladen.museum": 1,
  "school.museum": 1,
  "school.na": 1,
  "school.nz": 1,
  "school.za": 1,
  "schoolbus.jp": 1,
  "schools.nsw.edu.au": 1,
  "schulplattform.de": 1,
  "schulserver.de": 1,
  "schweiz.museum": 1,
  "sci.eg": 1,
  "science-fiction.museum": 1,
  "science.museum": 1,
  "scienceandhistory.museum": 1,
  "scienceandindustry.museum": 1,
  "sciencecenter.museum": 1,
  "sciencecenters.museum": 1,
  "sciencehistory.museum": 1,
  "sciences.museum": 1,
  "sciencesnaturelles.museum": 1,
  "scientist.aero": 1,
  "scotland.museum": 1,
  "scrapper-site.net": 1,
  "scrapping.cc": 1,
  "scrysec.com": 1,
  "sd.cn": 1,
  "sd.us": 1,
  "sdn.gov.pl": 1,
  "sdscloud.pl": 1,
  "se.eu.org": 1,
  "se.gov.br": 1,
  "se.leg.br": 1,
  "se.net": 1,
  "seaport.museum": 1,
  "sebastopol.ua": 1,
  "sec.ps": 1,
  "secaas.hk": 1,
  "secret.jp": 1,
  "securitytactics.com": 1,
  "seg.br": 1,
  "seidat.net": 1,
  "seihi.nagasaki.jp": 1,
  "seika.kyoto.jp": 1,
  "seiro.niigata.jp": 1,
  "seirou.niigata.jp": 1,
  "seiyo.ehime.jp": 1,
  "sejny.pl": 1,
  "sekd1.beebyteapp.io": 1,
  "seki.gifu.jp": 1,
  "sekigahara.gifu.jp": 1,
  "sekikawa.niigata.jp": 1,
  "sel.no": 1,
  "selbu.no": 1,
  "selfip.biz": 1,
  "selfip.com": 1,
  "selfip.info": 1,
  "selfip.net": 1,
  "selfip.org": 1,
  "selje.no": 1,
  "seljord.no": 1,
  "sellfy.store": 1,
  "sells-for-less.com": 1,
  "sells-for-u.com": 1,
  "sells-it.net": 1,
  "sellsyourhome.org": 1,
  "semboku.akita.jp": 1,
  "semine.miyagi.jp": 1,
  "senasa.ar": 1,
  "sendai.jp": 2,
  "sennan.osaka.jp": 1,
  "senseering.net": 1,
  "sensiosite.cloud": 2,
  "seoul.kr": 1,
  "sera.hiroshima.jp": 1,
  "seranishi.hiroshima.jp": 1,
  "servebbs.com": 1,
  "servebbs.net": 1,
  "servebbs.org": 1,
  "servebeer.com": 1,
  "serveblog.net": 1,
  "servecounterstrike.com": 1,
  "serveexchange.com": 1,
  "serveftp.com": 1,
  "serveftp.net": 1,
  "serveftp.org": 1,
  "servegame.com": 1,
  "servegame.org": 1,
  "servehalflife.com": 1,
  "servehttp.com": 1,
  "servehumour.com": 1,
  "serveirc.com": 1,
  "serveminecraft.net": 1,
  "servemp3.com": 1,
  "servep2p.com": 1,
  "servepics.com": 1,
  "servequake.com": 1,
  "servers.run": 1,
  "servesarcasm.com": 1,
  "service.gov.scot": 1,
  "service.gov.uk": 1,
  "service.one": 1,
  "services.aero": 1,
  "setagaya.tokyo.jp": 1,
  "seto.aichi.jp": 1,
  "setouchi.okayama.jp": 1,
  "settlement.museum": 1,
  "settlers.museum": 1,
  "settsu.osaka.jp": 1,
  "sevastopol.ua": 1,
  "sex.hu": 1,
  "sex.pl": 1,
  "sf.no": 1,
  "sg-1.paas.massivegrid.net": 1,
  "sh.cn": 1,
  "shacknet.nu": 1,
  "shakotan.hokkaido.jp": 1,
  "shari.hokkaido.jp": 1,
  "shell.museum": 1,
  "sherbrooke.museum": 1,
  "shibata.miyagi.jp": 1,
  "shibata.niigata.jp": 1,
  "shibecha.hokkaido.jp": 1,
  "shibetsu.hokkaido.jp": 1,
  "shibukawa.gunma.jp": 1,
  "shibuya.tokyo.jp": 1,
  "shichikashuku.miyagi.jp": 1,
  "shichinohe.aomori.jp": 1,
  "shiftcrypto.dev": 1,
  "shiftcrypto.io": 1,
  "shiftedit.io": 1,
  "shiga.jp": 1,
  "shiiba.miyazaki.jp": 1,
  "shijonawate.osaka.jp": 1,
  "shika.ishikawa.jp": 1,
  "shikabe.hokkaido.jp": 1,
  "shikama.miyagi.jp": 1,
  "shikaoi.hokkaido.jp": 1,
  "shikatsu.aichi.jp": 1,
  "shiki.saitama.jp": 1,
  "shikokuchuo.ehime.jp": 1,
  "shima.mie.jp": 1,
  "shimabara.nagasaki.jp": 1,
  "shimada.shizuoka.jp": 1,
  "shimamaki.hokkaido.jp": 1,
  "shimamoto.osaka.jp": 1,
  "shimane.jp": 1,
  "shimane.shimane.jp": 1,
  "shimizu.hokkaido.jp": 1,
  "shimizu.shizuoka.jp": 1,
  "shimoda.shizuoka.jp": 1,
  "shimodate.ibaraki.jp": 1,
  "shimofusa.chiba.jp": 1,
  "shimogo.fukushima.jp": 1,
  "shimoichi.nara.jp": 1,
  "shimoji.okinawa.jp": 1,
  "shimokawa.hokkaido.jp": 1,
  "shimokitayama.nara.jp": 1,
  "shimonita.gunma.jp": 1,
  "shimonoseki.yamaguchi.jp": 1,
  "shimosuwa.nagano.jp": 1,
  "shimotsuke.tochigi.jp": 1,
  "shimotsuma.ibaraki.jp": 1,
  "shinagawa.tokyo.jp": 1,
  "shinanomachi.nagano.jp": 1,
  "shingo.aomori.jp": 1,
  "shingu.fukuoka.jp": 1,
  "shingu.hyogo.jp": 1,
  "shingu.wakayama.jp": 1,
  "shinichi.hiroshima.jp": 1,
  "shinjo.nara.jp": 1,
  "shinjo.okayama.jp": 1,
  "shinjo.yamagata.jp": 1,
  "shinjuku.tokyo.jp": 1,
  "shinkamigoto.nagasaki.jp": 1,
  "shinonsen.hyogo.jp": 1,
  "shinshinotsu.hokkaido.jp": 1,
  "shinshiro.aichi.jp": 1,
  "shinto.gunma.jp": 1,
  "shintoku.hokkaido.jp": 1,
  "shintomi.miyazaki.jp": 1,
  "shinyoshitomi.fukuoka.jp": 1,
  "shiogama.miyagi.jp": 1,
  "shiojiri.nagano.jp": 1,
  "shioya.tochigi.jp": 1,
  "shirahama.wakayama.jp": 1,
  "shirakawa.fukushima.jp": 1,
  "shirakawa.gifu.jp": 1,
  "shirako.chiba.jp": 1,
  "shiranuka.hokkaido.jp": 1,
  "shiraoi.hokkaido.jp": 1,
  "shiraoka.saitama.jp": 1,
  "shirataka.yamagata.jp": 1,
  "shiriuchi.hokkaido.jp": 1,
  "shiroi.chiba.jp": 1,
  "shiroishi.miyagi.jp": 1,
  "shiroishi.saga.jp": 1,
  "shirosato.ibaraki.jp": 1,
  "shishikui.tokushima.jp": 1,
  "shiso.hyogo.jp": 1,
  "shisui.chiba.jp": 1,
  "shitara.aichi.jp": 1,
  "shiwa.iwate.jp": 1,
  "shizukuishi.iwate.jp": 1,
  "shizuoka.jp": 1,
  "shizuoka.shizuoka.jp": 1,
  "shobara.hiroshima.jp": 1,
  "shonai.fukuoka.jp": 1,
  "shonai.yamagata.jp": 1,
  "shoo.okayama.jp": 1,
  "shop.brendly.rs": 1,
  "shop.ht": 1,
  "shop.hu": 1,
  "shop.pl": 1,
  "shop.ro": 1,
  "shop.th": 1,
  "shoparena.pl": 1,
  "shopitsite.com": 1,
  "shopselect.net": 1,
  "shopware.store": 1,
  "show.aero": 1,
  "showa.fukushima.jp": 1,
  "showa.gunma.jp": 1,
  "showa.yamanashi.jp": 1,
  "shunan.yamaguchi.jp": 1,
  "shw.io": 1,
  "si.eu.org": 1,
  "si.it": 1,
  "sibenik.museum": 1,
  "sic.it": 1,
  "sicilia.it": 1,
  "sicily.it": 1,
  "siellak.no": 1,
  "siena.it": 1,
  "sigdal.no": 1,
  "siiites.com": 1,
  "siljan.no": 1,
  "silk.museum": 1,
  "simple-url.com": 1,
  "simplesite.com": 1,
  "simplesite.com.br": 1,
  "simplesite.gr": 1,
  "simplesite.pl": 1,
  "sinaapp.com": 1,
  "siracusa.it": 1,
  "sirdal.no": 1,
  "site.tb-hosting.com": 1,
  "site.transip.me": 1,
  "siteleaf.net": 1,
  "sites.static.land": 1,
  "sjc.br": 1,
  "sk.ca": 1,
  "sk.eu.org": 1,
  "skanit.no": 1,
  "skanland.no": 1,
  "skaun.no": 1,
  "skedsmo.no": 1,
  "skedsmokorset.no": 1,
  "ski.museum": 1,
  "ski.no": 1,
  "skien.no": 1,
  "skierva.no": 1,
  "skiptvet.no": 1,
  "skjak.no": 1,
  "skjervoy.no": 1,
  "sklep.pl": 1,
  "sko.gov.pl": 1,
  "skoczow.pl": 1,
  "skodje.no": 1,
  "skole.museum": 1,
  "skydiving.aero": 1,
  "skygearapp.com": 1,
  "slask.pl": 1,
  "slattum.no": 1,
  "sld.do": 1,
  "sld.pa": 1,
  "slg.br": 1,
  "slupsk.pl": 1,
  "slz.br": 1,
  "sm.ua": 1,
  "small-web.org": 1,
  "smartlabeling.scw.cloud": 1,
  "smola.no": 1,
  "smushcdn.com": 1,
  "sn.cn": 1,
  "snaase.no": 1,
  "snasa.no": 1,
  "snillfjord.no": 1,
  "snoasa.no": 1,
  "so.gov.pl": 1,
  "so.it": 1,
  "sobetsu.hokkaido.jp": 1,
  "soc.dz": 1,
  "soc.lk": 1,
  "soc.srcf.net": 1,
  "sochi.su": 1,
  "society.museum": 1,
  "sodegaura.chiba.jp": 1,
  "soeda.fukuoka.jp": 1,
  "software.aero": 1,
  "sogndal.no": 1,
  "sogne.no": 1,
  "soja.okayama.jp": 1,
  "soka.saitama.jp": 1,
  "sokndal.no": 1,
  "sola.no": 1,
  "sologne.museum": 1,
  "solund.no": 1,
  "soma.fukushima.jp": 1,
  "somna.no": 1,
  "sondre-land.no": 1,
  "sondrio.it": 1,
  "songdalen.no": 1,
  "soni.nara.jp": 1,
  "soo.kagoshima.jp": 1,
  "sopot.pl": 1,
  "sor-aurdal.no": 1,
  "sor-fron.no": 1,
  "sor-odal.no": 1,
  "sor-varanger.no": 1,
  "sorfold.no": 1,
  "sorocaba.br": 1,
  "sorreisa.no": 1,
  "sortland.no": 1,
  "sorum.no": 1,
  "sos.pl": 1,
  "sosa.chiba.jp": 1,
  "sosnowiec.pl": 1,
  "soundandvision.museum": 1,
  "soundcast.me": 1,
  "southcarolina.museum": 1,
  "southwest.museum": 1,
  "sowa.ibaraki.jp": 1,
  "sp.gov.br": 1,
  "sp.it": 1,
  "sp.leg.br": 1,
  "space-to-rent.com": 1,
  "space.museum": 1,
  "spacekit.io": 1,
  "spb.ru": 1,
  "spb.su": 1,
  "spdns.de": 1,
  "spdns.eu": 1,
  "spdns.org": 1,
  "spectrum.myjino.ru": 2,
  "sphinx.mythic-beasts.com": 1,
  "spjelkavik.no": 1,
  "sport.hu": 1,
  "spy.museum": 1,
  "spydeberg.no": 1,
  "square.museum": 1,
  "square7.ch": 1,
  "square7.de": 1,
  "square7.net": 1,
  "sr.gov.pl": 1,
  "sr.it": 1,
  "srht.site": 1,
  "srv.br": 1,
  "ss.it": 1,
  "ssl.origin.cdn77-secure.org": 1,
  "st.no": 1,
  "staba.jp": 1,
  "stackhero-network.com": 1,
  "stadt.museum": 1,
  "stage.nodeart.io": 1,
  "staging.onred.one": 1,
  "stalbans.museum": 1,
  "stalowa-wola.pl": 1,
  "stange.no": 1,
  "starachowice.pl": 1,
  "stargard.pl": 1,
  "starnberg.museum": 1,
  "starostwo.gov.pl": 1,
  "stat.no": 1,
  "state.museum": 1,
  "stateofdelaware.museum": 1,
  "stathelle.no": 1,
  "static-access.net": 1,
  "static.land": 1,
  "static.observableusercontent.com": 1,
  "statics.cloud": 2,
  "station.museum": 1,
  "stavanger.no": 1,
  "stavern.no": 1,
  "steam.museum": 1,
  "steiermark.museum": 1,
  "steigen.no": 1,
  "steinkjer.no": 1,
  "stg-builder.code.com": 2,
  "stg.dev": 2,
  "stgstage.dev": 2,
  "sth.ac.at": 1,
  "stjohn.museum": 1,
  "stjordal.no": 1,
  "stjordalshalsen.no": 1,
  "stockholm.museum": 1,
  "stokke.no": 1,
  "stolos.io": 2,
  "stor-elvdal.no": 1,
  "storage.yandexcloud.net": 1,
  "stord.no": 1,
  "stordal.no": 1,
  "store.bb": 1,
  "store.dk": 1,
  "store.nf": 1,
  "store.ro": 1,
  "store.st": 1,
  "store.ve": 1,
  "storebase.store": 1,
  "storfjord.no": 1,
  "storj.farm": 1,
  "stpetersburg.museum": 1,
  "strand.no": 1,
  "stranda.no": 1,
  "streamlitapp.com": 1,
  "stripper.jp": 1,
  "stryn.no": 1,
  "student.aero": 1,
  "stuff-4-sale.org": 1,
  "stuff-4-sale.us": 1,
  "stufftoread.com": 1,
  "stuttgart.museum": 1,
  "su.paba.se": 1,
  "sub.jp": 1,
  "sue.fukuoka.jp": 1,
  "suedtirol.it": 1,
  "suginami.tokyo.jp": 1,
  "sugito.saitama.jp": 1,
  "suifu.ibaraki.jp": 1,
  "suisse.museum": 1,
  "suita.osaka.jp": 1,
  "sukagawa.fukushima.jp": 1,
  "sukumo.kochi.jp": 1,
  "sula.no": 1,
  "suldal.no": 1,
  "suli.hu": 1,
  "sumida.tokyo.jp": 1,
  "sumita.iwate.jp": 1,
  "sumoto.hyogo.jp": 1,
  "sumoto.kumamoto.jp": 1,
  "sumy.ua": 1,
  "sunagawa.hokkaido.jp": 1,
  "sund.no": 1,
  "sunndal.no": 1,
  "sunnyday.jp": 1,
  "supabase.co": 1,
  "supabase.in": 1,
  "supabase.net": 1,
  "supersale.jp": 1,
  "surgeonshall.museum": 1,
  "surnadal.no": 1,
  "surrey.museum": 1,
  "susaki.kochi.jp": 1,
  "susono.shizuoka.jp": 1,
  "suwa.nagano.jp": 1,
  "suwalki.pl": 1,
  "suzaka.nagano.jp": 1,
  "suzu.ishikawa.jp": 1,
  "suzuka.mie.jp": 1,
  "sv.it": 1,
  "svalbard.no": 1,
  "svc.firenet.ch": 2,
  "sveio.no": 1,
  "svelvik.no": 1,
  "svizzera.museum": 1,
  "svn-repos.de": 1,
  "sweden.museum": 1,
  "sweetpepper.org": 1,
  "swidnica.pl": 1,
  "swidnik.pl": 1,
  "swiebodzin.pl": 1,
  "swinoujscie.pl": 1,
  "sx.cn": 1,
  "sydney.museum": 1,
  "sykkylven.no": 1,
  "syncloud.it": 1,
  "syno-ds.de": 1,
  "synology-diskstation.de": 1,
  "synology-ds.de": 1,
  "synology.me": 1,
  "sys.qcx.io": 2,
  "sytes.net": 1,
  "szczecin.pl": 1,
  "szczytno.pl": 1,
  "szex.hu": 1,
  "szkola.pl": 1,
  "t.bg": 1,
  "t.se": 1,
  "t3l3p0rt.net": 1,
  "ta.it": 1,
  "taa.it": 1,
  "tabayama.yamanashi.jp": 1,
  "tabitorder.co.il": 1,
  "tabuse.yamaguchi.jp": 1,
  "tachiarai.fukuoka.jp": 1,
  "tachikawa.tokyo.jp": 1,
  "tadaoka.osaka.jp": 1,
  "tado.mie.jp": 1,
  "tadotsu.kagawa.jp": 1,
  "tagajo.miyagi.jp": 1,
  "tagami.niigata.jp": 1,
  "tagawa.fukuoka.jp": 1,
  "tahara.aichi.jp": 1,
  "taifun-dns.de": 1,
  "taiji.wakayama.jp": 1,
  "taiki.hokkaido.jp": 1,
  "taiki.mie.jp": 1,
  "tainai.niigata.jp": 1,
  "taira.toyama.jp": 1,
  "taishi.hyogo.jp": 1,
  "taishi.osaka.jp": 1,
  "taishin.fukushima.jp": 1,
  "taito.tokyo.jp": 1,
  "taiwa.miyagi.jp": 1,
  "tajimi.gifu.jp": 1,
  "tajiri.osaka.jp": 1,
  "taka.hyogo.jp": 1,
  "takagi.nagano.jp": 1,
  "takahagi.ibaraki.jp": 1,
  "takahama.aichi.jp": 1,
  "takahama.fukui.jp": 1,
  "takaharu.miyazaki.jp": 1,
  "takahashi.okayama.jp": 1,
  "takahata.yamagata.jp": 1,
  "takaishi.osaka.jp": 1,
  "takamatsu.kagawa.jp": 1,
  "takamori.kumamoto.jp": 1,
  "takamori.nagano.jp": 1,
  "takanabe.miyazaki.jp": 1,
  "takanezawa.tochigi.jp": 1,
  "takaoka.toyama.jp": 1,
  "takarazuka.hyogo.jp": 1,
  "takasago.hyogo.jp": 1,
  "takasaki.gunma.jp": 1,
  "takashima.shiga.jp": 1,
  "takasu.hokkaido.jp": 1,
  "takata.fukuoka.jp": 1,
  "takatori.nara.jp": 1,
  "takatsuki.osaka.jp": 1,
  "takatsuki.shiga.jp": 1,
  "takayama.gifu.jp": 1,
  "takayama.gunma.jp": 1,
  "takayama.nagano.jp": 1,
  "takazaki.miyazaki.jp": 1,
  "takehara.hiroshima.jp": 1,
  "taketa.oita.jp": 1,
  "taketomi.okinawa.jp": 1,
  "taki.mie.jp": 1,
  "takikawa.hokkaido.jp": 1,
  "takino.hyogo.jp": 1,
  "takinoue.hokkaido.jp": 1,
  "takko.aomori.jp": 1,
  "tako.chiba.jp": 1,
  "taku.saga.jp": 1,
  "tama.tokyo.jp": 1,
  "tamakawa.fukushima.jp": 1,
  "tamaki.mie.jp": 1,
  "tamamura.gunma.jp": 1,
  "tamano.okayama.jp": 1,
  "tamatsukuri.ibaraki.jp": 1,
  "tamayu.shimane.jp": 1,
  "tamba.hyogo.jp": 1,
  "tana.no": 1,
  "tanabe.kyoto.jp": 1,
  "tanabe.wakayama.jp": 1,
  "tanagura.fukushima.jp": 1,
  "tananger.no": 1,
  "tank.museum": 1,
  "tanohata.iwate.jp": 1,
  "tara.saga.jp": 1,
  "tarama.okinawa.jp": 1,
  "taranto.it": 1,
  "targi.pl": 1,
  "tarnobrzeg.pl": 1,
  "tarui.gifu.jp": 1,
  "tarumizu.kagoshima.jp": 1,
  "tas.au": 1,
  "tas.edu.au": 1,
  "tas.gov.au": 1,
  "tashkent.su": 1,
  "tatebayashi.gunma.jp": 1,
  "tateshina.nagano.jp": 1,
  "tateyama.chiba.jp": 1,
  "tateyama.toyama.jp": 1,
  "tatsuno.hyogo.jp": 1,
  "tatsuno.nagano.jp": 1,
  "tawaramoto.nara.jp": 1,
  "taxi.br": 1,
  "tc.br": 1,
  "tcm.museum": 1,
  "tcp4.me": 1,
  "te.it": 1,
  "te.ua": 1,
  "teaches-yoga.com": 1,
  "tec.br": 1,
  "tec.mi.us": 1,
  "tec.ve": 1,
  "tech.orange": 1,
  "technology.museum": 1,
  "tecnologia.bo": 1,
  "tel.tr": 1,
  "tele.amune.org": 1,
  "telebit.app": 1,
  "telebit.io": 1,
  "telebit.xyz": 2,
  "telekommunikation.museum": 1,
  "television.museum": 1,
  "temp-dns.com": 1,
  "tempio-olbia.it": 1,
  "tempioolbia.it": 1,
  "tempurl.host": 1,
  "tendo.yamagata.jp": 1,
  "tenei.fukushima.jp": 1,
  "tenkawa.nara.jp": 1,
  "tenri.nara.jp": 1,
  "teo.br": 1,
  "teramo.it": 1,
  "termez.su": 1,
  "terni.it": 1,
  "ternopil.ua": 1,
  "teshikaga.hokkaido.jp": 1,
  "test-iserv.de": 1,
  "test.ru": 1,
  "test.tj": 1,
  "texas.museum": 1,
  "textile.museum": 1,
  "tgory.pl": 1,
  "the.br": 1,
  "theater.museum": 1,
  "theshop.jp": 1,
  "theworkpc.com": 1,
  "thick.jp": 1,
  "thingdustdata.com": 1,
  "thruhere.net": 1,
  "tickets.io": 1,
  "time.museum": 1,
  "time.no": 1,
  "timekeeping.museum": 1,
  "tingvoll.no": 1,
  "tinn.no": 1,
  "tj.cn": 1,
  "tjeldsund.no": 1,
  "tjome.no": 1,
  "tksat.bo": 1,
  "tlon.network": 1,
  "tm.cy": 1,
  "tm.dz": 1,
  "tm.fr": 1,
  "tm.hu": 1,
  "tm.km": 1,
  "tm.mc": 1,
  "tm.mg": 1,
  "tm.no": 1,
  "tm.pl": 1,
  "tm.ro": 1,
  "tm.se": 1,
  "tm.za": 1,
  "tmp.br": 1,
  "tn.it": 1,
  "tn.oxa.cloud": 1,
  "tn.us": 1,
  "to.gov.br": 1,
  "to.gt": 1,
  "to.it": 1,
  "to.leg.br": 1,
  "to.md": 1,
  "toba.mie.jp": 1,
  "tobe.ehime.jp": 1,
  "tobetsu.hokkaido.jp": 1,
  "tobishima.aichi.jp": 1,
  "tochigi.jp": 1,
  "tochigi.tochigi.jp": 1,
  "tochio.niigata.jp": 1,
  "toda.saitama.jp": 1,
  "toei.aichi.jp": 1,
  "toga.toyama.jp": 1,
  "togakushi.nagano.jp": 1,
  "togane.chiba.jp": 1,
  "togitsu.nagasaki.jp": 1,
  "togliatti.su": 1,
  "togo.aichi.jp": 1,
  "togura.nagano.jp": 1,
  "tohma.hokkaido.jp": 1,
  "tohnosho.chiba.jp": 1,
  "toho.fukuoka.jp": 1,
  "tokai.aichi.jp": 1,
  "tokai.ibaraki.jp": 1,
  "tokamachi.niigata.jp": 1,
  "tokashiki.okinawa.jp": 1,
  "toki.gifu.jp": 1,
  "tokigawa.saitama.jp": 1,
  "tokke.no": 1,
  "tokoname.aichi.jp": 1,
  "tokorozawa.saitama.jp": 1,
  "tokushima.jp": 1,
  "tokushima.tokushima.jp": 1,
  "tokuyama.yamaguchi.jp": 1,
  "tokyo.jp": 1,
  "tolga.no": 1,
  "tomakomai.hokkaido.jp": 1,
  "tomari.hokkaido.jp": 1,
  "tome.miyagi.jp": 1,
  "tomi.nagano.jp": 1,
  "tomigusuku.okinawa.jp": 1,
  "tomika.gifu.jp": 1,
  "tomioka.gunma.jp": 1,
  "tomisato.chiba.jp": 1,
  "tomiya.miyagi.jp": 1,
  "tomobe.ibaraki.jp": 1,
  "tonaki.okinawa.jp": 1,
  "tonami.toyama.jp": 1,
  "tondabayashi.osaka.jp": 1,
  "tone.ibaraki.jp": 1,
  "tonkotsu.jp": 1,
  "tono.iwate.jp": 1,
  "tonosho.kagawa.jp": 1,
  "tonsberg.no": 1,
  "toolforge.org": 1,
  "toon.ehime.jp": 1,
  "topology.museum": 1,
  "torahime.shiga.jp": 1,
  "toride.ibaraki.jp": 1,
  "torino.it": 1,
  "torino.museum": 1,
  "torproject.net": 1,
  "torsken.no": 1,
  "tos.it": 1,
  "tosa.kochi.jp": 1,
  "tosashimizu.kochi.jp": 1,
  "toscana.it": 1,
  "toshima.tokyo.jp": 1,
  "tosu.saga.jp": 1,
  "tottori.jp": 1,
  "tottori.tottori.jp": 1,
  "touch.museum": 1,
  "tourism.pl": 1,
  "tourism.tn": 1,
  "towada.aomori.jp": 1,
  "town.museum": 1,
  "townnews-staging.com": 1,
  "toya.hokkaido.jp": 1,
  "toyako.hokkaido.jp": 1,
  "toyama.jp": 1,
  "toyama.toyama.jp": 1,
  "toyo.kochi.jp": 1,
  "toyoake.aichi.jp": 1,
  "toyohashi.aichi.jp": 1,
  "toyokawa.aichi.jp": 1,
  "toyonaka.osaka.jp": 1,
  "toyone.aichi.jp": 1,
  "toyono.osaka.jp": 1,
  "toyooka.hyogo.jp": 1,
  "toyosato.shiga.jp": 1,
  "toyota.aichi.jp": 1,
  "toyota.yamaguchi.jp": 1,
  "toyotomi.hokkaido.jp": 1,
  "toyotsu.fukuoka.jp": 1,
  "toyoura.hokkaido.jp": 1,
  "tozawa.yamagata.jp": 1,
  "tozsde.hu": 1,
  "tp.it": 1,
  "tr.eu.org": 1,
  "tr.it": 1,
  "tr.no": 1,
  "tra.kp": 1,
  "trader.aero": 1,
  "trading.aero": 1,
  "traeumtgerade.de": 1,
  "trafficplex.cloud": 1,
  "trainer.aero": 1,
  "trana.no": 1,
  "tranby.no": 1,
  "trani-andria-barletta.it": 1,
  "trani-barletta-andria.it": 1,
  "traniandriabarletta.it": 1,
  "tranibarlettaandria.it": 1,
  "tranoy.no": 1,
  "translate.goog": 1,
  "translated.page": 1,
  "transport.museum": 1,
  "transporte.bo": 1,
  "transurl.be": 2,
  "transurl.eu": 2,
  "transurl.nl": 2,
  "trapani.it": 1,
  "travel.in": 1,
  "travel.pl": 1,
  "travel.tt": 1,
  "trd.br": 1,
  "tree.museum": 1,
  "trentin-sud-tirol.it": 1,
  "trentin-sudtirol.it": 1,
  "trentin-sued-tirol.it": 1,
  "trentin-suedtirol.it": 1,
  "trentino-a-adige.it": 1,
  "trentino-aadige.it": 1,
  "trentino-alto-adige.it": 1,
  "trentino-altoadige.it": 1,
  "trentino-s-tirol.it": 1,
  "trentino-stirol.it": 1,
  "trentino-sud-tirol.it": 1,
  "trentino-sudtirol.it": 1,
  "trentino-sued-tirol.it": 1,
  "trentino-suedtirol.it": 1,
  "trentino.it": 1,
  "trentinoa-adige.it": 1,
  "trentinoaadige.it": 1,
  "trentinoalto-adige.it": 1,
  "trentinoaltoadige.it": 1,
  "trentinos-tirol.it": 1,
  "trentinostirol.it": 1,
  "trentinosud-tirol.it": 1,
  "trentinosudtirol.it": 1,
  "trentinosued-tirol.it": 1,
  "trentinosuedtirol.it": 1,
  "trentinsud-tirol.it": 1,
  "trentinsudtirol.it": 1,
  "trentinsued-tirol.it": 1,
  "trentinsuedtirol.it": 1,
  "trento.it": 1,
  "treviso.it": 1,
  "trieste.it": 1,
  "triton.zone": 2,
  "troandin.no": 1,
  "trogstad.no": 1,
  "troitsk.su": 1,
  "trolley.museum": 1,
  "tromsa.no": 1,
  "tromso.no": 1,
  "trondheim.no": 1,
  "trust.museum": 1,
  "trustee.museum": 1,
  "try-snowplow.com": 1,
  "trycloudflare.com": 1,
  "trysil.no": 1,
  "ts.it": 1,
  "ts.net": 1,
  "tselinograd.su": 1,
  "tsk.tr": 1,
  "tst.site": 2,
  "tsu.mie.jp": 1,
  "tsubame.niigata.jp": 1,
  "tsubata.ishikawa.jp": 1,
  "tsubetsu.hokkaido.jp": 1,
  "tsuchiura.ibaraki.jp": 1,
  "tsuga.tochigi.jp": 1,
  "tsugaru.aomori.jp": 1,
  "tsuiki.fukuoka.jp": 1,
  "tsukigata.hokkaido.jp": 1,
  "tsukiyono.gunma.jp": 1,
  "tsukuba.ibaraki.jp": 1,
  "tsukui.kanagawa.jp": 1,
  "tsukumi.oita.jp": 1,
  "tsumagoi.gunma.jp": 1,
  "tsunan.niigata.jp": 1,
  "tsuno.kochi.jp": 1,
  "tsuno.miyazaki.jp": 1,
  "tsuru.yamanashi.jp": 1,
  "tsuruga.fukui.jp": 1,
  "tsurugashima.saitama.jp": 1,
  "tsurugi.ishikawa.jp": 1,
  "tsuruoka.yamagata.jp": 1,
  "tsuruta.aomori.jp": 1,
  "tsushima.aichi.jp": 1,
  "tsushima.nagasaki.jp": 1,
  "tsuwano.shimane.jp": 1,
  "tsuyama.okayama.jp": 1,
  "tt.im": 1,
  "tula.su": 1,
  "tuleap-partners.com": 1,
  "tunk.org": 1,
  "tur.ar": 1,
  "tur.br": 1,
  "turek.pl": 1,
  "turin.it": 1,
  "turystyka.pl": 1,
  "tuscany.it": 1,
  "tuva.su": 1,
  "tuxfamily.org": 1,
  "tv.bb": 1,
  "tv.bo": 1,
  "tv.br": 1,
  "tv.im": 1,
  "tv.in": 1,
  "tv.it": 1,
  "tv.kg": 1,
  "tv.na": 1,
  "tv.sd": 1,
  "tv.tr": 1,
  "tv.tz": 1,
  "tvedestrand.no": 1,
  "tw.cn": 1,
  "twmail.cc": 1,
  "twmail.net": 1,
  "twmail.org": 1,
  "tx.us": 1,
  "tychy.pl": 1,
  "tydal.no": 1,
  "tynset.no": 1,
  "typedream.app": 1,
  "tysfjord.no": 1,
  "tysnes.no": 1,
  "tysvar.no": 1,
  "u.bg": 1,
  "u.channelsdvr.net": 1,
  "u.se": 1,
  "u2-local.xnbay.com": 1,
  "u2.xnbay.com": 1,
  "ua.rs": 1,
  "ube.yamaguchi.jp": 1,
  "uber.space": 1,
  "uberspace.de": 2,
  "uchihara.ibaraki.jp": 1,
  "uchiko.ehime.jp": 1,
  "uchinada.ishikawa.jp": 1,
  "uchinomi.kagawa.jp": 1,
  "ud.it": 1,
  "uda.nara.jp": 1,
  "udi.br": 1,
  "udine.it": 1,
  "udono.mie.jp": 1,
  "ueda.nagano.jp": 1,
  "ueno.gunma.jp": 1,
  "uenohara.yamanashi.jp": 1,
  "ufcfan.org": 1,
  "ug.gov.pl": 1,
  "ugim.gov.pl": 1,
  "uhren.museum": 1,
  "ui.nabu.casa": 1,
  "uji.kyoto.jp": 1,
  "ujiie.tochigi.jp": 1,
  "ujitawara.kyoto.jp": 1,
  "uk.com": 1,
  "uk.eu.org": 1,
  "uk.in": 1,
  "uk.kg": 1,
  "uk.net": 1,
  "uk.oxa.cloud": 1,
  "uk.primetel.cloud": 1,
  "uk.reclaim.cloud": 1,
  "uk0.bigv.io": 1,
  "uki.kumamoto.jp": 1,
  "ukiha.fukuoka.jp": 1,
  "ullensaker.no": 1,
  "ullensvang.no": 1,
  "ulm.museum": 1,
  "ulsan.kr": 1,
  "ulvik.no": 1,
  "um.gov.pl": 1,
  "umaji.kochi.jp": 1,
  "umb.it": 1,
  "umbria.it": 1,
  "umi.fukuoka.jp": 1,
  "umig.gov.pl": 1,
  "unazuki.toyama.jp": 1,
  "under.jp": 1,
  "undersea.museum": 1,
  "uni5.net": 1,
  "unicloud.pl": 1,
  "union.aero": 1,
  "univ.sn": 1,
  "university.museum": 1,
  "unjarga.no": 1,
  "unnan.shimane.jp": 1,
  "unusualperson.com": 1,
  "unzen.nagasaki.jp": 1,
  "uonuma.niigata.jp": 1,
  "uozu.toyama.jp": 1,
  "up.in": 1,
  "upaas.kazteleport.kz": 1,
  "upli.io": 1,
  "upow.gov.pl": 1,
  "upper.jp": 1,
  "uppo.gov.pl": 1,
  "urakawa.hokkaido.jp": 1,
  "urasoe.okinawa.jp": 1,
  "urausu.hokkaido.jp": 1,
  "urawa.saitama.jp": 1,
  "urayasu.chiba.jp": 1,
  "urbino-pesaro.it": 1,
  "urbinopesaro.it": 1,
  "ureshino.mie.jp": 1,
  "uri.arpa": 1,
  "url.tw": 1,
  "urn.arpa": 1,
  "urown.cloud": 1,
  "uruma.okinawa.jp": 1,
  "uryu.hokkaido.jp": 1,
  "us-1.evennode.com": 1,
  "us-2.evennode.com": 1,
  "us-3.evennode.com": 1,
  "us-4.evennode.com": 1,
  "us-east-1.amazonaws.com": 1,
  "us-east-1.elasticbeanstalk.com": 1,
  "us-east-2.elasticbeanstalk.com": 1,
  "us-gov-west-1.elasticbeanstalk.com": 1,
  "us-west-1.elasticbeanstalk.com": 1,
  "us-west-2.elasticbeanstalk.com": 1,
  "us.ax": 1,
  "us.com": 1,
  "us.eu.org": 1,
  "us.gov.pl": 1,
  "us.in": 1,
  "us.kg": 1,
  "us.na": 1,
  "us.org": 1,
  "us.platform.sh": 1,
  "us.reclaim.cloud": 1,
  "usa.museum": 1,
  "usa.oita.jp": 1,
  "usantiques.museum": 1,
  "usarts.museum": 1,
  "uscountryestate.museum": 1,
  "usculture.museum": 1,
  "usdecorativearts.museum": 1,
  "user.aseinet.ne.jp": 1,
  "user.fm": 2,
  "user.localcert.dev": 2,
  "user.party.eus": 1,
  "user.srcf.net": 1,
  "usercontent.goog": 2,
  "usercontent.jp": 1,
  "users.scale.virtualcloud.com.br": 1,
  "usgarden.museum": 1,
  "ushiku.ibaraki.jp": 1,
  "ushistory.museum": 1,
  "ushuaia.museum": 1,
  "uslivinghistory.museum": 1,
  "usr.cloud.muni.cz": 1,
  "ustka.pl": 1,
  "usui.fukuoka.jp": 1,
  "usuki.oita.jp": 1,
  "ut.us": 1,
  "utah.museum": 1,
  "utashinai.hokkaido.jp": 1,
  "utazas.hu": 1,
  "utazu.kagawa.jp": 1,
  "uto.kumamoto.jp": 1,
  "utsira.no": 1,
  "utsunomiya.tochigi.jp": 1,
  "utwente.io": 1,
  "uvic.museum": 1,
  "uw.gov.pl": 1,
  "uwajima.ehime.jp": 1,
  "uwu.ai": 1,
  "uy.com": 1,
  "uz.ua": 1,
  "uzhgorod.ua": 1,
  "uzs.gov.pl": 1,
  "v-info.info": 1,
  "v.bg": 1,
  "v.ua": 1,
  "va.it": 1,
  "va.no": 1,
  "va.us": 1,
  "vaapste.no": 1,
  "vadso.no": 1,
  "vaga.no": 1,
  "vagan.no": 1,
  "vagsoy.no": 1,
  "vaksdal.no": 1,
  "val-d-aosta.it": 1,
  "val-daosta.it": 1,
  "vald-aosta.it": 1,
  "valdaosta.it": 1,
  "valer.hedmark.no": 1,
  "valer.ostfold.no": 1,
  "valle-aosta.it": 1,
  "valle-d-aosta.it": 1,
  "valle-daosta.it": 1,
  "valle.no": 1,
  "valleaosta.it": 1,
  "valled-aosta.it": 1,
  "valledaosta.it": 1,
  "vallee-aoste.it": 1,
  "vallee-d-aoste.it": 1,
  "valleeaoste.it": 1,
  "valleedaoste.it": 1,
  "valley.museum": 1,
  "vang.no": 1,
  "vantaa.museum": 1,
  "vanylven.no": 1,
  "vao.it": 1,
  "vapor.cloud": 1,
  "vaporcloud.io": 1,
  "vardo.no": 1,
  "varese.it": 1,
  "varggat.no": 1,
  "varoy.no": 1,
  "vb.it": 1,
  "vc.it": 1,
  "vda.it": 1,
  "ve.it": 1,
  "vefsn.no": 1,
  "vega.no": 1,
  "vegarshei.no": 1,
  "velvet.jp": 1,
  "ven.it": 1,
  "veneto.it": 1,
  "venezia.it": 1,
  "venice.it": 1,
  "vennesla.no": 1,
  "verbania.it": 1,
  "vercel.app": 1,
  "vercel.dev": 1,
  "vercelli.it": 1,
  "verdal.no": 1,
  "verona.it": 1,
  "verran.no": 1,
  "versailles.museum": 1,
  "verse.jp": 1,
  "versus.jp": 1,
  "vestby.no": 1,
  "vestnes.no": 1,
  "vestre-slidre.no": 1,
  "vestre-toten.no": 1,
  "vestvagoy.no": 1,
  "vet.br": 1,
  "veterinaire.fr": 1,
  "veterinaire.km": 1,
  "vevelstad.no": 1,
  "vf.no": 1,
  "vfs.cloud9.af-south-1.amazonaws.com": 1,
  "vfs.cloud9.ap-east-1.amazonaws.com": 1,
  "vfs.cloud9.ap-northeast-1.amazonaws.com": 1,
  "vfs.cloud9.ap-northeast-2.amazonaws.com": 1,
  "vfs.cloud9.ap-northeast-3.amazonaws.com": 1,
  "vfs.cloud9.ap-south-1.amazonaws.com": 1,
  "vfs.cloud9.ap-southeast-1.amazonaws.com": 1,
  "vfs.cloud9.ap-southeast-2.amazonaws.com": 1,
  "vfs.cloud9.ca-central-1.amazonaws.com": 1,
  "vfs.cloud9.eu-central-1.amazonaws.com": 1,
  "vfs.cloud9.eu-north-1.amazonaws.com": 1,
  "vfs.cloud9.eu-south-1.amazonaws.com": 1,
  "vfs.cloud9.eu-west-1.amazonaws.com": 1,
  "vfs.cloud9.eu-west-2.amazonaws.com": 1,
  "vfs.cloud9.eu-west-3.amazonaws.com": 1,
  "vfs.cloud9.me-south-1.amazonaws.com": 1,
  "vfs.cloud9.sa-east-1.amazonaws.com": 1,
  "vfs.cloud9.us-east-1.amazonaws.com": 1,
  "vfs.cloud9.us-east-2.amazonaws.com": 1,
  "vfs.cloud9.us-west-1.amazonaws.com": 1,
  "vfs.cloud9.us-west-2.amazonaws.com": 1,
  "vgs.no": 1,
  "vi.it": 1,
  "vi.us": 1,
  "vibo-valentia.it": 1,
  "vibovalentia.it": 1,
  "vic.au": 1,
  "vic.edu.au": 1,
  "vic.gov.au": 1,
  "vicenza.it": 1,
  "video.hu": 1,
  "vik.no": 1,
  "viking.museum": 1,
  "vikna.no": 1,
  "village.museum": 1,
  "vindafjord.no": 1,
  "vinnica.ua": 1,
  "vinnytsia.ua": 1,
  "vip.jelastic.cloud": 1,
  "vipsinaapp.com": 1,
  "virginia.museum": 1,
  "virtual-user.de": 1,
  "virtual.museum": 1,
  "virtualserver.io": 1,
  "virtualuser.de": 1,
  "virtuel.museum": 1,
  "viterbo.it": 1,
  "vivian.jp": 1,
  "vix.br": 1,
  "vlaanderen.museum": 1,
  "vladikavkaz.ru": 1,
  "vladikavkaz.su": 1,
  "vladimir.ru": 1,
  "vladimir.su": 1,
  "vlog.br": 1,
  "vm.bytemark.co.uk": 1,
  "vn.ua": 1,
  "voagat.no": 1,
  "volda.no": 1,
  "volkenkunde.museum": 1,
  "vologda.su": 1,
  "volyn.ua": 1,
  "voorloper.cloud": 1,
  "voss.no": 1,
  "vossevangen.no": 1,
  "vp4.me": 1,
  "vpndns.net": 1,
  "vpnplus.to": 1,
  "vps-host.net": 1,
  "vps.mcdir.ru": 1,
  "vps.myjino.ru": 2,
  "vr.it": 1,
  "vs.it": 1,
  "vs.mythic-beasts.com": 1,
  "vt.it": 1,
  "vt.us": 1,
  "vultrobjects.com": 2,
  "vv.it": 1,
  "vxl.sh": 1,
  "w.bg": 1,
  "w.se": 1,
  "wa.au": 1,
  "wa.edu.au": 1,
  "wa.gov.au": 1,
  "wa.us": 1,
  "wada.nagano.jp": 1,
  "wafflecell.com": 1,
  "wajiki.tokushima.jp": 1,
  "wajima.ishikawa.jp": 1,
  "wakasa.fukui.jp": 1,
  "wakasa.tottori.jp": 1,
  "wakayama.jp": 1,
  "wakayama.wakayama.jp": 1,
  "wake.okayama.jp": 1,
  "wakkanai.hokkaido.jp": 1,
  "wakuya.miyagi.jp": 1,
  "walbrzych.pl": 1,
  "wales.museum": 1,
  "wallonie.museum": 1,
  "wanouchi.gifu.jp": 1,
  "war.museum": 1,
  "warabi.saitama.jp": 1,
  "warmia.pl": 1,
  "warszawa.pl": 1,
  "washingtondc.museum": 1,
  "washtenaw.mi.us": 1,
  "wassamu.hokkaido.jp": 1,
  "watarai.mie.jp": 1,
  "watari.miyagi.jp": 1,
  "watch-and-clock.museum": 1,
  "watchandclock.museum": 1,
  "watson.jp": 1,
  "waw.pl": 1,
  "wazuka.kyoto.jp": 1,
  "we.bs": 1,
  "we.tc": 1,
  "web.app": 1,
  "web.bo": 1,
  "web.co": 1,
  "web.do": 1,
  "web.gu": 1,
  "web.id": 1,
  "web.in": 1,
  "web.lk": 1,
  "web.nf": 1,
  "web.ni": 1,
  "web.pk": 1,
  "web.tj": 1,
  "web.tr": 1,
  "web.ve": 1,
  "web.za": 1,
  "webhare.dev": 2,
  "webhop.biz": 1,
  "webhop.info": 1,
  "webhop.me": 1,
  "webhop.net": 1,
  "webhop.org": 1,
  "webhosting.be": 1,
  "weblike.jp": 1,
  "webpaas.ovh.net": 2,
  "webredirect.org": 1,
  "website.yandexcloud.net": 1,
  "webspace.rocks": 1,
  "webthings.io": 1,
  "webview-assets.cloud9.af-south-1.amazonaws.com": 1,
  "webview-assets.cloud9.ap-east-1.amazonaws.com": 1,
  "webview-assets.cloud9.ap-northeast-1.amazonaws.com": 1,
  "webview-assets.cloud9.ap-northeast-2.amazonaws.com": 1,
  "webview-assets.cloud9.ap-northeast-3.amazonaws.com": 1,
  "webview-assets.cloud9.ap-south-1.amazonaws.com": 1,
  "webview-assets.cloud9.ap-southeast-1.amazonaws.com": 1,
  "webview-assets.cloud9.ap-southeast-2.amazonaws.com": 1,
  "webview-assets.cloud9.ca-central-1.amazonaws.com": 1,
  "webview-assets.cloud9.eu-central-1.amazonaws.com": 1,
  "webview-assets.cloud9.eu-north-1.amazonaws.com": 1,
  "webview-assets.cloud9.eu-south-1.amazonaws.com": 1,
  "webview-assets.cloud9.eu-west-1.amazonaws.com": 1,
  "webview-assets.cloud9.eu-west-2.amazonaws.com": 1,
  "webview-assets.cloud9.eu-west-3.amazonaws.com": 1,
  "webview-assets.cloud9.me-south-1.amazonaws.com": 1,
  "webview-assets.cloud9.sa-east-1.amazonaws.com": 1,
  "webview-assets.cloud9.us-east-1.amazonaws.com": 1,
  "webview-assets.cloud9.us-east-2.amazonaws.com": 1,
  "webview-assets.cloud9.us-west-1.amazonaws.com": 1,
  "webview-assets.cloud9.us-west-2.amazonaws.com": 1,
  "wedeploy.io": 1,
  "wedeploy.me": 1,
  "wedeploy.sh": 1,
  "weeklylottery.org.uk": 1,
  "wegrow.pl": 1,
  "wellbeingzone.co.uk": 1,
  "wellbeingzone.eu": 1,
  "west1-us.cloudjiffy.net": 1,
  "western.museum": 1,
  "westeurope.azurestaticapps.net": 1,
  "westfalen.museum": 1,
  "westus2.azurestaticapps.net": 1,
  "whaling.museum": 1,
  "whitesnow.jp": 1,
  "whm.fr-par.scw.cloud": 1,
  "whm.nl-ams.scw.cloud": 1,
  "wi.us": 1,
  "wielun.pl": 1,
  "wien.funkfeuer.at": 1,
  "wif.gov.pl": 1,
  "wiih.gov.pl": 1,
  "wiki.bo": 1,
  "wiki.br": 1,
  "wildlife.museum": 1,
  "williamsburg.museum": 1,
  "winb.gov.pl": 1,
  "windmill.museum": 1,
  "wios.gov.pl": 1,
  "witd.gov.pl": 1,
  "withgoogle.com": 1,
  "withyoutube.com": 1,
  "wiw.gov.pl": 1,
  "wixsite.com": 1,
  "wlocl.pl": 1,
  "wloclawek.pl": 1,
  "wmcloud.org": 1,
  "wmflabs.org": 1,
  "wnext.app": 1,
  "wodzislaw.pl": 1,
  "wolomin.pl": 1,
  "woltlab-demo.com": 1,
  "workers.dev": 1,
  "workinggroup.aero": 1,
  "workisboring.com": 1,
  "works.aero": 1,
  "workshop.museum": 1,
  "worse-than.tv": 1,
  "wpdevcloud.com": 1,
  "wpenginepowered.com": 1,
  "wphostedmail.com": 1,
  "wpmucdn.com": 1,
  "wpmudev.host": 1,
  "writesthisblog.com": 1,
  "wroc.pl": 1,
  "wroclaw.pl": 1,
  "ws.na": 1,
  "wsa.gov.pl": 1,
  "wskr.gov.pl": 1,
  "wuoz.gov.pl": 1,
  "wv.us": 1,
  "www.ck": 0,
  "www.ro": 1,
  "wy.us": 1,
  "wzmiuw.gov.pl": 1,
  "x.bg": 1,
  "x.mythic-beasts.com": 1,
  "x.se": 1,
  "x443.pw": 1,
  "xen.prgmr.com": 1,
  "xj.cn": 1,
  "xn--0trq7p7nn.jp": 1,
  "xn--12c1fe0br.xn--o3cw4h": 1,
  "xn--12cfi8ixb8l.xn--o3cw4h": 1,
  "xn--12co0c3b4eva.xn--o3cw4h": 1,
  "xn--1ctwo.jp": 1,
  "xn--1lqs03n.jp": 1,
  "xn--1lqs71d.jp": 1,
  "xn--2m4a15e.jp": 1,
  "xn--32vp30h.jp": 1,
  "xn--41a.xn--p1acf": 1,
  "xn--4dbgdty6c.xn--4dbrk0ce": 1,
  "xn--4it168d.jp": 1,
  "xn--4it797k.jp": 1,
  "xn--4pvxs.jp": 1,
  "xn--55qx5d.cn": 1,
  "xn--55qx5d.hk": 1,
  "xn--55qx5d.xn--j6w193g": 1,
  "xn--5dbhl8d.xn--4dbrk0ce": 1,
  "xn--5js045d.jp": 1,
  "xn--5rtp49c.jp": 1,
  "xn--5rtq34k.jp": 1,
  "xn--6btw5a.jp": 1,
  "xn--6orx2r.jp": 1,
  "xn--7t0a264c.jp": 1,
  "xn--80aaa0cvac.xn--p1acf": 1,
  "xn--80au.xn--90a3ac": 1,
  "xn--8dbq2a.xn--4dbrk0ce": 1,
  "xn--8ltr62k.jp": 1,
  "xn--8pvr4u.jp": 1,
  "xn--90a1af.xn--p1acf": 1,
  "xn--90amc.xn--p1acf": 1,
  "xn--90azh.xn--90a3ac": 1,
  "xn--9dbhblg6di.museum": 1,
  "xn--andy-ira.no": 1,
  "xn--aroport-bya.ci": 1,
  "xn--asky-ira.no": 1,
  "xn--aurskog-hland-jnb.no": 1,
  "xn--avery-yua.no": 1,
  "xn--b-5ga.nordland.no": 1,
  "xn--b-5ga.telemark.no": 1,
  "xn--balsan-sdtirol-nsb.it": 1,
  "xn--bdddj-mrabd.no": 1,
  "xn--bearalvhki-y4a.no": 1,
  "xn--berlevg-jxa.no": 1,
  "xn--bhcavuotna-s4a.no": 1,
  "xn--bhccavuotna-k7a.no": 1,
  "xn--bidr-5nac.no": 1,
  "xn--bievt-0qa.no": 1,
  "xn--bjarky-fya.no": 1,
  "xn--bjddar-pta.no": 1,
  "xn--blt-elab.no": 1,
  "xn--bmlo-gra.no": 1,
  "xn--bod-2na.no": 1,
  "xn--bozen-sdtirol-2ob.it": 1,
  "xn--brnny-wuac.no": 1,
  "xn--brnnysund-m8ac.no": 1,
  "xn--brum-voa.no": 1,
  "xn--btsfjord-9za.no": 1,
  "xn--bulsan-sdtirol-nsb.it": 1,
  "xn--c1avg.xn--90a3ac": 1,
  "xn--c1avg.xn--p1acf": 1,
  "xn--c3s14m.jp": 1,
  "xn--cesena-forl-mcb.it": 1,
  "xn--cesenaforl-i8a.it": 1,
  "xn--ciqpn.hk": 1,
  "xn--comunicaes-v6a2o.museum": 1,
  "xn--correios-e-telecomunicaes-ghc29a.museum": 1,
  "xn--czrw28b.tw": 1,
  "xn--d1at.xn--90a3ac": 1,
  "xn--d5qv7z876c.jp": 1,
  "xn--davvenjrga-y4a.no": 1,
  "xn--djrs72d6uy.jp": 1,
  "xn--djty4k.jp": 1,
  "xn--dnna-gra.no": 1,
  "xn--drbak-wua.no": 1,
  "xn--dyry-ira.no": 1,
  "xn--efvn9s.jp": 1,
  "xn--ehqz56n.jp": 1,
  "xn--elqq16h.jp": 1,
  "xn--eveni-0qa01ga.no": 1,
  "xn--f6qx53a.jp": 1,
  "xn--finny-yua.no": 1,
  "xn--fjord-lra.no": 1,
  "xn--fl-zia.no": 1,
  "xn--flor-jra.no": 1,
  "xn--forl-cesena-fcb.it": 1,
  "xn--forlcesena-c8a.it": 1,
  "xn--frde-gra.no": 1,
  "xn--frna-woa.no": 1,
  "xn--frya-hra.no": 1,
  "xn--ggaviika-8ya47h.no": 1,
  "xn--gildeskl-g0a.no": 1,
  "xn--givuotna-8ya.no": 1,
  "xn--gjvik-wua.no": 1,
  "xn--gls-elac.no": 1,
  "xn--gmq050i.hk": 1,
  "xn--gmqw5a.hk": 1,
  "xn--gmqw5a.xn--j6w193g": 1,
  "xn--gnstigbestellen-zvb.de": 1,
  "xn--gnstigliefern-wob.de": 1,
  "xn--h-2fa.no": 1,
  "xn--h1aegh.museum": 1,
  "xn--h1ahn.xn--p1acf": 1,
  "xn--h1aliz.xn--p1acf": 1,
  "xn--h3cuzk1di.xn--o3cw4h": 1,
  "xn--hbmer-xqa.no": 1,
  "xn--hcesuolo-7ya35b.no": 1,
  "xn--hebda8b.xn--4dbrk0ce": 1,
  "xn--hery-ira.nordland.no": 1,
  "xn--hery-ira.xn--mre-og-romsdal-qqb.no": 1,
  "xn--hgebostad-g3a.no": 1,
  "xn--hkkinen-5wa.fi": 1,
  "xn--hmmrfeasta-s4ac.no": 1,
  "xn--hnefoss-q1a.no": 1,
  "xn--hobl-ira.no": 1,
  "xn--holtlen-hxa.no": 1,
  "xn--hpmir-xqa.no": 1,
  "xn--hyanger-q1a.no": 1,
  "xn--hylandet-54a.no": 1,
  "xn--indery-fya.no": 1,
  "xn--io0a7i.cn": 1,
  "xn--io0a7i.hk": 1,
  "xn--j1adp.xn--p1acf": 1,
  "xn--j1aef.xn--p1acf": 1,
  "xn--j1ael8b.xn--p1acf": 1,
  "xn--jlster-bya.no": 1,
  "xn--jrpeland-54a.no": 1,
  "xn--k7yn95e.jp": 1,
  "xn--karmy-yua.no": 1,
  "xn--kbrq7o.jp": 1,
  "xn--kfjord-iua.no": 1,
  "xn--klbu-woa.no": 1,
  "xn--klt787d.jp": 1,
  "xn--kltp7d.jp": 1,
  "xn--kltx9a.jp": 1,
  "xn--klty5x.jp": 1,
  "xn--koluokta-7ya57h.no": 1,
  "xn--krager-gya.no": 1,
  "xn--kranghke-b0a.no": 1,
  "xn--krdsherad-m8a.no": 1,
  "xn--krehamn-dxa.no": 1,
  "xn--krjohka-hwab49j.no": 1,
  "xn--ksnes-uua.no": 1,
  "xn--kvfjord-nxa.no": 1,
  "xn--kvitsy-fya.no": 1,
  "xn--kvnangen-k0a.no": 1,
  "xn--l-1fa.no": 1,
  "xn--laheadju-7ya.no": 1,
  "xn--langevg-jxa.no": 1,
  "xn--lcvr32d.hk": 1,
  "xn--ldingen-q1a.no": 1,
  "xn--leagaviika-52b.no": 1,
  "xn--lesund-hua.no": 1,
  "xn--lgrd-poac.no": 1,
  "xn--lhppi-xqa.no": 1,
  "xn--linds-pra.no": 1,
  "xn--lns-qla.museum": 1,
  "xn--loabt-0qa.no": 1,
  "xn--lrdal-sra.no": 1,
  "xn--lrenskog-54a.no": 1,
  "xn--lt-liac.no": 1,
  "xn--lten-gra.no": 1,
  "xn--lury-ira.no": 1,
  "xn--m3ch0j3a.xn--o3cw4h": 1,
  "xn--mely-ira.no": 1,
  "xn--merker-kua.no": 1,
  "xn--mgba3a4f16a.ir": 1,
  "xn--mgba3a4fra.ir": 1,
  "xn--mjndalen-64a.no": 1,
  "xn--mk0axi.hk": 1,
  "xn--mkru45i.jp": 1,
  "xn--mlatvuopmi-s4a.no": 1,
  "xn--mli-tla.no": 1,
  "xn--mlselv-iua.no": 1,
  "xn--moreke-jua.no": 1,
  "xn--mori-qsa.nz": 1,
  "xn--mosjen-eya.no": 1,
  "xn--mot-tla.no": 1,
  "xn--msy-ula0h.no": 1,
  "xn--mtta-vrjjat-k7af.no": 1,
  "xn--muost-0qa.no": 1,
  "xn--mxtq1m.hk": 1,
  "xn--mxtq1m.xn--j6w193g": 1,
  "xn--nit225k.jp": 1,
  "xn--nmesjevuemie-tcba.no": 1,
  "xn--nry-yla5g.no": 1,
  "xn--ntso0iqx3a.jp": 1,
  "xn--ntsq17g.jp": 1,
  "xn--nttery-byae.no": 1,
  "xn--nvuotna-hwa.no": 1,
  "xn--o1ac.xn--90a3ac": 1,
  "xn--o1ach.xn--90a3ac": 1,
  "xn--o3cyx2a.xn--o3cw4h": 1,
  "xn--od0alg.cn": 1,
  "xn--od0alg.hk": 1,
  "xn--od0alg.xn--j6w193g": 1,
  "xn--od0aq3b.hk": 1,
  "xn--oppegrd-ixa.no": 1,
  "xn--ostery-fya.no": 1,
  "xn--osyro-wua.no": 1,
  "xn--porsgu-sta26f.no": 1,
  "xn--pssu33l.jp": 1,
  "xn--qqqt11m.jp": 1,
  "xn--rady-ira.no": 1,
  "xn--rdal-poa.no": 1,
  "xn--rde-ula.no": 1,
  "xn--rdy-0nab.no": 1,
  "xn--rennesy-v1a.no": 1,
  "xn--rhkkervju-01af.no": 1,
  "xn--rholt-mra.no": 1,
  "xn--rht27z.jp": 1,
  "xn--rht3d.jp": 1,
  "xn--rht61e.jp": 1,
  "xn--risa-5na.no": 1,
  "xn--risr-ira.no": 1,
  "xn--rland-uua.no": 1,
  "xn--rlingen-mxa.no": 1,
  "xn--rmskog-bya.no": 1,
  "xn--rny31h.jp": 1,
  "xn--rros-gra.no": 1,
  "xn--rskog-uua.no": 1,
  "xn--rst-0na.no": 1,
  "xn--rsta-fra.no": 1,
  "xn--ryken-vua.no": 1,
  "xn--ryrvik-bya.no": 1,
  "xn--s-1fa.no": 1,
  "xn--sandnessjen-ogb.no": 1,
  "xn--sandy-yua.no": 1,
  "xn--sdtirol-n2a.it": 1,
  "xn--seral-lra.no": 1,
  "xn--sgne-gra.no": 1,
  "xn--skierv-uta.no": 1,
  "xn--skjervy-v1a.no": 1,
  "xn--skjk-soa.no": 1,
  "xn--sknit-yqa.no": 1,
  "xn--sknland-fxa.no": 1,
  "xn--slat-5na.no": 1,
  "xn--slt-elab.no": 1,
  "xn--smla-hra.no": 1,
  "xn--smna-gra.no": 1,
  "xn--snase-nra.no": 1,
  "xn--sndre-land-0cb.no": 1,
  "xn--snes-poa.no": 1,
  "xn--snsa-roa.no": 1,
  "xn--sr-aurdal-l8a.no": 1,
  "xn--sr-fron-q1a.no": 1,
  "xn--sr-odal-q1a.no": 1,
  "xn--sr-varanger-ggb.no": 1,
  "xn--srfold-bya.no": 1,
  "xn--srreisa-q1a.no": 1,
  "xn--srum-gra.no": 1,
  "xn--stjrdal-s1a.no": 1,
  "xn--stjrdalshalsen-sqb.no": 1,
  "xn--stre-toten-zcb.no": 1,
  "xn--tjme-hra.no": 1,
  "xn--tn0ag.hk": 1,
  "xn--tnsberg-q1a.no": 1,
  "xn--tor131o.jp": 1,
  "xn--trany-yua.no": 1,
  "xn--trentin-sd-tirol-rzb.it": 1,
  "xn--trentin-sdtirol-7vb.it": 1,
  "xn--trentino-sd-tirol-c3b.it": 1,
  "xn--trentino-sdtirol-szb.it": 1,
  "xn--trentinosd-tirol-rzb.it": 1,
  "xn--trentinosdtirol-7vb.it": 1,
  "xn--trentinsd-tirol-6vb.it": 1,
  "xn--trentinsdtirol-nsb.it": 1,
  "xn--trgstad-r1a.no": 1,
  "xn--trna-woa.no": 1,
  "xn--troms-zua.no": 1,
  "xn--tysvr-vra.no": 1,
  "xn--uc0atv.hk": 1,
  "xn--uc0atv.tw": 1,
  "xn--uc0atv.xn--j6w193g": 1,
  "xn--uc0ay4a.hk": 1,
  "xn--uist22h.jp": 1,
  "xn--uisz3g.jp": 1,
  "xn--unjrga-rta.no": 1,
  "xn--uuwu58a.jp": 1,
  "xn--vads-jra.no": 1,
  "xn--valle-aoste-ebb.it": 1,
  "xn--valle-d-aoste-ehb.it": 1,
  "xn--valleaoste-e7a.it": 1,
  "xn--valledaoste-ebb.it": 1,
  "xn--vard-jra.no": 1,
  "xn--vegrshei-c0a.no": 1,
  "xn--vestvgy-ixa6o.no": 1,
  "xn--vg-yiab.no": 1,
  "xn--vgan-qoa.no": 1,
  "xn--vgsy-qoa0j.no": 1,
  "xn--vgu402c.jp": 1,
  "xn--vler-qoa.hedmark.no": 1,
  "xn--vler-qoa.xn--stfold-9xa.no": 1,
  "xn--vre-eiker-k8a.no": 1,
  "xn--vrggt-xqad.no": 1,
  "xn--vry-yla5g.no": 1,
  "xn--wcvs22d.hk": 1,
  "xn--wcvs22d.xn--j6w193g": 1,
  "xn--yer-zna.no": 1,
  "xn--ygarden-p1a.no": 1,
  "xn--ystre-slidre-ujb.no": 1,
  "xn--zbx025d.jp": 1,
  "xn--zf0ao64a.tw": 1,
  "xn--zf0avx.hk": 1,
  "xnbay.com": 1,
  "xs4all.space": 1,
  "xx.gl": 1,
  "xy.ax": 1,
  "xz.cn": 1,
  "y.bg": 1,
  "y.se": 1,
  "yabu.hyogo.jp": 1,
  "yabuki.fukushima.jp": 1,
  "yachimata.chiba.jp": 1,
  "yachiyo.chiba.jp": 1,
  "yachiyo.ibaraki.jp": 1,
  "yaese.okinawa.jp": 1,
  "yahaba.iwate.jp": 1,
  "yahiko.niigata.jp": 1,
  "yaita.tochigi.jp": 1,
  "yaizu.shizuoka.jp": 1,
  "yakage.okayama.jp": 1,
  "yakumo.hokkaido.jp": 1,
  "yakumo.shimane.jp": 1,
  "yali.mythic-beasts.com": 1,
  "yalta.ua": 1,
  "yamada.fukuoka.jp": 1,
  "yamada.iwate.jp": 1,
  "yamada.toyama.jp": 1,
  "yamaga.kumamoto.jp": 1,
  "yamagata.gifu.jp": 1,
  "yamagata.ibaraki.jp": 1,
  "yamagata.jp": 1,
  "yamagata.nagano.jp": 1,
  "yamagata.yamagata.jp": 1,
  "yamaguchi.jp": 1,
  "yamakita.kanagawa.jp": 1,
  "yamamoto.miyagi.jp": 1,
  "yamanakako.yamanashi.jp": 1,
  "yamanashi.jp": 1,
  "yamanashi.yamanashi.jp": 1,
  "yamanobe.yamagata.jp": 1,
  "yamanouchi.nagano.jp": 1,
  "yamashina.kyoto.jp": 1,
  "yamato.fukushima.jp": 1,
  "yamato.kanagawa.jp": 1,
  "yamato.kumamoto.jp": 1,
  "yamatokoriyama.nara.jp": 1,
  "yamatotakada.nara.jp": 1,
  "yamatsuri.fukushima.jp": 1,
  "yamazoe.nara.jp": 1,
  "yame.fukuoka.jp": 1,
  "yanagawa.fukuoka.jp": 1,
  "yanaizu.fukushima.jp": 1,
  "yandexcloud.net": 1,
  "yao.osaka.jp": 1,
  "yaotsu.gifu.jp": 1,
  "yasaka.nagano.jp": 1,
  "yashio.saitama.jp": 1,
  "yashiro.hyogo.jp": 1,
  "yasu.shiga.jp": 1,
  "yasuda.kochi.jp": 1,
  "yasugi.shimane.jp": 1,
  "yasuoka.nagano.jp": 1,
  "yatomi.aichi.jp": 1,
  "yatsuka.shimane.jp": 1,
  "yatsushiro.kumamoto.jp": 1,
  "yawara.ibaraki.jp": 1,
  "yawata.kyoto.jp": 1,
  "yawatahama.ehime.jp": 1,
  "yazu.tottori.jp": 1,
  "ybo.faith": 1,
  "ybo.party": 1,
  "ybo.review": 1,
  "ybo.science": 1,
  "ybo.trade": 1,
  "yk.ca": 1,
  "yn.cn": 1,
  "ynh.fr": 1,
  "yoichi.hokkaido.jp": 1,
  "yoita.niigata.jp": 1,
  "yoka.hyogo.jp": 1,
  "yokaichiba.chiba.jp": 1,
  "yokawa.hyogo.jp": 1,
  "yokkaichi.mie.jp": 1,
  "yokohama.jp": 2,
  "yokoshibahikari.chiba.jp": 1,
  "yokosuka.kanagawa.jp": 1,
  "yokote.akita.jp": 1,
  "yokoze.saitama.jp": 1,
  "yolasite.com": 1,
  "yombo.me": 1,
  "yomitan.okinawa.jp": 1,
  "yonabaru.okinawa.jp": 1,
  "yonago.tottori.jp": 1,
  "yonaguni.okinawa.jp": 1,
  "yonezawa.yamagata.jp": 1,
  "yono.saitama.jp": 1,
  "yorii.saitama.jp": 1,
  "york.museum": 1,
  "yorkshire.museum": 1,
  "yoro.gifu.jp": 1,
  "yosemite.museum": 1,
  "yoshida.saitama.jp": 1,
  "yoshida.shizuoka.jp": 1,
  "yoshikawa.saitama.jp": 1,
  "yoshimi.saitama.jp": 1,
  "yoshino.nara.jp": 1,
  "yoshinogari.saga.jp": 1,
  "yoshioka.gunma.jp": 1,
  "yotsukaido.chiba.jp": 1,
  "youth.museum": 1,
  "yuasa.wakayama.jp": 1,
  "yufu.oita.jp": 1,
  "yugawa.fukushima.jp": 1,
  "yugawara.kanagawa.jp": 1,
  "yuki.ibaraki.jp": 1,
  "yukuhashi.fukuoka.jp": 1,
  "yura.wakayama.jp": 1,
  "yurihonjo.akita.jp": 1,
  "yusuhara.kochi.jp": 1,
  "yusui.kagoshima.jp": 1,
  "yuu.yamaguchi.jp": 1,
  "yuza.yamagata.jp": 1,
  "yuzawa.niigata.jp": 1,
  "z.bg": 1,
  "z.se": 1,
  "za.bz": 1,
  "za.com": 1,
  "za.net": 1,
  "za.org": 1,
  "zachpomor.pl": 1,
  "zagan.pl": 1,
  "zakopane.pl": 1,
  "zama.kanagawa.jp": 1,
  "zamami.okinawa.jp": 1,
  "zao.miyagi.jp": 1,
  "zaporizhzhe.ua": 1,
  "zaporizhzhia.ua": 1,
  "zapto.org": 1,
  "zapto.xyz": 1,
  "zarow.pl": 1,
  "zentsuji.kagawa.jp": 1,
  "zgora.pl": 1,
  "zgorzelec.pl": 1,
  "zhitomir.ua": 1,
  "zhytomyr.ua": 1,
  "zj.cn": 1,
  "zlg.br": 1,
  "zombie.jp": 1,
  "zoological.museum": 1,
  "zoology.museum": 1,
  "zp.gov.pl": 1,
  "zp.ua": 1,
  "zt.ua": 1,
  "zushi.kanagawa.jp": 1
}

/***/ }),

/***/ "./node_modules/adblockpluscore/data/resources.js":
/*!********************************************************!*\
  !*** ./node_modules/adblockpluscore/data/resources.js ***!
  \********************************************************/
/***/ ((__unused_webpack_module, exports) => {

exports.resources = {
  "blank-text": "data:text/plain,",
  "blank-css": "data:text/css,",
  "blank-js": "data:application/javascript,",
  "blank-html": "data:text/html,<!DOCTYPE html><html><head></head><body></body></html>",
  "blank-mp3": "data:audio/mpeg;base64,SUQzBAAAAAAAI1RTU0UAAAAPAAADTGF2ZjU4LjIwLjEwMAAAAAAAAAAAAAAA//tUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASW5mbwAAAA8AAAAGAAADAABgYGBgYGBgYGBgYGBgYGBggICAgICAgICAgICAgICAgICgoKCgoKCgoKCgoKCgoKCgwMDAwMDAwMDAwMDAwMDAwMDg4ODg4ODg4ODg4ODg4ODg4P////////////////////8AAAAATGF2YzU4LjM1AAAAAAAAAAAAAAAAJAYAAAAAAAAAAwDVxttG//sUZAAP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAETEFNRTMuMTAwVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZB4P8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZDwP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZFoP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZHgP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV//sUZJYP8AAAaQAAAAgAAA0gAAABAAABpAAAACAAADSAAAAEVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV",
  "blank-mp4": "data:video/mp4;base64,AAAAIGZ0eXBpc29tAAACAGlzb21pc28yYXZjMW1wNDEAAAAIZnJlZQAAAuJtZGF0AAACrwYF//+r3EXpvebZSLeWLNgg2SPu73gyNjQgLSBjb3JlIDE2MCByMzAxMU0gY2RlOWE5MyAtIEguMjY0L01QRUctNCBBVkMgY29kZWMgLSBDb3B5bGVmdCAyMDAzLTIwMjAgLSBodHRwOi8vd3d3LnZpZGVvbGFuLm9yZy94MjY0Lmh0bWwgLSBvcHRpb25zOiBjYWJhYz0xIHJlZj0zIGRlYmxvY2s9MTowOjAgYW5hbHlzZT0weDM6MHgxMTMgbWU9aGV4IHN1Ym1lPTcgcHN5PTEgcHN5X3JkPTEuMDA6MC4wMCBtaXhlZF9yZWY9MSBtZV9yYW5nZT0xNiBjaHJvbWFfbWU9MCB0cmVsbGlzPTEgOHg4ZGN0PTEgY3FtPTAgZGVhZHpvbmU9MjEsMTEgZmFzdF9wc2tpcD0xIGNocm9tYV9xcF9vZmZzZXQ9LTIgdGhyZWFkcz0yIGxvb2thaGVhZF90aHJlYWRzPTEgc2xpY2VkX3RocmVhZHM9MCBucj0wIGRlY2ltYXRlPTEgaW50ZXJsYWNlZD0wIGJsdXJheV9jb21wYXQ9MCBjb25zdHJhaW5lZF9pbnRyYT0wIGJmcmFtZXM9MyBiX3B5cmFtaWQ9MiBiX2FkYXB0PTEgYl9iaWFzPTAgZGlyZWN0PTEgd2VpZ2h0Yj0xIG9wZW5fZ29wPTAgd2VpZ2h0cD0yIGtleWludD0yNTAga2V5aW50X21pbj0yNSBzY2VuZWN1dD00MCBpbnRyYV9yZWZyZXNoPTAgcmNfbG9va2FoZWFkPTQwIHJjPWNyZiBtYnRyZWU9MSBjcmY9MjMuMCBxY29tcD0wLjYwIHFwbWluPTAgcXBtYXg9NjkgcXBzdGVwPTQgaXBfcmF0aW89MS40MCBhcT0xOjEuMDAAgAAAACNliIQAK//+9dvzLK5umjbe9jc2CT9EPcfnoOYC2tjtP+go4QAAAwRtb292AAAAbG12aGQAAAAAAAAAAAAAAAAAAAPoAAAAKAABAAABAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAACLnRyYWsAAABcdGtoZAAAAAMAAAAAAAAAAAAAAAEAAAAAAAAAKAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAEAAAAAAZAAAADgAAAAAACRlZHRzAAAAHGVsc3QAAAAAAAAAAQAAACgAAAAAAAEAAAAAAaZtZGlhAAAAIG1kaGQAAAAAAAAAAAAAAAAAADIAAAACAFXEAAAAAAAtaGRscgAAAAAAAAAAdmlkZQAAAAAAAAAAAAAAAFZpZGVvSGFuZGxlcgAAAAFRbWluZgAAABR2bWhkAAAAAQAAAAAAAAAAAAAAJGRpbmYAAAAcZHJlZgAAAAAAAAABAAAADHVybCAAAAABAAABEXN0YmwAAACtc3RzZAAAAAAAAAABAAAAnWF2YzEAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAZAA4AEgAAABIAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY//8AAAA3YXZjQwFkAAr/4QAaZ2QACvNlHJ42JwEQAAADABAAAAMDIPEiWWABAAZo6+PLIsD8+PgAAAAAEHBhc3AAAAABAAAAAQAAABhzdHRzAAAAAAAAAAEAAAABAAACAAAAABxzdHNjAAAAAAAAAAEAAAABAAAAAQAAAAEAAAAUc3RzegAAAAAAAALaAAAAAQAAABRzdGNvAAAAAAAAAAEAAAAwAAAAYnVkdGEAAABabWV0YQAAAAAAAAAhaGRscgAAAAAAAAAAbWRpcmFwcGwAAAAAAAAAAAAAAAAtaWxzdAAAACWpdG9vAAAAHWRhdGEAAAABAAAAAExhdmY1OC40NS4xMDA=",
  "1x1-transparent-gif": "data:image/gif;base64,R0lGODlhAQABAIABAAAAAP///yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
  "2x2-transparent-png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAIAAAACCAYAAABytg0kAAAAC0lEQVQI12NgQAcAABIAAe+JVKQAAAAASUVORK5CYII=",
  "3x2-transparent-png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAACCAYAAACddGYaAAAAC0lEQVQI12NgwAUAABoAASRETuUAAAAASUVORK5CYII=",
  "32x32-transparent-png": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAAGklEQVRYw+3BAQEAAACCIP+vbkhAAQAAAO8GECAAAZf3V9cAAAAASUVORK5CYII="
}

/***/ }),

/***/ "./node_modules/adblockpluscore/lib/analytics.js":
/*!*******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/analytics.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_187056__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



const {Prefs} = __nested_webpack_require_187056__(/*! prefs */ "./sdk/api/prefs.js");

const {MILLIS_IN_DAY} = __nested_webpack_require_187056__(/*! ./time */ "./node_modules/adblockpluscore/lib/time.js");

/**
 * Converts a version string into a `Date` object with minute-level precision.
 *
 * @param {string} version The version string in `YYYYMMDD[HH[MM]]` format or
 *   just the value `"0"`.
 *
 * @returns {Date} A `Date` object. If the value of `version` is `"0"`, the
 *   returned value represents the Unix epoch.
 */
function versionToDate(version) {
  if (version == "0")
    return new Date(0);

  let year = version.substring(0, 4);
  let month = version.substring(4, 6);
  let date = version.substring(6, 8);

  let hours = version.substring(8, 10) || "00";
  let minutes = version.substring(10, 12) || "00";

  // The input is nearly a valid ISO 8601 timestamp, except for the hyphens,
  // the colon, and the special characters T and Z. We can use the timestamp
  // string version of the Date constructor directly. Alternatively, we could
  // use Date.UTC(), but that would require some adjustment to the values
  // (e.g. the month must be 0-based).
  return new Date(`${year}-${month}-${date}T${hours}:${minutes}Z`);
}

/**
 * Strips the value of the `firstVersion` parameter down to either `YYYYMMDD`,
 * `YYYYMM`, or `YYYY` depending on its distance from the value of the
 * `currentVersion` parameter.
 *
 * @param {string} firstVersion A version string in `YYYYMMDD[HH[MM]]` format
 *   with an optional `"-E"` suffix or just `"0"` or `"0-E"`.
 * @param {string} currentVersion A version string in `YYYYMMDD[HH[MM]]` format
 *   or just `"0"`.
 *
 * @returns {?string}
 */
function stripFirstVersion(firstVersion, currentVersion) {
  let eFlag = firstVersion.endsWith("-E");
  if (eFlag)
    firstVersion = firstVersion.slice(0, -2);

  try {
    let firstDate = versionToDate(firstVersion);
    let currentDate = versionToDate(currentVersion);

    if (currentDate - firstDate > 365 * MILLIS_IN_DAY)
      firstVersion = firstVersion.substring(0, 4);
    else if (currentDate - firstDate > 30 * MILLIS_IN_DAY)
      firstVersion = firstVersion.substring(0, 6);
    else
      firstVersion = firstVersion.substring(0, 8);
  }
  catch (error) {
    return null;
  }

  if (eFlag)
    firstVersion += "-E";

  return firstVersion;
}

/**
 * Checks whether this is a fresh installation.
 * @returns {boolean}
 */
function isFreshInstall() {
  return !("data" in Prefs.notificationdata);
}

/**
 * `{@link module:analytics.analytics analytics}` implementation.
 */
class Analytics {
  /**
   * @hideconstructor
   */
  constructor() {
  }

  /**
   * Checks whether the given URL is trusted for analytics purposes based on
   * the value of the `analytics.trustedHosts` preference.
   *
   * @param {string} url The URL.
   *
   * @returns {boolean} Whether the URL is trusted.
   */
  isTrusted(url) {
    let {trustedHosts} = Prefs.analytics || {};
    if (Array.isArray(trustedHosts)) {
      try {
        return trustedHosts.includes(new URL(url).host);
      }
      catch (error) {
      }
    }

    return false;
  }

  /**
   * Returns a string indicating the version of the first ever downloaded
   * resource (as recorded by
   * `{@link module:analytics~Analytics#recordVersion recordVersion()}`), for
   * the purpose of cohort analysis.
   *
   * For privacy reasons, the original value is stripped down to either
   * `YYYYMMDD`, `YYYYMM`, or `YYYY` depending on its age. An `-E` suffix is
   * appended to the original value if it was recorded on an existing
   * installation.
   *
   * @returns {?string} A string indicating the version of the first ever
   *   downloaded resource, or `"0"` or `"0-E"` if there is no data, or `null`
   *   in case of a parsing error.
   */
  getFirstVersion() {
    let {analytics} = Prefs;
    if (analytics) {
      let {firstVersion = "0", currentVersion = "0"} = analytics.data || {};
      let strippedFirstVersion = stripFirstVersion(firstVersion,
                                                   currentVersion);
      if (strippedFirstVersion) {
        if (strippedFirstVersion == "0" && !isFreshInstall())
          strippedFirstVersion = "0-E";

        return strippedFirstVersion;
      }
    }

    return null;
  }

  /**
   * Records the version of a downloaded resource for the purpose of cohort
   * analysis.
   *
   * The value of the `analytics` preference must be set at least to an
   * empty object, otherwise nothing is ever recorded and
   * `{@link module:analytics~Analytics#getFirstVersion getFirstVersion()}`
   * always returns `null`.
   *
   * @param {string} version The version, in `YYYYMMDD[HH[MM]]` format.
   */
  recordVersion(version) {
    if (!/^(\d{8}|\d{10}|\d{12})$/.test(version))
      return;

    let {analytics} = Prefs;
    if (analytics) {
      if (!analytics.data)
        analytics.data = {};

      let {data} = analytics;

      data.currentVersion = version;

      if (typeof data.firstVersion == "undefined") {
        // If this is not a new installation, set the -E flag.
        if (!isFreshInstall())
          version += "-E";

        data.firstVersion = version;
      }

      // JSON values aren't saved unless they are assigned a different object.
      Prefs.analytics = JSON.parse(JSON.stringify(analytics));
    }
  }
}

/**
 * Implements data analytics functions.
 * @type {module:analytics~Analytics}
 */
exports.analytics = new Analytics();


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/caching.js":
/*!*****************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/caching.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * A `Cache` object represents a cache of arbitrary data.
 * @package
 */
exports.Cache = class Cache extends Map {
  /**
   * Creates a cache.
   * @param {number} capacity The maximum number of entries that can exist in
   *   the cache.
   */
  constructor(capacity) {
    // Note: This check works for non-number values.
    if (!(capacity >= 1))
      throw new Error("capacity must be a positive number.");

    super();
    this._capacity = capacity;
  }

  /**
   * Writes an entry to the cache.
   *
   * If the cache has reached the specified maximum number of entries, all the
   * old entries are cleared first.
   *
   * @param {?*} key The key for the entry.
   * @param {?*} value The value of the entry.
   */
  set(key, value) {
    // To prevent logical errors, neither key nor value is allowed to be
    // undefined.
    if (typeof key == "undefined")
      throw new Error("key must not be undefined.");

    if (typeof value == "undefined")
      throw new Error("value must not be undefined.");

    if (this.size == this._capacity && !this.has(key))
      this.clear();

    super.set(key, value);
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/contentTypes.js":
/*!**********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/contentTypes.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



let contentTypes =
/**
 * Content types for request blocking and allowing (allowlisting).
 *
 * There are two kinds of content types: resource types, and special
 * (non-resource) types.
 *
 * Resource types include web resources like scripts, images, and so on.
 *
 * Special types include filter options for popup blocking and CSP header
 * injection as well as flags for allowing documents.
 *
 * By default a filter matches any resource type, but if a filter has an
 * explicit resource type, special option, or allowing flag, like
 * `$script`, `$popup`, or `$elemhide`, then it matches only the given type,
 * option, or flag.
 *
 * @type {Object}
 *
 * @public
 */
exports.contentTypes = {
  // Types of web resources.
  OTHER: 1,
  SCRIPT: 2,
  IMAGE: 4,
  STYLESHEET: 8,
  OBJECT: 16,
  SUBDOCUMENT: 32,
  WEBSOCKET: 128,
  WEBRTC: 256,
  PING: 1024,
  XMLHTTPREQUEST: 2048, // 1 << 11

  MEDIA: 16384,
  FONT: 32768, // 1 << 15

  // Special filter options.
  POPUP: 1 << 24,
  CSP: 1 << 25,
  HEADER: 1 << 26,

  // Allowing flags.
  DOCUMENT: 1 << 27,
  GENERICBLOCK: 1 << 28,
  ELEMHIDE: 1 << 29,
  GENERICHIDE: 1 << 30
};

// Backwards compatibility.
contentTypes.BACKGROUND = contentTypes.IMAGE;
contentTypes.XBL = contentTypes.OTHER;
contentTypes.DTD = contentTypes.OTHER;

const RESOURCE_TYPES =
/**
 * Bitmask for resource types like `$script`, `$image`, `$stylesheet`, and so
 * on.
 *
 * If a filter has no explicit content type, it applies to all resource types
 * (but not to any {@link module:contentTypes.SPECIAL_TYPES special types}).
 *
 * @const {number}
 *
 * @package
 */
// The first 24 bits are reserved for resource types like "script", "image",
// and so on.
// https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/ResourceType
exports.RESOURCE_TYPES = (1 << 24) - 1;

const SPECIAL_TYPES = ~RESOURCE_TYPES & (1 << 31) - 1;
/**
 * Bitmask for special "types" (options and flags) like `$csp`, `$elemhide`,
 * and so on.
 *
 * @const {number}
 *
 * @package
 */
exports.SPECIAL_TYPES = SPECIAL_TYPES;

/**
 * Bitmask for "types" that match against request context more than
 * actual content type. When matching against context types, you
 * should also include the request's resource type.
 *
 * @const {number}
 *
 * @package
 */
const CONTEXT_TYPES = contentTypes.HEADER | contentTypes.CSP;
exports.CONTEXT_TYPES = CONTEXT_TYPES;

/**
 * Bitmask for "types" (flags) that are for exception rules only, like
 * `$document`, `$elemhide`, and so on.
 *
 * @const {number}
 *
 * @package
 */
exports.ALLOWING_TYPES = contentTypes.DOCUMENT |
                         contentTypes.GENERICBLOCK |
                         contentTypes.ELEMHIDE |
                         contentTypes.GENERICHIDE;

/**
 * Yields individual types from a filter's type mask.
 *
 * @param {number} contentType A filter's type mask.
 * @param {number} [selection] Which types to yield.
 *
 * @generator
 * @yields {number}
 *
 * @package
 */
exports.enumerateTypes = function* enumerateTypes(contentType, selection = ~0) {
  for (let mask = contentType & selection, bitIndex = 0;
    mask != 0; mask >>>= 1, bitIndex++) {
    if ((mask & 1) != 0) {
      // Note: The zero-fill right shift by zero is necessary for dropping the
      // sign.
      yield 1 << bitIndex >>> 0;
    }
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/dnr/index.js":
/*!*******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/dnr/index.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_200094__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



/** @module */

const {Pattern} = __nested_webpack_require_200094__(/*! ../patterns */ "./node_modules/adblockpluscore/lib/patterns.js");
const {parseDomains} = __nested_webpack_require_200094__(/*! ../url */ "./node_modules/adblockpluscore/lib/url.js");
const {contentTypes, RESOURCE_TYPES} = __nested_webpack_require_200094__(/*! ../contentTypes */ "./node_modules/adblockpluscore/lib/contentTypes.js");
const {
  generateCSPRules,
  generateAllowingRules,
  generateRedirectRules,
  generateBlockingRules,
  validateRule
} = __nested_webpack_require_200094__(/*! ./rules */ "./node_modules/adblockpluscore/lib/dnr/rules.js");
const {parse, FilterParsingError} = __nested_webpack_require_200094__(/*! ../filters */ "./node_modules/adblockpluscore/lib/filters/index.js");

/**
 * @typedef {Object} ConverterOptions
 * @property {function} isRegexSupported a sync/async method to check if a
 *  generic regular expression is compatible with the engine.
 * @property {function} modifyRule a sync method to modify a DNR rule if needed.
 */

/**
 * Returns a callback bound to the given options.
 * @param {ConverterOptions} options in Mv3 Web extensions this would be
 *  `chrome.declarativeNetRequest.isRegexSupported`, so that it's possible to
 *  pass `chrome.declarativeNetRequest` directly as option.
 * @returns {function}
 */
exports.createConverter = options => convert.bind({
  ...options,
  // ensure a callback to verify RegExp when needed
  // By default regex are not supported.
  isRegexSupported: options.isRegexSupported || (() => false),
  // ensure a callback to modify a DNR rule when needed
  modifyRule: options.modifyRule || ((rule, context) => rule)
});

/**
 * @typedef {Object} Rule see https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-Rule
 * @property {object} action see https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-RuleAction
 * @property {object} condition see https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-RuleCondition
 * @property {number} id a unique identifier for this rule
 * @property {number?} priority optional priority of the filter
 */

/**
 * Returns an array with DNR Rules if the text is network related, or an Error
 * if no suitable rule can be created.
 * @param {string} text the filter text to convert or the generated error.
 * @param {number} line the line number of the filter text.
 * @returns {Rule[]|FilterParsingError}
 */
function convert(text, line) {
  const result = parse(text);

  if (result instanceof FilterParsingError)
    return result;

  return asDNR.call(this, result, line);
}

/** Convert a parsed filter to a DeclarativeNetRequest
 *
 * To work properly this function must be bound to an object that
 * has a method `isRegexSupported` that will return whether the RegExp
 * passed as argument is valid or not for DNR. This is necessary as
 * they have to be RE2 expection and this syntax isn't supported by native
 * JavaScript. There is a (native) node module or the Chrome WebExtension
 * API. `createConverter` will provide a default function that always
 * return true.
 *
 * @param {module:filters/index~ParsedFilter} parsedFilter The parsed filter
 *   object.
 * @param {number} line The parsed filter line number
 * @return {Rule[]|Error}
 */
function asDNR(parsedFilter, line) {
  let {
    blocking,
    text,
    regexpSource,
    contentType,
    matchCase,
    domains,
    thirdParty,
    sitekeys,
    header,
    rewrite,
    csp
  } = parsedFilter;

  // Sitekey aren't currently handled with DeclarativeNetRequest
  if (sitekeys || header) {
    return new FilterParsingError("filter_unknown_option",
                                  {
                                    option: sitekeys ? "sitekey" : "header",
                                    text
                                  });
  }

  try {
    const urlPattern = new Pattern(regexpSource, matchCase);
    let {pattern: urlFilter} = urlPattern;
    let checkValidRegExp = true;
    let hostname;

    matchCase = urlPattern.matchCase;

    if (urlFilter) {
      // We need to split out the hostname part (if any) of the filter, then
      // decide if it can be matched as lowercase or not.
      let match = /^(\|\||[a-zA-Z]*:\/\/)([^*^?/|]*)(.*)$/.exec(urlFilter);
      if (match) {
        hostname = match[2].toLowerCase();

        urlFilter = match[1] + hostname + match[3];
        matchCase = matchCase ||
                    match[3].length < 2 ||
                    !/[a-zA-Z]/.test(match[3]);
      }

      // The declarativeNetRequest API does not like the urlFilter to have a
      // redundant ||* prefix, so let's strip that now.
      if (urlFilter.startsWith("||*"))
        // A pattern beginning with `||*` isn't allowed, and `*`
        // should be used instead. So let's remove the `||`
        // See https://developer.chrome.com/docs/extensions/reference/declarativeNetRequest/#type-RuleCondition
        urlFilter = urlFilter.substr(2);
    }
    else if (urlPattern.regexp) {
      checkValidRegExp = this.isRegexSupported({
        regex: urlPattern.regexp.source,
        isCaseSensitive: matchCase
      });
    }

    if (!checkValidRegExp) {
      return new FilterParsingError("filter_invalid_regexp",
                                    {
                                      regexp: urlPattern.regexp.source,
                                      text
                                    });
    }

    const filter = {
      blocking,
      regexp: urlPattern.regexp,
      contentType: contentType || RESOURCE_TYPES,
      thirdParty,
      rewrite,
      csp,
      domains: domains === null ? null : parseDomains(
        domains.toLowerCase(), "|")
    };

    let result;
    if (contentType & contentTypes.CSP)
      result = generateCSPRules(filter, urlFilter, matchCase);
    else if (!blocking)
      result = generateAllowingRules(filter, urlFilter, matchCase);
    else if (rewrite)
      result = generateRedirectRules(filter, urlFilter, matchCase);
    else
      result = generateBlockingRules(filter, urlFilter, matchCase);

    let context = {
      text: parsedFilter.text,
      line
    };
    return result
      .map(rule => this.modifyRule(rule, context))
      .map(validateRule);
  }
  catch (error) {
    return new FilterParsingError("filter_invalid_regexp",
                                  {regexp: regexpSource, text});
  }
}

exports.asDNR = asDNR;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/dnr/rules.js":
/*!*******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/dnr/rules.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_207542__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



/** @module */

const {contentTypes} = __nested_webpack_require_207542__(/*! ../contentTypes */ "./node_modules/adblockpluscore/lib/contentTypes.js");
const {resources} = __nested_webpack_require_207542__(/*! ../../data/resources.js */ "./node_modules/adblockpluscore/data/resources.js");

// We differentiate generic rules from specific ones in order to support the
// conversion of $genericblock exception filters. Since with the
// declarativeNetRequest API "allow" rules take priority over "allowAllRequest"
// rules, we also need to take care to give "allowAllRequest" rules a slighlty
// higher priority.
const GENERIC_PRIORITY = 1000;
exports.GENERIC_PRIORITY = GENERIC_PRIORITY;
const GENERIC_ALLOW_ALL_PRIORITY = 1001;
exports.GENERIC_ALLOW_ALL_PRIORITY = GENERIC_ALLOW_ALL_PRIORITY;
const SPECIFIC_PRIORITY = 2000;
exports.SPECIFIC_PRIORITY = SPECIFIC_PRIORITY;
const SPECIFIC_ALLOW_ALL_PRIORITY = 2001;
exports.SPECIFIC_ALLOW_ALL_PRIORITY = SPECIFIC_ALLOW_ALL_PRIORITY;


const requestTypes = new Map([
  [contentTypes.OTHER, ["other", "csp_report"]],
  [contentTypes.SCRIPT, ["script"]],
  [contentTypes.IMAGE, ["image"]],
  [contentTypes.STYLESHEET, ["stylesheet"]],
  [contentTypes.OBJECT, ["object"]],
  [contentTypes.SUBDOCUMENT, ["sub_frame"]],
  [contentTypes.WEBSOCKET, ["websocket"]],
  [contentTypes.PING, ["ping"]],
  [contentTypes.XMLHTTPREQUEST, ["xmlhttprequest"]],
  [contentTypes.MEDIA, ["media"]],
  [contentTypes.FONT, ["font"]]
]);
exports.requestTypes = requestTypes;

const supportedRequestTypes = Array.from(requestTypes.keys())
                                   .reduce(((srt, t) => srt | t));
exports.supportedRequestTypes = supportedRequestTypes;

function getResourceTypes(filterContentType) {
  // The default is to match everything except "main_frame", which is fine.
  if ((filterContentType & supportedRequestTypes) == supportedRequestTypes)
    return;

  let result = [];

  for (let [mask, types] of requestTypes) {
    if (filterContentType & mask)
      result = result.concat(types);
  }

  return result;
}

function getDomains(filterDomains) {
  let domains = [];
  let excludedDomains = [];
  let isGenericFilter = true;

  if (filterDomains) {
    for (let [domain, enabled] of filterDomains) {
      if (domain == "")
        isGenericFilter = enabled;
      else
        (enabled ? domains : excludedDomains).push(domain);
    }
  }

  return {domains, excludedDomains, isGenericFilter};
}

function getCondition(filter, urlFilter, resourceTypes, matchCase) {
  let condition = {};

  if (urlFilter)
    condition.urlFilter = urlFilter;
  else if (filter.regexp)
    condition.regexFilter = filter.regexp.source;

  if (resourceTypes)
    condition.resourceTypes = resourceTypes;

  if (!matchCase)
    condition.isUrlFilterCaseSensitive = false;

  if (filter.thirdParty != null)
    condition.domainType = filter.thirdParty ? "thirdParty" : "firstParty";

  let {domains, excludedDomains, isGenericFilter} = getDomains(filter.domains);

  if (domains.length)
    condition.domains = domains;
  if (excludedDomains.length)
    condition.excludedDomains = excludedDomains;

  return [condition, isGenericFilter];
}

exports.generateRedirectRules = function(filter, urlFilter, matchCase) {
  let url = resources[filter.rewrite];

  // We can't generate rules for unknown abp-resources...
  if (!url)
    return [];

  let resourceTypes = getResourceTypes(filter.contentType);

  // We can't generate rules for filters which don't include any supported
  // resource types.
  if (resourceTypes && resourceTypes.length == 0)
    return [];

  let [condition, isGenericFilter] = getCondition(
    filter, urlFilter, resourceTypes, matchCase
  );

  return [{
    priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY,
    condition,
    action: {
      type: "redirect",
      redirect: {url}
    }
  }];
};

exports.generateCSPRules = function(filter, urlFilter, matchCase) {
  let [condition, isGenericFilter] = getCondition(
    filter, urlFilter, ["main_frame", "sub_frame"], matchCase
  );

  let rule;

  if (!filter.blocking) {
    // The DNR makes no distinction between CSP rules and main_frame/sub_frame
    // rules. Ideally, we would give CSP rules a different priority therefore,
    // to ensure that a $csp exception filter would not accidentally allowlist
    // the whole website. Unfortunately, I don't think that's possible if we are
    // to also support the distinction between specific and generic rules.
    //   Luckily, we are adding an "allow" rule (not "allowAllRequest") here and
    // there is no such thing as a blocking filter which applies to the
    // $document (main_frame), so we don't have to worry about that. There is
    // such a thing as a $subdocument blocking filter though, which a $csp
    // exception filter should not usually affect.
    //   As a compromise in order to support both $csp and $genericblock, we
    // accept that $csp exception filters might wrongly prevent frame-blocking
    // filters from matching. If this compromise proves problematic, we might
    // need to reconsider this in the future.
    rule = {
      action: {
        type: "allow"
      },
      condition,
      priority: filter.contentType & contentTypes.GENERICBLOCK ?
                  GENERIC_PRIORITY : SPECIFIC_PRIORITY
    };
  }
  else {
    rule = {
      action: {
        type: "modifyHeaders",
        responseHeaders: [{
          header: "Content-Security-Policy",
          operation: "append",
          value: filter.csp
        }]
      },
      condition,
      priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY
    };
  }

  // Chromium doesn't consider main_frame requests to have initiated from their
  // URL, so the domains/excludedDomains rule conditions won't work as expected
  // for main_frame requests. This is a problem for $csp filters which also use
  // the $domain option. As a partial workaround, we generate a separate
  // urlFilter rule for each domain. But note, we can't support excludedDomains
  // ($csp=...$~domain=...) or urlFilter conditions (||...$csp=...,domain=...).
  // See https://bugs.chromium.org/p/chromium/issues/detail?id=1207326
  //
  // Note: Hopefully, this workaround won't be necessary for long, but if we
  // need it long-term, then perhaps we should generate one rule with a longer
  // regexFilter condition instead. But if we do that, we will need to be
  // careful not to hit the memory limit for regular expression rule conditions
  // and also to match subdomains correctly.
  if (rule.condition.excludedDomains)
    return [];
  if (rule.condition.domains) {
    if (condition.urlFilter)
      return [];

    let {domains} = condition;
    delete condition.domains;

    let rules = [];
    for (let domain of domains) {
      let domainRule = JSON.parse(JSON.stringify(rule));
      domainRule.condition.urlFilter = "||" + domain + "^";
      rules.push(domainRule);
    }

    return rules;
  }

  return [rule];
};

exports.generateBlockingRules = function(filter, urlFilter, matchCase) {
  let resourceTypes = getResourceTypes(filter.contentType);

  // We can't generate rules for filters which don't include any supported
  // resource types.
  if (resourceTypes && resourceTypes.length == 0)
    return [];

  let [condition, isGenericFilter] = getCondition(
    filter, urlFilter, resourceTypes, matchCase
  );

  return [{
    priority: isGenericFilter ? GENERIC_PRIORITY : SPECIFIC_PRIORITY,
    condition,
    action: {
      type: "block"
    }
  }];
};

exports.generateAllowingRules = function(filter, urlFilter, matchCase) {
  let rules = [];
  let {contentType} = filter;

  let genericBlock = contentType & contentTypes.GENERICBLOCK;

  if (contentType & contentTypes.DOCUMENT || genericBlock) {
    contentType &= ~contentTypes.SUBDOCUMENT;

    rules.push({
      priority: genericBlock ?
                  GENERIC_ALLOW_ALL_PRIORITY : SPECIFIC_ALLOW_ALL_PRIORITY,
      condition: getCondition(
        filter, urlFilter, ["main_frame", "sub_frame"], matchCase)[0],
      action: {
        type: "allowAllRequests"
      }
    });
  }

  let resourceTypes = getResourceTypes(contentType);
  if (!resourceTypes || resourceTypes.length) {
    rules.push({
      priority: genericBlock ? GENERIC_PRIORITY : SPECIFIC_PRIORITY,
      condition: getCondition(filter, urlFilter, resourceTypes, matchCase)[0],
      action: {
        type: "allow"
      }
    });
  }

  return rules;
};

function validateIsAsciiOnly(str) {
  // [0-127] range is considered to be allowed ASCII characters
  if (!/^[\x00-\x7F]*$/.test(str))
    throw new Error(`Invalid ASCII characters found in: "${str}"`);
}
exports.validateIsAsciiOnly = validateIsAsciiOnly;

function validateDomains(domains) {
  if (domains) {
    for (let domain of domains)
      validateIsAsciiOnly(domain);
  }
}

function validateCondition(condition) {
  if (condition.urlFilter)
    validateIsAsciiOnly(condition.urlFilter);
  if (condition.regexFilter)
    validateIsAsciiOnly(condition.regexFilter);

  validateDomains(condition.initiatorDomains);
  validateDomains(condition.requestDomains);

  // deprecated starting Chrome 101
  validateDomains(condition.domains);
  validateDomains(condition.excludedDomains);

  // starting Chrome 101
  validateDomains(condition.excludedInitiatorDomains);
  validateDomains(condition.excludedRequestDomains);
}

exports.validateRule = function(rule) {
  try {
    validateCondition(rule.condition);
    return rule;
  }
  catch (e) {
    return e;
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/downloader.js":
/*!********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/downloader.js ***!
  \********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_218107__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Downloads a set of URLs in regular time intervals.
 */

const {MILLIS_IN_DAY} = __nested_webpack_require_218107__(/*! ./time */ "./node_modules/adblockpluscore/lib/time.js");
const {isLocalhost} = __nested_webpack_require_218107__(/*! ./url */ "./node_modules/adblockpluscore/lib/url.js");

/**
 * A type of function that yields `{@link module:downloader.Downloadable}`
 * objects to a `{@link module:downloader.Downloader}`.
 *
 * **Note**: The implementation must yield a new
 * `{@link module:downloader.Downloadable}` instance on each call with
 * up-to-date values for properties like
 * `{@link module:downloader.Downloadable#lastCheck}`,
 * `{@link module:downloader.Downloadable#lastVersion}`,
 * `{@link module:downloader.Downloadable#downloadCount}`, and others. If a
 * value is outdated, it may result in unexpected behavior.
 *
 * @callback DataSource
 *
 * @yields {module:downloader.Downloadable}
 * @generator
 *
 * @see module:downloader.Downloader
 * @see module:downloader.Downloader#dataSource
 */

/**
 * Use a `Downloader` object to download a set of URLs at regular time
 * intervals.
 *
 * This class is used by `{@link module:synchronizer.synchronizer}` and
 * `{@link module:notifications.notifications}`.
 *
 * @example
 *
 * function* dataSource()
 * {
 *   yield new Downloadable("https://example.com/filters.txt");
 * }
 *
 * let initialDelay = 1000;
 * let checkInterval = 60000;
 *
 * let downloader = new Downloader(dataSource);
 * downloader.scheduleChecks(checkInterval, initialDelay);
 *
 * downloader.onDownloadStarted = function(downloadable)
 * {
 *   console.log(`Downloading ${downloadable.url} ...`);
 * }
 *
 * @package
 */
exports.Downloader = class Downloader {
  /**
   * Creates a new downloader instance.
   * @param {module:downloader~DataSource} dataSource
   *   A function that yields `{@link module:downloader.Downloadable}` objects
   *   on each {@link module:downloader.Downloader#scheduleChecks check}.
   */
  constructor(dataSource) {
    /**
     * Maximal time interval that the checks can be left out until the soft
     * expiration interval increases.
     * @type {number}
     */
    this.maxAbsenceInterval = 1 * MILLIS_IN_DAY;

    /**
     * Minimal time interval before retrying a download after an error.
     * @type {number}
     */
    this.minRetryInterval = 1 * MILLIS_IN_DAY;

    /**
     * Maximal allowed expiration interval; larger expiration
     * intervals will be corrected.
     * @type {number}
     */
    this.maxExpirationInterval = 14 * MILLIS_IN_DAY;

    /**
     * Maximal number of redirects before the download is considered as failed.
     * @type {number}
     */
    this.maxRedirects = 5;

    /**
     * Called whenever expiration intervals for an object need to be adapted.
     * @type {function?}
     */
    this.onExpirationChange = null;

    /**
     * Callback to be triggered whenever a download starts.
     * @type {function?}
     */
    this.onDownloadStarted = null;

    /**
     * Callback to be triggered whenever a download finishes successfully.
     *
     * The callback can return an error code to indicate that the data is
     * wrong.
     *
     * @type {function?}
     */
    this.onDownloadSuccess = null;

    /**
     * Callback to be triggered whenever a download fails.
     * @type {function?}
     */
    this.onDownloadError = null;

    /**
     * A function that yields `{@link module:downloader.Downloadable}` objects
     * on each {@link module:downloader.Downloader#scheduleChecks check}.
     * @type {module:downloader~DataSource}
     */
    this.dataSource = dataSource;

    /**
     * Set containing the URLs of objects currently being downloaded.
     * @type {Set.<string>}
     */
    this._downloading = new Set();

    /**
     * Store the timeout ID for scheduled checks.
     * @type {number}
     */
    this._timeout = 0;
  }

  /**
   * Schedules checks at regular time intervals.
   *
   * @param {number} interval The interval between checks in milliseconds.
   * @param {number} delay The delay before the initial check in milliseconds.
   */
  scheduleChecks(interval, delay) {
    // clear previous timeouts if called too many times
    this.unscheduleChecks();

    let check = () => {
      try {
        this._doCheck();
      }
      finally {
        // Schedule the next check only after the callback has finished with
        // the current check.
        this._timeout =
          setTimeout(check, interval); // eslint-disable-line no-undef
      }
    };

    // Note: test/_common.js overrides setTimeout() for the tests; if this
    // global function is used anywhere else, it may give incorrect results.
    // This is why we disable ESLint's no-undef rule locally.
    // https://gitlab.com/eyeo/adblockplus/abc/adblockpluscore/issues/43
    this._timeout = setTimeout(check, delay); // eslint-disable-line no-undef
  }

  /**
   * Clear previously scheduled checks, if any.
   */
  unscheduleChecks() {
    if (this._timeout) {
      clearTimeout(this._timeout); // eslint-disable-line no-undef
      this._timeout = 0;
    }
  }

  /**
   * Checks whether anything needs downloading.
   */
  _doCheck() {
    let now = Date.now();
    for (let downloadable of this.dataSource()) {
      if (downloadable.lastCheck &&
          now - downloadable.lastCheck > this.maxAbsenceInterval) {
        // No checks for a long time interval - user must have been offline,
        // e.g.  during a weekend. Increase soft expiration to prevent load
        // peaks on the server.
        downloadable.softExpiration += now - downloadable.lastCheck;
      }
      downloadable.lastCheck = now;

      // Sanity check: do expiration times make sense? Make sure people changing
      // system clock don't get stuck with outdated subscriptions.
      if (downloadable.hardExpiration - now > this.maxExpirationInterval)
        downloadable.hardExpiration = now + this.maxExpirationInterval;
      if (downloadable.softExpiration - now > this.maxExpirationInterval)
        downloadable.softExpiration = now + this.maxExpirationInterval;

      // Notify the caller about changes to expiration parameters
      if (this.onExpirationChange)
        this.onExpirationChange(downloadable);

      // Does that object need downloading?
      if (downloadable.softExpiration > now &&
          downloadable.hardExpiration > now)
        continue;

      // Do not retry downloads too often
      if (downloadable.lastError &&
          now - downloadable.lastError < this.minRetryInterval)
        continue;

      this._download(downloadable, 0);
    }
  }

  /**
   * Checks whether an address is currently being downloaded.
   * @param {string} url
   * @returns {boolean}
   */
  isDownloading(url) {
    return this._downloading.has(url);
  }

  /**
   * Starts downloading for an object.
   * @param {Downloadable} downloadable
   */
  download(downloadable) {
    this._download(downloadable, 0);
  }

  /**
   * Generates the real download URL for an object by appending various
   * parameters.
   * @param {Downloadable} downloadable
   * @returns {string}
   */
  getDownloadUrl(downloadable) {
    const {addonName, addonVersion, application, applicationVersion,
           platform, platformVersion, manifestVersion} = __nested_webpack_require_218107__(/*! info */ "./sdk/api/info.js");

    let url = downloadable.redirectURL || downloadable.url;
    if (url.includes("?"))
      url += "&";
    else
      url += "?";

    // We limit the download count to 4+ to keep the request anonymized.
    let {downloadCount, disabled} = downloadable;
    if (downloadCount > 4)
      downloadCount = "4+";
    if (typeof disabled == "undefined")
      disabled = false;

    url += "addonName=" + encodeURIComponent(addonName) +
           "&addonVersion=" + encodeURIComponent(addonVersion) +
           "&application=" + encodeURIComponent(application) +
           "&applicationVersion=" + encodeURIComponent(applicationVersion) +
           "&platform=" + encodeURIComponent(platform) +
           "&platformVersion=" + encodeURIComponent(platformVersion) +
           "&lastVersion=" + encodeURIComponent(downloadable.lastVersion) +
           "&downloadCount=" + encodeURIComponent(downloadCount) +
           "&disabled=" + String(disabled) +
           "&manifestVersion=" + encodeURIComponent(manifestVersion);

    if (downloadable.firstVersion && !downloadable.redirectURL)
      url += "&firstVersion=" + encodeURIComponent(downloadable.firstVersion);

    return url;
  }

  _download(downloadable, redirects) {
    if (this.isDownloading(downloadable.url))
      return;

    let downloadUrl = this.getDownloadUrl(downloadable);
    let responseStatus = 0;

    let errorCallback = error => {
      console.warn("Adblock Plus: Downloading URL " + downloadable.url +
                   " failed (" + error + ")\n" +
                   "Download address: " + downloadUrl + "\n" +
                   "Server response: " + responseStatus);

      if (this.onDownloadError) {
        // Allow one extra redirect if the error handler gives us a redirect URL
        let redirectCallback = null;
        if (redirects <= this.maxRedirects) {
          redirectCallback = url => {
            downloadable.redirectURL = url;
            this._download(downloadable, redirects + 1);
          };
        }

        this.onDownloadError(
          downloadable, downloadUrl, error, responseStatus, redirectCallback
        );
      }
    };

    if (!Downloader.isValidURL(downloadUrl)) {
      errorCallback("synchronize_invalid_url");
      return;
    }

    let requestURL = new URL(downloadUrl);

    let initObj = {
      cache: "no-store",
      credentials: "omit",
      referrer: "no-referrer",
      method: downloadable.method
    };

    let handleError = () => {
      this._downloading.delete(downloadable.url);
      errorCallback("synchronize_connection_error");
    };

    let handleResponse = response => {
      this._downloading.delete(downloadable.url);

      // If the Response.url property is available [1], disallow redirection
      // from HTTPS to any other protocol.
      // [1]: https://developer.mozilla.org/en-US/docs/Web/API/Response/url#Browser_compatibility
      if (typeof response.url == "string" && requestURL.protocol == "https:" &&
          new URL(response.url).protocol != requestURL.protocol) {
        errorCallback("synchronize_connection_error");
        return;
      }

      responseStatus = response.status;

      if (responseStatus != 200) {
        errorCallback("synchronize_connection_error");
        return;
      }

      // We need to keep updated the subscription version even via HEAD.
      if (downloadable.method === "HEAD") {
        // However, as we don't know if the server would respond with such
        // detail, we need to be sure there is such `Date` or `date` field.
        let date = response.headers.get("Date") || response.headers.get("date");
        if (date) {
          // if that's the case, we want it to be formatted as YYYYMMDDHHMM.
          downloadable.lastVersion =
            new Date(date).toISOString().replace(/\D/g, "").slice(0, 12);
        }
      }

      if (!downloadable.disabled)
        downloadable.downloadCount++;

      response.text().then(
        responseText => {
          this.onDownloadSuccess(
            downloadable, responseText, errorCallback, url => {
              if (redirects >= this.maxRedirects) {
                errorCallback("synchronize_connection_error");
                return;
              }

              downloadable.redirectURL = url;
              this._download(downloadable, redirects + 1);
            }
          );
        },
        () => {
          errorCallback("synchronize_connection_error");
        }
      );
    };

    fetch(requestURL.href, initObj).then(handleResponse, handleError);

    this._downloading.add(downloadable.url);

    if (this.onDownloadStarted)
      this.onDownloadStarted(downloadable);
  }

  /**
   * Produces a soft and a hard expiration time for a given supplied
   * expiration interval.
   *
   * Downloadable things, like Subscription, have a certain time after
   * which they expire and you need to download a new, updated version.
   *
   * To spread the load on our download servers, we'd rather that all
   * users not download updates at exactly the same time, so on
   * download we calculate a soft expiration time, which is randomly
   * chosen between 80% and 120% of the original time. When we pass
   * the soft expiration, we start trying to download updates.
   *
   * However, there are other events that could cause downloads to all
   * happen at the same time. If many people leave their computer off
   * over the weekend and sign in at the beginning of business hours
   * on Monday, we could still see a spike in downloads at the same
   * time. To combat this, the soft expiration time may be delayed to
   * accomodate these periods of inactivity.
   *
   * There are limits to how far we want to delay our download due to
   * inactivity. This is why we also calculate a hard expiration time,
   * which is 200% of the original time. When we pass the hard
   * expiration, we should try to download an update whether there was
   * inactivity or not.
   *
   * This function must be called to calculate the new expiration
   * times as soon as a new version is downloaded.
   *
   * @param {number} interval how often in milliseconds the
   * downloadable should be updated
   * @returns {Array.<number>} soft and hard expiration times in
   * milliseconds since the Unix epoch
   */
  processExpirationInterval(interval) {
    interval = Math.min(Math.max(interval, 0), this.maxExpirationInterval);
    let soft = Math.round(interval * (Math.random() * 0.4 + 0.8));
    let hard = interval * 2;
    let now = Date.now();
    return [now + soft, now + hard];
  }
};

/**
 * Checks whether a URL is a valid download URL.
 *
 * For a URL to be a valid download URL, its scheme must be `https` or `data`.
 * If the host component of the URL is `localhost`, `127.0.0.1`, or `[::1]`,
 * however, but its scheme is not `https` or `data`, the URL is still
 * considered to be a valid download URL.
 *
 * `https://example.com/`, `data:,Hello%2C%20World!`, and
 * `http://127.0.0.1/example.txt` are all examples of valid download URLs.
 *
 * @param {string} url The URL.
 *
 * @returns {boolean} Whether the URL is a valid download URL.
 *
 * @package
 */
exports.Downloader.isValidURL = function isValidURL(url) {
  try {
    url = new URL(url);
  }
  catch (error) {
    return false;
  }

  if (!["https:", "data:"].includes(url.protocol) &&
      !isLocalhost(url.hostname))
    return false;

  return true;
};

/**
 * A `Downloadable` object represents a downloadable resource.
 * @package
 */
exports.Downloadable = class Downloadable {
  /**
   * Creates an object that can be downloaded by the downloader.
   * @param {string} url  URL that has to be requested for the object
   */
  constructor(url) {
    /**
     * URL that the download was redirected to if any.
     * @type {string?}
     */
    this.redirectURL = null;

    /**
     * Time of last download error or 0 if the last download was successful.
     * @type {number}
     */
    this.lastError = 0;

    /**
     * Time of last check whether the object needs downloading.
     * @type {number}
     */
    this.lastCheck = 0;

    /**
     * Object version corresponding to the last successful download.
     * @type {number}
     */
    this.lastVersion = 0;

    /**
     * A string indicating the version of the first ever downloaded resource,
     * in `YYYY[MM[DD]][-E]` format or just `"0"` or `"0-E"`.
     *
     * Note that unlike `{@link module:downloader.Downloadable#lastVersion}`
     * this property is related to analytics and its value is common across all
     * downloadable resources.
     *
     * If `{@link module:downloader.Downloadable#url}` is not a trusted URL,
     * the value of this property should be set to `null`.
     *
     * @see module:analytics~Analytics#getFirstVersion
     * @see module:analytics~Analytics#isTrusted
     *
     * @type {?string}
     *
     * @package
     */
    this.firstVersion = null;

    /**
     * Soft expiration time in milliseconds since the Unix epoch. This
     * will increase if no checks are performed for a while.
     *
     * Updates should be downloaded if `softExpiration` or
     * `{@link module:downloader.Downloadable#hardExpiration}` are in the past.
     * @type {number}
     */
    this.softExpiration = 0;

    /**
     * Hard expiration time in milliseconds since the Unix epoch. This
     * is fixed.
     *
     * Updates should be downloaded if
     * `{@link module:downloader.Downloadable#softExpiration}` or
     * `hardExpiration` are in the past.
     * @type {number}
     */
    this.hardExpiration = 0;

    /**
     * Number indicating how often the object was downloaded.
     * @type {number}
     */
    this.downloadCount = 0;

    /**
     * Request method to use, which is either "GET" or "HEAD".
     * @type {string}
     */
    this.method = "GET";

    /**
     * URL that has to be requested for the object.
     * @type {string}
     */
    this.url = url;
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/elemHide.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/elemHide.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_236458__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Element hiding implementation.
 */

const {domainSuffixes} = __nested_webpack_require_236458__(/*! ./url */ "./node_modules/adblockpluscore/lib/url.js");
const {FiltersByDomain, FilterMap} = __nested_webpack_require_236458__(/*! ./filtersByDomain */ "./node_modules/adblockpluscore/lib/filtersByDomain.js");
const {Cache} = __nested_webpack_require_236458__(/*! ./caching */ "./node_modules/adblockpluscore/lib/caching.js");
const {ElemHideExceptions} = __nested_webpack_require_236458__(/*! ./elemHideExceptions */ "./node_modules/adblockpluscore/lib/elemHideExceptions.js");

class ElemHide {
  /**
   * @param {ElemHideExceptions} elemHideExceptions The associated element
   *   hiding exceptions.
   */
  constructor(elemHideExceptions) {
    if (!(elemHideExceptions instanceof ElemHideExceptions))
      throw new Error("elemHideExceptions must be an ElemHideExceptions");

    /** @type {ElemHideExceptions} */
    this.elemHideExceptions = elemHideExceptions;

    /**
     * Lookup table, active flag, by filter by domain.
     *
     * (Only contains filters that aren't unconditionally matched for all
     * domains.)
     *
     * @type {FiltersByDomain}
     *
     * @private
     */
    this._filtersByDomain = new FiltersByDomain();

    /**
     * Lookup table, filter by selector.
     *
     * (Only used for selectors that are unconditionally matched for all
     * domains.)
     *
     * @type {Map.<string, Filter>}
     *
     * @private
     */
    this._filterBySelector = new Map();

    /**
     * This array caches the keys of
     * `{@link module:elemHide~ElemHide#_filterBySelector _filterBySelector}`
     * (selectors which unconditionally apply on all domains).
     *
     * It will be `null` if the cache needs to be rebuilt.
     *
     * @type {?Array.<string>}
     *
     * @private
     */
    this._unconditionalSelectors = null;

    /**
     * The default style sheet that applies on all domains.
     *
     * This is based on the value of
     * `{@link module:elemHide~ElemHide#_unconditionalSelectors
     *         _unconditionalSelectors}`.
     *
     * @type {?string}
     *
     * @private
     */
    this._defaultStyleSheet = null;

    /**
     * The common style sheet that applies on all unknown domains.
     *
     * This is a concatenation of the default style sheet and an additional
     * style sheet based on selectors from all generic filters that are not in
     * the `{@link module:elemHide~ElemHide#_unconditionalSelectors
     *             _unconditionalSelectors}` list.
     *
     * @type {?string}
     *
     * @private
     */
    this._commonStyleSheet = null;

    /**
     * Cache of generated domain-specific style sheets.
     *
     * This contains entries for only known domains. If a domain is unknown, it
     * gets `{@link module:elemHide~ElemHide#_commonStyleSheet
     *              _commonStyleSheet}`.
     *
     * @type {Cache.<string, string>}
     *
     * @private
     */
    this._styleSheetCache = new Cache(100);

    /**
     * Set containing known element hiding filters
     * @type {Set.<module:filterClasses.ElemHideFilter>}
     * @private
     */
    this._filters = new Set();

    /**
     * All domains known to occur in exceptions
     * @type {Set.<string>}
     * @private
     */
    this._exceptionDomains = new Set();

    this.elemHideExceptions.on("added", this._onExceptionAdded.bind(this));
  }

  /**
   * Removes all known element hiding filters.
   */
  clear() {
    this._commonStyleSheet = null;

    for (let collection of [this._styleSheetCache, this._filtersByDomain,
                            this._filterBySelector, this._filters,
                            this._exceptionDomains])
      collection.clear();

    this._unconditionalSelectors = null;
    this._defaultStyleSheet = null;
  }

  /**
   * Add a new element hiding filter.
   * @param {module:filterClasses.ElemHideFilter} filter
   */
  add(filter) {
    if (this._filters.has(filter))
      return;

    this._styleSheetCache.clear();
    this._commonStyleSheet = null;

    let {domains, selector} = filter;

    if (!(domains || this.elemHideExceptions.hasExceptions(selector))) {
      // The new filter's selector is unconditionally applied to all domains
      this._filterBySelector.set(selector, filter);
      this._unconditionalSelectors = null;
      this._defaultStyleSheet = null;
    }
    else {
      // The new filter's selector only applies to some domains
      this._filtersByDomain.add(filter, domains);
    }

    this._filters.add(filter);
  }

  /**
   * Removes an existing element hiding filter.
   * @param {module:filterClasses.ElemHideFilter} filter
   */
  remove(filter) {
    if (!this._filters.has(filter))
      return;

    this._styleSheetCache.clear();
    this._commonStyleSheet = null;

    let {selector} = filter;

    // Unconditially applied element hiding filters
    if (this._filterBySelector.get(selector) == filter) {
      this._filterBySelector.delete(selector);
      this._unconditionalSelectors = null;
      this._defaultStyleSheet = null;
    }
    // Conditionally applied element hiding filters
    else {
      this._filtersByDomain.remove(filter);
    }

    this._filters.delete(filter);
  }

  /**
   * Checks whether an element hiding filter exists.
   * @param {module:filterClasses.ElemHideFilter} filter
   * @returns {boolean}
   */
  has(filter) {
    return this._filters.has(filter);
  }

  /**
   * @typedef {Object} ElemHideStyleSheet
   * @property {string} code CSS code.
   * @property {?Array.<string>} selectors List of selectors.
   * @property {?Array.<string>} exceptions List of exceptions.
   */

  /**
   * Returns a style sheet for a given domain based on the current set of
   * filters.
   *
   * @param {string} domain The domain.
   * @param {boolean} [specificOnly=false] Whether selectors from generic
   *   filters should be included.
   * @param {boolean} [includeSelectors=false] Whether the return value should
   *   include a separate list of selectors.
   * @param {boolean} [includeExceptions=false] Whether the return value should
   *   include a separate list of exceptions.
   *
   * @returns {module:elemHide~ElemHideStyleSheet} An object containing the CSS
   *   code and the list of selectors.
   */
  getStyleSheet(domain, specificOnly = false, includeSelectors = false,
                includeExceptions = false) {
    let code = null;
    let selectors = null;
    let exceptions = null;

    if (specificOnly) {
      if (includeExceptions) {
        let selectorsAndExceptions =
          this._getConditionalSelectorsWithExceptions(domain, true);

        selectors = selectorsAndExceptions.selectors;
        exceptions = selectorsAndExceptions.exceptions;
      }
      else {
        selectors = this._getConditionalSelectors(domain, true);
      }

      code = createStyleSheet(selectors);
    }
    else {
      let knownSuffix = this._getKnownSuffix(domain);

      if (includeSelectors || includeExceptions) {
        let selectorsAndExceptions =
          this._getConditionalSelectorsWithExceptions(knownSuffix, false);

        selectors = selectorsAndExceptions.selectors;
        exceptions = selectorsAndExceptions.exceptions;
        code = knownSuffix == "" ? this._getCommonStyleSheet() :
          this._getDefaultStyleSheet() + createStyleSheet(selectors);

        selectors = this._getUnconditionalSelectors().concat(selectors);
      }
      else {
        code = knownSuffix == "" ? this._getCommonStyleSheet() :
          this._getDefaultStyleSheet() +
                 this._getDomainSpecificStyleSheet(knownSuffix);
      }
    }

    return {
      code,
      selectors: includeSelectors ? selectors : null,
      exceptions: includeExceptions ? exceptions : null
    };
  }

  /**
   * Returns a style sheet for a given domain based on the current set of
   * filters.
   *
   * @param {string} domain The domain.
   * @param {boolean} [specificOnly=false] Whether selectors from generic
   *   filters should be included.
   * @param {boolean} [includeSelectors=false] Whether the return value should
   *   include a separate list of selectors.
   * @param {boolean} [includeExceptions=false] Whether the return value should
   *   include a separate list of exceptions.
   *
   * @returns {module:elemHide~ElemHideStyleSheet} An object containing the CSS
   *   code and the list of selectors.
   *
   * @deprecated Use
   *   <code>{@link module:elemHide~ElemHide#getStyleSheet}</code> instead.
   * @see module:elemHide~ElemHide#getStyleSheet
   */
  generateStyleSheetForDomain(domain, specificOnly = false,
                              includeSelectors = false,
                              includeExceptions = false) {
    return this.getStyleSheet(
      domain, specificOnly, includeSelectors, includeExceptions
    );
  }

  /**
   * Returns the suffix of the given domain that is known.
   *
   * If no suffix is known, an empty string is returned.
   *
   * @param {?string} domain
   *
   * @returns {string}
   *
   * @private
   */
  _getKnownSuffix(domain) {
    for (let suffix of domainSuffixes(domain)) {
      if (this._filtersByDomain.has(suffix) ||
          this._exceptionDomains.has(suffix))
        return suffix;
    }

    return "";
  }

  /**
   * Returns a list of selectors that apply on each website unconditionally.
   * @returns {string[]}
   * @private
   */
  _getUnconditionalSelectors() {
    if (!this._unconditionalSelectors)
      this._unconditionalSelectors = [...this._filterBySelector.keys()];

    return this._unconditionalSelectors;
  }

  /**
   * Returns the list of selectors that apply on a given domain from the subset
   * of filters that do not apply unconditionally on all domains.
   *
   * @param {string} domain The domain.
   * @param {boolean} specificOnly Whether selectors from generic filters should
   *   be included.
   *
   * @returns {Array.<string>} The list of selectors.
   *
   * @private
   */
  _getConditionalSelectors(domain, specificOnly) {
    let selectors = [];

    let excluded = new Set();

    for (let currentDomain of domainSuffixes(domain, !specificOnly)) {
      let map = this._filtersByDomain.get(currentDomain);
      if (map) {
        for (let [filter, include] of (map instanceof FilterMap ?
          map.entries() : [[map, true]])) {
          if (!include) {
            excluded.add(filter);
          }
          else {
            let {selector} = filter;
            if ((excluded.size == 0 || !excluded.has(filter)) &&
                !this.elemHideExceptions.getException(selector, domain))
              selectors.push(selector);
          }
        }
      }
    }

    return selectors;
  }

  /**
   * Returns the list of selectors and the list of exceptions that apply on a
   * given domain from the subset of filters that do not apply unconditionally
   * on all domains.
   *
   * @param {string} domain The domain.
   * @param {boolean} specificOnly Whether selectors from generic filters should
   *   be included.
   *
   * @returns {{selectors: Array.<string>,
   *            exceptions: Array.<module:filterClasses.ElemHideException>}}
   *   An object containing the lists of selectors and exceptions.
   *
   * @private
   */
  _getConditionalSelectorsWithExceptions(domain, specificOnly) {
    let selectors = [];
    let exceptions = [];

    let excluded = new Set();

    for (let currentDomain of domainSuffixes(domain, !specificOnly)) {
      let map = this._filtersByDomain.get(currentDomain);
      if (map) {
        for (let [filter, include] of (map instanceof FilterMap ?
          map.entries() : [[map, true]])) {
          if (!include) {
            excluded.add(filter);
          }
          else if (excluded.size == 0 || !excluded.has(filter)) {
            let {selector} = filter;
            let exception =
                this.elemHideExceptions.getException(selector, domain);

            if (exception)
              exceptions.push(exception);
            else
              selectors.push(selector);
          }
        }
      }
    }

    return {selectors, exceptions};
  }

  /**
   * Returns the default style sheet that applies on all domains.
   * @returns {string}
   * @private
   */
  _getDefaultStyleSheet() {
    if (!this._defaultStyleSheet) {
      this._defaultStyleSheet =
        createStyleSheet(this._getUnconditionalSelectors());
    }

    return this._defaultStyleSheet;
  }

  /**
   * Returns the common style sheet that applies on all unknown domains.
   * @returns {string}
   * @private
   */
  _getCommonStyleSheet() {
    if (!this._commonStyleSheet) {
      this._commonStyleSheet =
        this._getDefaultStyleSheet() +
        createStyleSheet(this._getConditionalSelectors("", false));
    }

    return this._commonStyleSheet;
  }

  /**
   * Returns the domain-specific style sheet that applies on a given domain.
   * @param {string} domain
   * @returns {string}
   * @private
   */
  _getDomainSpecificStyleSheet(domain) {
    let styleSheet = this._styleSheetCache.get(domain);

    if (typeof styleSheet == "undefined") {
      styleSheet =
        createStyleSheet(this._getConditionalSelectors(domain, false));
      this._styleSheetCache.set(domain, styleSheet);
    }

    return styleSheet;
  }

  _onExceptionAdded(exception) {
    let {domains, selector} = exception;

    this._styleSheetCache.clear();
    this._commonStyleSheet = null;

    if (domains) {
      for (let domain of domains.keys()) {
        // Note: Once an exception domain is known it never becomes unknown,
        // even when all the exceptions containing that domain are removed.
        // This is a best-case optimization.
        if (domain != "")
          this._exceptionDomains.add(domain);
      }
    }

    // If this is the first exception for a previously unconditionally applied
    // element hiding selector we need to take care to update the lookups.
    let unconditionalFilterForSelector = this._filterBySelector.get(selector);
    if (unconditionalFilterForSelector) {
      this._filtersByDomain.add(unconditionalFilterForSelector);
      this._filterBySelector.delete(selector);
      this._unconditionalSelectors = null;
      this._defaultStyleSheet = null;
    }
  }
}

/**
 * Container for element hiding filters.
 */
exports.ElemHide = ElemHide;

/**
 * Yields rules from a style sheet returned by
 * `{@link module:elemHide.createStyleSheet createStyleSheet()}`.
 *
 * @param {string} styleSheet A style sheet returned by
 *   `{@link module:elemHide.createStyleSheet createStyleSheet()}`. If the
 *   given style sheet is *not* a value previously returned by a call to
 *   `{@link module:elemHide.createStyleSheet createStyleSheet()}`, the
 *   behavior is undefined.
 *
 * @generator
 * @yields {string} A rule from the given style sheet.
 */
exports.rulesFromStyleSheet = function* rulesFromStyleSheet(styleSheet) {
  let startIndex = 0;
  while (startIndex < styleSheet.length) {
    let ruleTerminatorIndex = styleSheet.indexOf("\n", startIndex);
    yield styleSheet.substring(startIndex, ruleTerminatorIndex);
    startIndex = ruleTerminatorIndex + 1;
  }
};

/**
 * Escapes curly braces to prevent CSS rule injection.
 *
 * @param {string} selector
 *
 * @returns {string}
 */
function escapeSelector(selector) {
  return selector.replace(/[{}]/g, c => `\\${c.charCodeAt().toString(16)} `);
}

/**
 * Creates an element hiding CSS rule for a given list of selectors.
 *
 * @param {string} selector The CSS selector for the rule.
 * @param {string} [declarationBlock] Optional CSS code to use as the
 *   declaration block. By default, the code `{display: none !important;}` is
 *   used. If specified, the value is injected as-is into the rule.
 *
 * @returns {string} A CSS rule.
 */
function createRule(
  selector,
  declarationBlock = "{display: none !important;}"
) {
  return `${escapeSelector(selector)} ${declarationBlock}\n`;
}

let createStyleSheet =
/**
 * Creates an element hiding CSS style sheet from a given list of selectors.
 *
 * @param {Array.<string>} selectors The list of selectors.
 * @param {string} [declarationBlock] Optional CSS code to use as the
 *   declaration block. By default, the code `{display: none !important;}` is
 *   used. If specified, the value is injected as-is into the style sheet.
 *
 * @returns {string} A CSS style sheet.
 */
exports.createStyleSheet = function createStyleSheet(selectors,
                                                     declarationBlock) {
  let styleSheet = "";

  for (let selector of selectors)
    styleSheet += createRule(selector, declarationBlock);

  return styleSheet;
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/elemHideEmulation.js":
/*!***************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/elemHideEmulation.js ***!
  \***************************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_254208__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



const {ElemHideExceptions} = __nested_webpack_require_254208__(/*! ./elemHideExceptions */ "./node_modules/adblockpluscore/lib/elemHideExceptions.js");

/**
 * @file Element hiding emulation implementation.
 */

class ElemHideEmulation extends Set {
  /**
   * Construct an ElemHideEmulation object
   * @param {ElemHideExceptions} elemHideExceptions The associated element
   *  hiding exceptions.
   */
  constructor(elemHideExceptions) {
    super();
    if (!(elemHideExceptions instanceof ElemHideExceptions))
      throw new Error("elemHideExceptions must be an ElemHideExceptions");

    /** @type {ElemHideExceptions} */
    this.elemHideExceptions = elemHideExceptions;
  }

  /**
   * Removes an existing element hiding emulation filter.
   * @param {module:filterClasses.ElemHideEmulationFilter} filter
   *
   * @deprecated Use
   *   <code>ElemHideEmulation#delete</code>
   *   instead.
   */
  remove(filter) {
    this.delete(filter);
  }

  /**
   * Returns a list of all element hiding emulation filters active on the given
   * domain.
   * @param {string} domain The domain.
   * @returns {Array.<module:filterClasses.ElemHideEmulationFilter>} A list of
   *   element hiding emulation filters.
   */
  getFilters(domain) {
    let result = [];

    for (let filter of this) {
      if (filter.isActiveOnDomain(domain) &&
          !this.elemHideExceptions.getException(filter.selector, domain))
        result.push(filter);
    }

    return result;
  }

  /**
   * Returns a list of all element hiding emulation filters active on the given
   * domain.
   * @param {string} domain The domain.
   * @returns {Array.<module:filterClasses.ElemHideEmulationFilter>} A list of
   *   element hiding emulation filters.
   *
   * @deprecated Use
   *   <code>{@link
   *          module:elemHideEmulation~ElemHideEmulation#getFilters}</code>
   *   instead.
   * @see module:elemHideEmulation~ElemHideEmulation#getFilters
   */
  getRulesForDomain(domain) {
    return this.getFilters(domain);
  }
}

/**
 * Container for element hiding emulation filters.
 */
exports.ElemHideEmulation = ElemHideEmulation;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/elemHideExceptions.js":
/*!****************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/elemHideExceptions.js ***!
  \****************************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_257402__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Element hiding exceptions implementation.
 */

const {EventEmitter} = __nested_webpack_require_257402__(/*! ./events */ "./node_modules/adblockpluscore/lib/events.js");

class ElemHideExceptions extends EventEmitter {
  /**
   * @hideconstructor
   */
  constructor() {
    super();

    /**
     * Lookup table, lists of element hiding exceptions by selector
     * @type {Map.<string, Set.<module:filterClasses.ElemHideException>>}
     * @private
     */
    this._exceptionsBySelector = new Map();

    /**
     * Set containing known element hiding exceptions
     * @type {Set.<module:filterClasses.ElemHideException>}
     * @private
     */
    this._exceptions = new Set();
  }

  /**
   * Removes all known element hiding exceptions.
   */
  clear() {
    this._exceptionsBySelector.clear();
    this._exceptions.clear();
  }

  /**
   * Adds a new element hiding exception.
   * @param {module:filterClasses.ElemHideException} exception
   */
  add(exception) {
    if (this._exceptions.has(exception))
      return;

    let {selector} = exception;
    let set = this._exceptionsBySelector.get(selector);
    if (set)
      set.add(exception);
    else
      this._exceptionsBySelector.set(selector, new Set([exception]));

    this._exceptions.add(exception);

    this.emit("added", exception);
  }

  /**
   * Removes an existing element hiding exception.
   * @param {module:filterClasses.ElemHideException} exception
   */
  remove(exception) {
    if (!this._exceptions.has(exception))
      return;

    let {selector} = exception;
    let set = this._exceptionsBySelector.get(selector);
    set.delete(exception);
    if (set.size == 0)
      this._exceptionsBySelector.delete(selector);

    this._exceptions.delete(exception);

    this.emit("removed", exception);
  }

  /**
   * Checks whether an element hiding exception exists.
   * @param {module:filterClasses.ElemHideException} exception
   * @returns {boolean}
   */
  has(exception) {
    return this._exceptions.has(exception);
  }

  /**
   * Checks whether any exception rules are registered for a selector.
   * @param {string} selector
   * @returns {boolean}
   */
  hasExceptions(selector) {
    return this._exceptionsBySelector.has(selector);
  }

  /**
   * Checks whether an exception rule is registered for a selector on a
   * particular domain.
   * @param {string} selector
   * @param {?string} [domain]
   * @returns {?module:filterClasses.ElemHideException}
   */
  getException(selector, domain) {
    let exceptions = this._exceptionsBySelector.get(selector);
    if (exceptions) {
      for (let exception of exceptions) {
        if (exception.isActiveOnDomain(domain))
          return exception;
      }
    }

    return null;
  }
}

/**
 * Container for element hiding exceptions.
 */
exports.ElemHideExceptions = ElemHideExceptions;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/events.js":
/*!****************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/events.js ***!
  \****************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * Registers and emits named events.
 */
exports.EventEmitter = class EventEmitter {
  constructor() {
    this._listeners = new Map();
  }

  /**
   * Adds a listener for the specified event name.
   *
   * @param {string}   name
   * @param {function} listener
   */
  on(name, listener) {
    let listeners = this._listeners.get(name);
    if (listeners)
      listeners.push(listener);
    else
      this._listeners.set(name, [listener]);
  }

  /**
   * Removes a listener for the specified event name.
   *
   * @param {string}   name
   * @param {function} listener
   */
  off(name, listener) {
    let listeners = this._listeners.get(name);
    if (listeners) {
      if (listeners.length > 1) {
        let idx = listeners.indexOf(listener);
        if (idx != -1)
          listeners.splice(idx, 1);
      }
      else if (listeners[0] === listener) {
        // We must use strict equality above for compatibility with
        // Array.prototype.indexOf
        this._listeners.delete(name);
      }
    }
  }

  /**
   * Returns a copy of the array of listeners for the specified event.
   *
   * @param {string} name
   *
   * @returns {Array.<function>}
   */
  listeners(name) {
    let listeners = this._listeners.size > 0 ? this._listeners.get(name) : null;
    return listeners ? listeners.slice() : [];
  }

  /**
   * Checks whether there are any listeners for the specified event.
   *
   * @param {string} [name] The name of the event. If omitted, checks whether
   *   there are any listeners for any event.
   *
   * @returns {boolean}
   */
  hasListeners(name) {
    return this._listeners.size > 0 &&
           (typeof name == "undefined" || this._listeners.has(name));
  }

  /**
   * Calls all previously added listeners for the given event name.
   *
   * @param {string} name
   * @param {...*}   [args]
   */
  emit(name, ...args) {
    let listeners = this._listeners.size > 0 ? this._listeners.get(name) : null;
    if (listeners) {
      for (let listener of listeners.slice())
        listener(...args);
    }
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/features.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/features.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * Feature flags for the filterEngine.
 *
 * @type {Object}
 *
 * @public
 */
exports.Features = {
  // Default features: Manifest v2.
  DEFAULT: 0,
  // We have DeclarativeNetRequest
  DNR: 1
};



/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filterClasses.js":
/*!***********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filterClasses.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_265611__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Definition of Filter class and its subclasses.
 */

const {
  contentTypes, RESOURCE_TYPES, CONTEXT_TYPES
} = __nested_webpack_require_265611__(/*! ./contentTypes */ "./node_modules/adblockpluscore/lib/contentTypes.js");
const {CONTENT_FILTER} = __nested_webpack_require_265611__(/*! ./filters */ "./node_modules/adblockpluscore/lib/filters/index.js");
const {Pattern} = __nested_webpack_require_265611__(/*! ./patterns */ "./node_modules/adblockpluscore/lib/patterns.js");
const {parseDomains, domainSuffixes} = __nested_webpack_require_265611__(/*! ./url */ "./node_modules/adblockpluscore/lib/url.js");
const {parse, FilterParsingError} = __nested_webpack_require_265611__(/*! ./filters */ "./node_modules/adblockpluscore/lib/filters/index.js");

const {resources} = __nested_webpack_require_265611__(/*! ../data/resources.js */ "./node_modules/adblockpluscore/data/resources.js");

const MIN_GENERIC_CONTENT_FILTER_BODY_LENGTH = 3;

/** The filter state
 * @type {module:filterState.FilterState}
 */
let filterState = null;

/**
 * @typedef {Object} HttpHeader
 * @property {string} name
 * @property {?string} value
 */

/**
 * Map of internal resources for URL rewriting.
 * @type {Map.<string,string>}
 */
let resourceMap = new Map(
  Object.keys(resources).map(key => [key, resources[key]])
);

let isActiveFilter =
/**
 * Checks whether the given filter is an active filter.
 *
 * Filters of type `blocking`, `allowing`, `elemhide`, `elemhideexception`,
 * `elemhideemulation`, and `snippet` are considered active; filters of type
 * `invalid` and `comment` are not considered active.
 *
 * @param {?Filter} filter The filter.
 *
 * @returns {boolean} Whether the filter is active.
 */
exports.isActiveFilter = function isActiveFilter(filter) {
  return filter instanceof ActiveFilter;
};

let Filter =
/**
 * Abstract base class for filters
 */
exports.Filter = class Filter {
  /**
   * @param {string} text   string representation of the filter
   */
  constructor(text) {
    this.text = text;
  }

  static useFilterState(reference) {
    filterState = reference;
  }

  /**
   * Filter type as a string, e.g. "blocking".
   *
   * Can be `blocking`, `allowing`, `elemhide`, `elemhideexception`,
   * `elemhideemulation`, `snippet`, `comment` or `invalid`.
   *
   * @type {string}
   */
  get type() {
    throw new Error("Please define filter type in the subclass");
  }

  /**
   * True if filter should only be loaded if it comes from a
   * privileged subscription (circumvention subscriptions or special
   * subscriptions).
   * @type {bool}
   */
  get requiresPrivilegedSubscription() {
    return false;
  }

  /**
   * Serializes the filter for writing out on disk.
   * @yields {string}
   */
  *serialize() {
    let {text} = this;

    yield "[Filter]";
    yield "text=" + text;
  }

  toString() {
    return this.text;
  }
};

/**
 * Cache for known filters, maps string representation to filter objects.
 * @type {Map.<string, module:filterClasses.Filter>}
 */
let knownFilters = new Map();

/**
 * Creates a filter of correct type from its text representation - does the
 * basic parsing and calls the right constructor then.
 *
 * @param {string} text   as in Filter()\
 * @return {module:filterClasses.Filter}
 */
exports.Filter.fromText = function(text) {
  let filter = knownFilters.get(text);
  if (filter)
    return filter;

  if (text.length === 0) {
    filter = new InvalidFilter(text, "filter_empty");
  }
  else if (text[0] == "!") {
    filter = new CommentFilter(text);
  }
  else {
    let match = text.includes("#") ? CONTENT_FILTER.exec(text) : null;
    if (match)
      filter = ContentFilter.fromText(text, match[1], match[2], match[3]);
    else
      filter = URLFilter.fromText(text);
  }

  if (filter.type !== "invalid")
    knownFilters.set(filter.text, filter);

  return filter;
};

/**
 * Deserializes a filter
 *
 * @param {Object}  obj map of serialized properties and their values
 * @return {module:filterClasses.Filter} filter or null if the filter couldn't
 *   be created
 */
exports.Filter.fromObject = function(obj) {
  let filter = Filter.fromText(obj.text);
  if (isActiveFilter(filter) && filterState)
    filterState.fromObject(filter.text, obj);
  return filter;
};

let {normalize} = __nested_webpack_require_265611__(/*! ./filters/index.js */ "./node_modules/adblockpluscore/lib/filters/index.js");
exports.Filter.normalize = normalize;

let InvalidFilter =
/**
 * Class for invalid filters
 * @extends module:filterClasses.Filter
 */
exports.InvalidFilter = class InvalidFilter extends Filter {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @param {string} reason Reason why this filter is invalid
   * @param {string?} option The optional option passed to the filter
   * @private
   */
  constructor(text, reason, option = null) {
    super(text);

    this.reason = reason;
    this.option = option;
  }

  get type() {
    return "invalid";
  }

  *serialize() {}
};

let CommentFilter =
/**
 * Class for comments
 * @extends module:filterClasses.Filter
 */
exports.CommentFilter = class CommentFilter extends Filter {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @private
   */
  constructor(text) {
    super(text);
  }

  get type() {
    return "comment";
  }

  *serialize() {}
};

let ActiveFilter =
/**
 * Abstract base class for filters that can get hits
 * @extends module:filterClasses.Filter
 */
exports.ActiveFilter = class ActiveFilter extends Filter {
  /**
   * @param {string} text
   *   see {@link module:filterClasses.Filter Filter()}
   * @param {string} [domains]
   *   Domains that the filter is restricted to separated by domainSeparator
   *   e.g. "foo.com|bar.com|~baz.com"
   * @private
   */
  constructor(text, domains) {
    super(text);

    /**
     * String that the domains property should be generated from
     * @type {?string}
     */
    this.domainSource = domains || null;

    this._domains = domains ? void 0 : null;
  }

  /**
   * Number of filters contained, will always be 1 (required to
   * optimize {@link module:matcher.Matcher Matcher}).
   * @type {number}
   */
  get size() {
    return 1;
  }

  /**
   * See Filter.serialize()
   * @inheritdoc
   */
  *serialize() {
    if (filterState)
      yield* filterState.serialize(this.text);
  }

  /**
   * Defines whether the filter is disabled globally.
   * @type {boolean}
   * @deprecated use
   * {@link module:filterClasses.ActiveFilter#isDisabledForSubscription} and
   * {@link module:filterClasses.ActiveFilter#setDisabledForSubscription} for
   * disabling and enabling filters for specific subscriptions.
   */
  get disabled() {
    return filterState && !filterState.isEnabled(this.text);
  }
  set disabled(value) {
    if (filterState)
      filterState.setEnabled(this.text, !value);
  }

  /**
   * Defines which subscriptions the filter is disabled for.
   * See {@link module:filterClasses.ActiveFilter#isDisabledForSubscription} and
   * {@link module:filterClasses.ActiveFilter#setDisabledForSubscription} for
   * disabling and enabling filters.
   * @type {Set<string>}
   */
  get disabledSubscriptions() {
    if (!filterState)
      return new Set();
    return filterState.disabledSubscriptions(this.text);
  }

  /**
   * Checks whether this filter is disabled.
   * @param {string} subscriptionUrl The subscription to check for
   * enabled / disabled state.
   * @return {boolean} true if the filter is disabled
   */
  isDisabledForSubscription(subscriptionUrl) {
    return filterState &&
      filterState.isDisabledForSubscription(this.text, subscriptionUrl);
  }
  /**
   * Disables or enables the filter.
   * @param {string} [subscriptionUrl] The subscription on which to
   * disable / enable the filter.
   * @param {boolean} [value] new disabled value, true for disabled
   * and false for enabled
   */
  setDisabledForSubscription(subscriptionUrl, value) {
    if (filterState)
      filterState.setDisabledForSubscription(this.text, subscriptionUrl, value);
  }

  /**
   * Separator character used in domainSource property
   * @type {string}
   */
  get domainSeparator() {
    return ",";
  }

  /**
   * Number of hits on the filter since the last reset
   * @type {number}
   */
  get hitCount() {
    return filterState ? filterState.getHitCount(this.text) : 0;
  }
  set hitCount(value) {
    if (filterState)
      filterState.setHitCount(this.text, value);
  }

  /**
   * Last time the filter had a hit (in milliseconds since the beginning of the
   * epoch)
   * @type {number}
   */
  get lastHit() {
    return filterState ? filterState.getLastHit(this.text) : 0;
  }
  set lastHit(value) {
    if (filterState)
      filterState.setLastHit(this.text, value);
  }

  /**
   * Map containing domains that this filter should match on/not match
   * on or null if the filter should match on all domains
   * @type {?Map.<string,boolean>}
   */
  get domains() {
    if (typeof this._domains == "undefined") {
      let {domainSource: source, domainSeparator: sep} = this;
      this._domains = parseDomains(source.toLowerCase(), sep);
    }
    return this._domains;
  }

  /**
   * Array containing public keys of websites that this filter should apply to
   * @type {?Array.<string>}
   */
  get sitekeys() {
    return null;
  }

  /**
   * String that the sitekey property should be generated from
   * @type {?string}
   */
  get sitekeySource() {
    return null;
  }

  /**
   * Checks whether this filter is active on a domain.
   * @param {?string} [docDomain] domain name of the document that loads the URL
   * @param {string} [sitekey] public key provided by the document
   * @return {boolean} true in case of the filter being active
   */
  isActiveOnDomain(docDomain, sitekey) {
    // Sitekeys are case-sensitive so we shouldn't convert them to
    // upper-case to avoid false positives here. Instead we need to
    // change the way filter options are parsed.
    if (this.sitekeys &&
        (!sitekey || !this.sitekeys.includes(sitekey)))
      return false;

    let {domains} = this;

    // If no domains are set the rule matches everywhere
    if (!domains)
      return true;

    if (docDomain == null)
      docDomain = "";
    else if (docDomain[docDomain.length - 1] == ".")
      docDomain = docDomain.substring(0, docDomain.length - 1);

    // If the document has no host name, match only if the filter
    // isn't restricted to specific domains
    if (!docDomain)
      return domains.get("");

    for (docDomain of domainSuffixes(docDomain)) {
      let isDomainIncluded = domains.get(docDomain);
      if (typeof isDomainIncluded != "undefined")
        return isDomainIncluded;
    }

    return domains.get("");
  }

  /**
   * Checks whether this filter is active only on a domain and its subdomains.
   * @param {?string} [docDomain]
   * @return {boolean}
   */
  isActiveOnlyOnDomain(docDomain) {
    let {domains} = this;

    if (!domains || domains.get(""))
      return false;

    if (docDomain == null)
      docDomain = "";
    else if (docDomain[docDomain.length - 1] == ".")
      docDomain = docDomain.substring(0, docDomain.length - 1);

    if (!docDomain)
      return false;

    for (let [domain, isIncluded] of domains) {
      if (isIncluded && domain != docDomain) {
        if (domain.length <= docDomain.length)
          return false;

        if (!domain.endsWith("." + docDomain))
          return false;
      }
    }

    return true;
  }

  /**
   * Checks whether this filter is generic or specific
   * @return {boolean}
   */
  isGeneric() {
    let {sitekeys, domains} = this;

    return !(sitekeys && sitekeys.length) && (!domains || domains.get(""));
  }

  /**
   * Yields the filter itself (required to optimize
   *   {@link module:matcher.Matcher Matcher}).
   * @yields {module:filterClasses.ActiveFilter}
   * @package
   */
  *[Symbol.iterator]() {
    yield this;
  }
};

let URLFilter =
/**
 * Abstract base class for URL filters
 * @extends module:filterClasses.ActiveFilter
 */
exports.URLFilter = class URLFilter extends ActiveFilter {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @param {string} regexpSource
   *   filter part that the regular expression should be build from
   * @param {number} [contentType]
   *   Content types the filter applies to, combination of values from
   *   `{@link module:contentTypes.contentTypes}`
   * @param {boolean} [matchCase]
   *   Defines whether the filter should distinguish between lower and upper
   *   case letters
   * @param {string} [domains]
   *   Domains that the filter is restricted to, e.g. "foo.com|bar.com|~baz.com"
   * @param {boolean} [thirdParty]
   *   Defines whether the filter should apply to third-party or first-party
   *   content only
   * @param {string} [sitekeys]
   *   Public keys of websites that this filter should apply to
   * @param {?HttpHeader} [header]
   *   Header-based filtering.
   * @param {?string} [rewrite]
   *   The name of the internal resource to which to rewrite the
   *   URL. e.g. if the value of the `$rewrite` option is
   *   `abp-resource:blank-html`, this should be `blank-html`.
   *
   * @private
   */
  constructor(text, regexpSource, contentType, matchCase, domains, thirdParty,
              sitekeys, header, rewrite) {
    super(text, domains);

    this._sitekeySource = sitekeys == null ? null : sitekeys;
    this._sitekeys = sitekeys == null ? null : void 0;

    /**
     * Content types the filter applies to, combination of values from
     * `{@link module:contentTypes.contentTypes}`
     * @type {number}
     */
    this.contentType = contentType != null ? contentType : RESOURCE_TYPES;

    /**
     * Defines whether the filter should apply to third-party or
     * first-party content only. Can be null (apply to all content).
     * @type {?boolean}
     */
    this.thirdParty = thirdParty != null ? thirdParty : null;

    /**
     * Header-based filtering expression. Refer to the filter
     * documentation reference for the syntax, or
     * `{@link BlockingFilter.filterHeaders}` for the reference
     * implementation.
     * @type {?HttpHeader}
     */
    this.header = header != null ? header : null;

    /**
     * The name of the internal resource to which to rewrite the
     * URL. e.g. if the value of the `$rewrite` option is
     * `abp-resource:blank-html`, this should be `blank-html`.
     * @type {?string}
     */
    this.rewrite = rewrite != null ? rewrite : null;

    /**
     * Pattern for matching request URLs
     * @type {Pattern}
     */
    this.urlPattern = new Pattern(regexpSource, matchCase);
  }

  /**
   * Expression from which a regular expression should be generated -
   * for delayed creation of the regexp property.
   *
   * Undefined if the filter uses a regex literal pattern.
   * @type {?string}
   * @deprecated Use <code>filter.urlPattern.pattern</code>, or other
   * functions available on <code>{@link module:patterns.Pattern}</code>.
   */
  get pattern() {
    return this.urlPattern.pattern;
  }

  /**
   * Regular expression to be used when testing against this pattern
   * @type {RegExp}
   * @deprecated Use <code>filter.urlPattern.regexp</code>, or other
   * functions available on <code>{@link module:patterns.Pattern}</code>.
   */
  get regexp() {
    return this.urlPattern.regexp;
  }

  /**
   * Defines whether the filter should distinguish between lower and
   * upper case letters
   * @type {boolean}
   */
  get matchCase() {
    return this.urlPattern.matchCase;
  }

  /**
   * @see ActiveFilter.domainSeparator
   */
  get domainSeparator() {
    return "|";
  }

  /**
   * @see ActiveFilter.sitekeys
   */
  get sitekeys() {
    if (typeof this._sitekeys == "undefined")
      this._sitekeys = this._sitekeySource.split("|");

    return this._sitekeys;
  }

  /**
   * @see ActiveFilter.sitekeySource
   */
  get sitekeySource() {
    return this._sitekeySource;
  }

  /**
   * Tests whether the URL request matches this filter
   * @param {module:url.URLRequest} request URL request to be tested
   * @param {number} typeMask bitmask of content / request types to match
   * @param {?string} [sitekey] public key provided by the document
   * @return {boolean} true in case of a match
   */
  matches(request, typeMask, sitekey) {
    let contextMask = typeMask & CONTEXT_TYPES;
    let resourceMask = typeMask & ~CONTEXT_TYPES;
    return (this.contentType & resourceMask) != 0 &&
      (contextMask == 0 ?
       (this.contentType & CONTEXT_TYPES) == 0 :
       (this.contentType & contextMask) != 0
      ) &&
      (this.thirdParty == null || this.thirdParty == request.thirdParty) &&
      (this.urlPattern.regexp ?
       this.isActiveOnDomain(request.documentHostname, sitekey) &&
       this.urlPattern.matchesLocation(request) :
       this.urlPattern.matchesLocation(request) &&
       this.isActiveOnDomain(request.documentHostname, sitekey));
  }
};

/**
 * Creates a URL filter from its text representation
 *
 * @param {string} filterText   same as in Filter()
 * @return {module:filterClasses.Filter}
 */
exports.URLFilter.fromText = function(filterText) {
  let result = parse(filterText);

  if (result instanceof FilterParsingError) {
    let option = null;
    if (result.message == "filter_unknown_option" && result.detail)
      option = result.detail.option;
    return new InvalidFilter(filterText, result.message, option);
  }

  let {
    blocking,
    text,
    regexpSource,
    contentType,
    matchCase,
    domains,
    thirdParty,
    sitekeys,
    header,
    rewrite,
    csp
  } = result;

  try {
    if (blocking) {
      return new BlockingFilter(
        text,
        regexpSource,
        contentType,
        matchCase,
        domains,
        thirdParty,
        sitekeys,
        header,
        rewrite,
        csp
      );
    }
    return new AllowingFilter(
      text,
      regexpSource,
      contentType,
      matchCase,
      domains,
      thirdParty,
      sitekeys,
      header
    );
  }
  catch (e) {
    return new InvalidFilter(filterText, "filter_invalid_regexp");
  }
};

/**
 * @deprecated Use <code>{@link contentTypes}</code> instead.
 * @see contentTypes
 */
// For backwards compatibility.
URLFilter.typeMap = contentTypes;

let BlockingFilter =
/**
 * Class for blocking filters
 * @extends module:filterClasses.URLFilter
 */
exports.BlockingFilter = class BlockingFilter extends URLFilter {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @param {string} regexpSource see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {number} [contentType] see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {boolean} [matchCase] see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {string} [domains] see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {boolean} [thirdParty] see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {string} [sitekeys] see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {?HttpHeader} [header] see
   *   {@link module:filterClasses.URLFilter URLFilter()}
   * @param {?string} [rewrite]
   *   The name of the internal resource to which to rewrite the
   *   URL. e.g. if the value of the `$rewrite` option is
   *   `abp-resource:blank-html`, this should be `blank-html`.
   * @param {?string} [csp]
   *   Content Security Policy to inject when the filter matches
   *
   * @private
   */
  constructor(text, regexpSource, contentType, matchCase, domains, thirdParty,
              sitekeys, header, rewrite, csp) {
    super(
      text,
      regexpSource,
      contentType,
      matchCase,
      domains,
      thirdParty,
      sitekeys,
      header,
      rewrite
    );

    /**
     * Content Security Policy to inject for matching requests.
     * @type {?string}
     */
    this.csp = csp != null ? csp : null;
  }

  get type() {
    return "blocking";
  }

  get requiresPrivilegedSubscription() {
    return (this.contentType & contentTypes.HEADER) != 0;
  }

  /**
   * Rewrites an URL.
   * @param {string} url the URL to rewrite
   * @return {string} the rewritten URL, or the original in case of failure
   */
  rewriteUrl(url) {
    return resourceMap.get(this.rewrite) || url;
  }

  /**
   * Filter headers.
   *
   * This function would be called by the request blocker code after
   * matching the request.
   *
   * @param {webRequest.HttpHeaders} headers the HTTP response headers
   *   to match, as they are returned by the request blocker. They
   *   follow the {@link webRequest API
   *   https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/HttpHeaders}.
   * @return {boolean} Whether the headers match. Will return true if
   *   there is nothing to match against, or if the header is present
   *   but no value.
   */
  filterHeaders(headers) {
    if (!this.header)
      return true;

    for (let header of headers) {
      if (header.name.toLowerCase() == this.header.name) {
        if (this.header.value) {
          if (header.value.includes(this.header.value))
            return true;
        }
        else {
          return true;
        }
      }
    }

    return false;
  }
};

let AllowingFilter =
/**
 * Class for allowing (allowlisting) filters
 * @extends module:filterClasses.URLFilter
 */
exports.AllowingFilter = class AllowingFilter extends URLFilter {
  get type() {
    return "allowing";
  }
};

let ContentFilter =
/**
 * Base class for content filters
 * @extends module:filterClasses.ActiveFilter
 */
exports.ContentFilter = class ContentFilter extends ActiveFilter {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @param {string} [domains] Host names or domains the filter should be
   *                           restricted to
   * @param {string} body      The body of the filter or the script that should
   *                           be executed or the CSS selector for the HTML
   *                           elements that should be hidden
   *
   * @private
   */
  constructor(text, domains, body) {
    super(text, domains || null);

    this.body = body;
  }
};

/**
 * Creates a content filter from a pre-parsed text representation
 *
 * @param {string} text         same as in Filter()
 * @param {string} [domains]
 *   domains part of the text representation
 * @param {string} [type]
 *   rule type, either:
 *     * "" for an element hiding filter
 *     * "@" for an element hiding exception filter
 *     * "?" for an element hiding emulation filter
 *     * "$" for a snippet filter
 * @param {string} body
 *   body part of the text representation, either a CSS selector or a snippet
 *   script
 * @return {module:filterClasses.ElemHideFilter|
 *          module:filterClasses.ElemHideException|
 *          module:filterClasses.ElemHideEmulationFilter|
 *          module:filterClasses.SnippetFilter|
 *          module:filterClasses.InvalidFilter}
 */
exports.ContentFilter.fromText = function(text, domains, type, body) {
  // We don't allow content filters which have any empty domains.
  // Note: The ContentFilter.prototype.domainSeparator is duplicated here, if
  // that changes this must be changed too.
  if (domains && /(^|,)~?(,|$)/.test(domains))
    return new InvalidFilter(text, "filter_invalid_domain");

  let restrictedByDomain = /,[^~][^,.]*\.[^,]/.test("," + domains) ||
      ("," + domains + ",").includes(",localhost,");

  if (type == "?" || type == "$") {
    // Element hiding emulation and snippet filters are inefficient so we need
    // to make sure that they're only applied if they specify active domains
    if (!restrictedByDomain) {
      return new InvalidFilter(text, type == "?" ?
        "filter_elemhideemulation_nodomain" :
        "filter_snippet_nodomain");
    }

    if (type == "?")
      return new ElemHideEmulationFilter(text, domains, body);

    return new SnippetFilter(text, domains, body);
  }

  if (!restrictedByDomain &&
      body.length < MIN_GENERIC_CONTENT_FILTER_BODY_LENGTH)
    return new InvalidFilter(text, "filter_elemhide_not_specific_enough");

  if (type == "@")
    return new ElemHideException(text, domains, body);

  return new ElemHideFilter(text, domains, body);
};

let ElemHideBase =
/**
 * Base class for element hiding filters
 * @extends module:filterClasses.ContentFilter
 */
exports.ElemHideBase = class ElemHideBase extends ContentFilter {
  /**
   * CSS selector for the HTML elements that should be hidden
   * @type {string}
   */
  get selector() {
    return this.body;
  }
};

let ElemHideFilter =
/**
 * Class for element hiding filters
 * @extends module:filterClasses.ElemHideBase
 */
exports.ElemHideFilter = class ElemHideFilter extends ElemHideBase {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @param {string} [domains]  see
   *   {@link module:filterClasses.ElemHideBase ElemHideBase()}
   * @param {string} selector see
   *   {@link module:filterClasses.ElemHideBase ElemHideBase()}
   *
   * @private
   */
  constructor(text, domains, selector) {
    super(text, domains, selector);
  }

  get type() {
    return "elemhide";
  }
};

let ElemHideException =
/**
 * Class for element hiding exceptions
 * @extends module:filterClasses.ElemHideBase
 */
exports.ElemHideException = class ElemHideException extends ElemHideBase {
  /**
   * @param {string} text see {@link module:filterClasses.Filter Filter()}
   * @param {string} [domains]  see
   *   {@link module:filterClasses.ElemHideBase ElemHideBase()}
   * @param {string} selector see
   *   {@link module:filterClasses.ElemHideBase ElemHideBase()}
   *
   * @private
   */
  constructor(text, domains, selector) {
    super(text, domains, selector);
  }

  get type() {
    return "elemhideexception";
  }
};

let ElemHideEmulationFilter =
/**
 * Class for element hiding emulation filters
 */
exports.ElemHideEmulationFilter =
class ElemHideEmulationFilter extends ElemHideBase {
  /**
   * @param {string} text    see {@link module:filterClasses.Filter Filter()}
   * @param {string} domains see
   *   {@link module:filterClasses.ElemHideBase ElemHideBase()}
   * @param {string} selector see
   *   {@link module:filterClasses.ElemHideBase ElemHideBase()}
   * @constructor
   * @extends module:filterClasses.ElemHideBase
   *
   * @private
   */
  constructor(text, domains, selector) {
    super(text, domains, selector);
  }

  get type() {
    return "elemhideemulation";
  }
};

let SnippetFilter =
/**
 * Class for snippet filters
 * @extends module:filterClasses.ContentFilter
 */
exports.SnippetFilter = class SnippetFilter extends ContentFilter {
  get type() {
    return "snippet";
  }
  get requiresPrivilegedSubscription() {
    return true;
  }

  /**
   * Script that should be executed
   * @type {string}
   */
  get script() {
    return this.body;
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filterEngine.js":
/*!**********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filterEngine.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_293660__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



__nested_webpack_require_293660__(/*! ./polyfill */ "./node_modules/adblockpluscore/lib/polyfill.js");
const {parseURL} = __nested_webpack_require_293660__(/*! ./url */ "./node_modules/adblockpluscore/lib/url.js");
const {Filter} = __nested_webpack_require_293660__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");
const {newDefaultMatcher} = __nested_webpack_require_293660__(/*! ./matcher */ "./node_modules/adblockpluscore/lib/matcher.js");
const {ElemHide} = __nested_webpack_require_293660__(/*! ./elemHide */ "./node_modules/adblockpluscore/lib/elemHide.js");
const {ElemHideEmulation} = __nested_webpack_require_293660__(/*! ./elemHideEmulation */ "./node_modules/adblockpluscore/lib/elemHideEmulation.js");
const {ElemHideExceptions} = __nested_webpack_require_293660__(/*! ./elemHideExceptions */ "./node_modules/adblockpluscore/lib/elemHideExceptions.js");
const {setRecommendations} = __nested_webpack_require_293660__(/*! ./recommendations */ "./node_modules/adblockpluscore/lib/recommendations.js");
const {Snippets} = __nested_webpack_require_293660__(/*! ./snippets */ "./node_modules/adblockpluscore/lib/snippets.js");
const {profiler} = __nested_webpack_require_293660__(/*! ./profiler */ "./node_modules/adblockpluscore/lib/profiler.js");
const {Features} = __nested_webpack_require_293660__(/*! ./features */ "./node_modules/adblockpluscore/lib/features.js");

/**
 * Filter engine.
 */
class FilterEngine {
  /**
   * @typedef FilterEngineOptions
   * @type {object}
   * @property {?Array.<object>} recommendations The index of known downloadable
   *   subscriptions.
   * @property {?module:features.Features} features Enable specific features
   */
  /**
   * Creates a `{@link module:filterEngine.FilterEngine FilterEngine}`
   * object.
   *
   * @param {?FilterEngineOptions} options The options to create the engine.
   */
  constructor(options) {
    this.p = profiler("FilterEngine");

    this.p.start();

    /** Activated features
     * @type {Features}
     */
    this.features = options ? options.features : Features.DEFAULT;

    if (options && options.recommendations)
      setRecommendations(options.recommendations);

    /** The `{@link module:elemHideExceptions.ElemHideExceptions}` for
     *    the engine.
     * @type {module:elemHideExceptions.ElemHideExceptions}
     */
    this.elemHideExceptions = new ElemHideExceptions();
    /** The `{@link module:elemHide.ElemHide}` for the engine.
     * @type {module:elemHide.ElemHide}
     */
    this.elemHide = new ElemHide(this.elemHideExceptions);
    /** The `{@link module:elemHideEmulation.ElemHideEmulation}` for
     *    the engine.
     * @type {module:elemHideEmulation.ElemHideEmulation}
     */
    this.elemHideEmulation = new ElemHideEmulation(this.elemHideExceptions);
    /** The `{@link module:snippets.Snippets}` for the engine.
     * @type {module:snippets.Snippets}
     */
    this.snippets = new Snippets();
    /** The `{@link module:matcher.CombinedMatcher}` to use with the engine.
     * @type {module:matcher.CombinedMatcher}
     */
    this.defaultMatcher = newDefaultMatcher();

    /** The `{@link module:filterListener.FilterListener}` to use.
     * @type {?module:filterListener.FilterListener}
     */
    this._filterListener = null;
    /** The `{@link module:filterStorage.FilterStorage}` to use.
     * @type {?module:filterStorage.FilterStorage}
     */
    this._filterStorage = null;

    /**
     * The promise returned by
     * `{@link module:filterEngine.FilterEngine#initialize}`.
     * @type {?Promise}
     * @private
     */
    this._initializationPromise = null;
  }

  /**
   * Initializes a `{@link module:filterEngine.FilterEngine FilterEngine}`
   * object with the given filters or filters loaded from disk.
   *
   * @param {Iterable.<string>} [filterSource] An iterable object that yields
   *   the text of the filters with which to initialize the
   *   `{@link module:filterEngine.FilterEngine FilterEngine}` object. If
   *   omitted, filters are loaded from disk.
   *
   * @returns {Promise} A promise that is fulfilled when the initialization is
   *   complete.
   *
   * @public
   */
  initialize(filterSource) {
    this.p.mark("initialize");
    if (!this._initializationPromise) {
      if (typeof filterSource == "undefined") {
        // Note: filterListener.js and filterStorage.js must be loaded
        // conditionally here in local scope in order for the engine
        // to be able to work in standalone mode with no disk and
        // network I/O.
        const {FilterStorage} = __nested_webpack_require_293660__(/*! ./filterStorage */ "./node_modules/adblockpluscore/lib/filterStorage.js");
        const {FilterListener} = __nested_webpack_require_293660__(/*! ./filterListener */ "./node_modules/adblockpluscore/lib/filterListener.js");
        this._filterStorage = new FilterStorage({features: this.features});
        this._filterListener = new FilterListener();
        this._initializationPromise = this._filterListener.initialize(
          this, this._filterStorage
        );
      }
      else {
        this._initializationPromise = Promise.resolve().then(() => {
          for (let text of filterSource) {
            text = Filter.normalize(text, true);
            if (text) {
              let filter = Filter.fromText(text);
              if (filter.type !== "invalid")
                this.add(filter);
            }
          }
        }).finally(() => {
          this.p.mark("download_done");
        });
      }
    }

    return this._initializationPromise;
  }

  get filterStorage() {
    return this._filterStorage;
  }

  /**
   * Selects the appropriate module for the given filter type.
   *
   * @param {string} type The type of a filter. This must be one of
   *   `"blocking"`, `"allowing"`, `"elemhide"`, `"elemhideemulation"`,
   *   `"elemhideexception"`, and `"snippet"`; otherwise the function returns
   *   `null`.
   *
   * @returns {?object} The appropriate module for the given filter type.
   */
  selectModule(type) {
    switch (type) {
      case "blocking":
      case "allowing":
        return this.defaultMatcher;
      case "elemhide":
        return this.elemHide;
      case "elemhideemulation":
        return this.elemHideEmulation;
      case "elemhideexception":
        return this.elemHideExceptions;
      case "snippet":
        return this.snippets;
    }

    return null;
  }

  /**
   * Adds a new filter.
   * @param {module:filterClasses.ActiveFilter} filter
   * @package
   */
  add(filter) {
    let module = this.selectModule(filter.type);
    if (module)
      module.add(filter);
  }

  /**
   * Removes an existing filter.
   * @param {module:filterClasses.ActiveFilter} filter
   * @package
   */
  remove(filter) {
    let module = this.selectModule(filter.type);
    if (module)
      module.remove(filter);
  }

  /**
   * Checks whether a filter exists.
   * @param {module:filterClasses.ActiveFilter} filter
   * @returns {boolean}
   * @package
   */
  has(filter) {
    let module = this.selectModule(filter.type);
    if (module)
      return module.has(filter);
    return false;
  }

  /**
   * Clears all filters.
   * @package
   */
  clear() {
    this.defaultMatcher.clear();
    this.elemHide.clear();
    this.elemHideEmulation.clear();
    this.elemHideExceptions.clear();
    this.snippets.clear();
  }

  /**
   * Matches existing URL filters against a web resource
   * (HTML document, CSS style sheet, PNG image, etc.) and returns the matching
   * filter if there's a match.
   *
   * @param {string|URL|module:url~URLInfo} url The URL of the resource.
   * @param {number} typeMask The
   *   {@link module:contentTypes.contentTypes content types} associated with
   *   the resource.
   * @param {string} documentHostname The hostname of the document of the
   *   resource.
   * @param {?string} [sitekey] An optional public key associated with the
   *   document of the resource.
   * @param {boolean} [specificOnly] Whether to ignore any generic filters.
   *
   * @returns {?string} A URL filter if there's a match; otherwise `null`.
   *
   * @public
   */
  match(url, typeMask, documentHostname, sitekey = null, specificOnly = false) {
    if (typeof url == "string")
      url = parseURL(url);

    let filter = this.defaultMatcher.match(
      url, typeMask, documentHostname, sitekey, specificOnly
    );
    return filter ? filter.text : null;
  }
}

/**
 * The `FilterEngine` class maintains filters for request blocking, element
 * hiding, and snippets.
 *
 * @public
 *
 * @example
 *
 * let {contentTypes, FilterEngine} = require("adblockpluscore");
 *
 * let filterEnginer = new FilterEngine();
 * await filterEngine.initialize(
 *   [
 *     "/annoying-ad^$image",
 *     "||example.com/social-widget.html^"
 *   ]
 * );
 *
 * let resource = {
 *   url: "https://ad-server.example.net/annoying-ad.png",
 *   documentURL: "https://news.example.com/world.html"
 * };
 *
 * let filter = filterEngine.match(resource.url, contentTypes.IMAGE,
 *                                 new URL(resource.documentURL).hostname);
 * console.log(filter); // prints "/annoying-ad^$image"
 */
exports.FilterEngine = FilterEngine;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filterListener.js":
/*!************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filterListener.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_303789__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Synchronization between filter storage and the filter engine.
 */

const {filterNotifier} = __nested_webpack_require_303789__(/*! ./filterNotifier */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
const {isActiveFilter, Filter} = __nested_webpack_require_303789__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");

/**
 * Checks whether filters from a given subscription should be deployed to the
 * filter engine.
 *
 * If the subscription is both valid and enabled, the function returns `true`;
 * otherwise, it returns `false`.
 *
 * @param {module:subscriptionClasses.Subscription} subscription
 *   The subscription.
 *
 * @returns {boolean} Whether filters from the subscription should be deployed
 *   to the filter engine.
 */
function shouldDeployFilters(subscription) {
  return subscription.valid && !subscription.disabled;
}

/**
 * Deploys a filter to the filter engine.
 *
 * The filter is deployed only if it belongs to at least one subscription that
 * is both valid and enabled.
 *
 * If the filter is a snippet filter, or a block filter with the `$header`
 * options, it is deployed only if it belongs to at
 * least one subscription that is valid, enabled, and of
 * {@link module:subscriptionClasses.Subscription#type type}
 * `circumvention` or a
 * {@link module:subscriptionClasses.SpecialSubscription special subscription}
 * that keeps user-defined filters.
 *
 * @param {module:filterEngine.FilterEngine} engine A reference to the
 *   filter engine.
 * @param {module:filterStorage.FilterStorage} storage A reference to
 *   the filter storage.
 * @param {Filter} filter The filter.
 * @param {?Array.<module:subscriptionClasses.Subscription>} [subscriptions]
 *   A list of subscriptions to which the filter belongs. If omitted or `null`,
 *   the information is looked up from
 *   {@link module:filterStorage.filterStorage filter storage}.
 */
function deployFilter(engine, storage, filter, subscriptions = null) {
  if (!isActiveFilter(filter))
    return;

  let deploy = false;
  let allowPrivileged = false;
  let requiresPrivilegedSubscription = filter.requiresPrivilegedSubscription;

  for (let subscription of subscriptions ||
                           storage.subscriptions(filter.text)) {
    if (shouldDeployFilters(subscription) &&
        !filter.isDisabledForSubscription(subscription.url)) {
      deploy = true;
      if (!requiresPrivilegedSubscription)
        break;

      // Allow snippets to be executed only by the circumvention lists or the
      // user's own filters.
      if (subscription.privileged) {
        allowPrivileged = true;
        break;
      }
    }
  }

  if (!deploy)
    return;

  if (requiresPrivilegedSubscription && !allowPrivileged)
    return;

  engine.add(filter);
}

/**
 * Undeploys a filter from the filter engine.
 *
 * The filter is undeployed only if it does not belong to at least one
 * subscription that is both valid and enabled.
 *
 * @param {module:filterEngine.FilterEngine} engine A reference to the
 *   filter engine.
 * @param {module:filterStorage.FilterStorage} storage A reference to the
 *   filter storage.
 * @param {module:filterClasses.Filter} filter The filter.
 */
function undeployFilter(engine, storage, filter) {
  if (!isActiveFilter(filter))
    return;

  let requiresPrivilegedSubscription = filter.requiresPrivilegedSubscription;

  for (let subscription of storage.subscriptions(filter.text)) {
    if (shouldDeployFilters(subscription) &&
        !filter.isDisabledForSubscription(subscription.url)) {
      if (!requiresPrivilegedSubscription ||
          (requiresPrivilegedSubscription && subscription.privileged))
        return;
    }
  }

  engine.remove(filter);
}

/**
 * `{@link module:filterListener.filterListener filterListener}`
 * implementation.
 */
class FilterListener {
  /**
   * Initializes filter listener on startup, registers the necessary hooks.
   *
   * Initialization is asynchronous; once complete,
   * `{@link module:filterNotifier.filterNotifier filterNotifier}` emits the
   * `ready` event.
   *
   * @hideconstructor
   */
  constructor() {
    /**
     * A reference to the filter engine.
     * @type {?module:filterEngine.FilterEngine}
     * @private
     */
    this._engine = null;

    /**
     * A reference to the filter storage
     * @type {?module:filterStorage.FilterStorage}
     * @private
     */
    this._storage = null;

    /**
     * Increases on filter changes, filters will be saved if it exceeds 1.
     * @type {number}
     * @private
     */
    this._isDirty = 0;
  }

  /**
   * Initializes filter listener.
   * @param {module:filterEngine.FilterEngine} engine A reference to the
   *   filter engine.
   * @param {module:filterStorage.FilterStorage} storage A reference to the
   *   filter storage.
   * @returns {Promise} A promise that is fulfilled when the initialization is
   *   complete.
   * @package
   */
  async initialize(engine, storage) {
    if (engine == null || typeof engine != "object")
      throw new Error("engine must be a non-null object.");
    if (storage == null || typeof storage != "object")
      throw new Error("filterStorage must be a non-null object.");

    if (this._engine != null || this._storage != null)
      throw new Error("Filter listener already initialized.");

    this._engine = engine;
    this._storage = storage;

    await storage.loadFromDisk();

    let promise = Promise.resolve();

    // Initialize filters from each subscription asynchronously on startup by
    // setting up a chain of promises.
    for (let subscription of storage.subscriptions()) {
      if (shouldDeployFilters(subscription)) {
        await promise.then(() => {
          for (let text of subscription.filterText()) {
            deployFilter(
              this._engine, storage, Filter.fromText(text), [subscription]
            );
          }
        });
      }
    }

    filterNotifier.on("filter.added", this._onFilterAdded.bind(this));
    filterNotifier.on("filter.removed", this._onFilterRemoved.bind(this));
    filterNotifier.on("filter.moved", this._onGenericChange.bind(this));

    filterNotifier.on("filterState.enabled",
                      this._onFilterStateEnabled.bind(this));
    filterNotifier.on("filterState.disabledSubscriptions",
                      this._onFilterStateEnabled.bind(this));
    filterNotifier.on("filterState.hitCount",
                      this._onFilterStateHitCount.bind(this));
    filterNotifier.on("filterState.lastHit",
                      this._onFilterStateLastHit.bind(this));

    filterNotifier.on("subscription.added",
                      this._onSubscriptionAdded.bind(this));
    filterNotifier.on("subscription.removed",
                      this._onSubscriptionRemoved.bind(this));
    filterNotifier.on("subscription.disabled",
                      this._onSubscriptionDisabled.bind(this));
    filterNotifier.on("subscription.updated",
                      this._onSubscriptionUpdated.bind(this));
    filterNotifier.on("subscription.title", this._onGenericChange.bind(this));
    filterNotifier.on("subscription.fixedTitle",
                      this._onGenericChange.bind(this));
    filterNotifier.on("subscription.homepage",
                      this._onGenericChange.bind(this));
    filterNotifier.on("subscription.downloadStatus",
                      this._onGenericChange.bind(this));
    filterNotifier.on("subscription.lastCheck",
                      this._onGenericChange.bind(this));
    filterNotifier.on("subscription.errors",
                      this._onGenericChange.bind(this));

    filterNotifier.on("load", this._onLoad.bind(this));
    filterNotifier.on("save", this._onSave.bind(this));

    // Indicate that all filters are ready for use.
    filterNotifier.emit("ready");
  }

  /**
   * Increases "dirty factor" of the filters and calls
   * filterStorage.saveToDisk() if it becomes 1 or more.
   *
   * Save is executed delayed to prevent multiple subsequent calls. If the
   * parameter is 0 it forces saving filters if any changes were recorded after
   * the previous save.
   *
   * @param {number} factor
   *
   * @private
   */
  _setDirty(factor) {
    if (factor == 0 && this._isDirty > 0)
      this._isDirty = 1;
    else
      this._isDirty += factor;
    if (this._isDirty >= 1) {
      this._isDirty = 0;
      this._storage.saveToDisk();
    }
  }

  _onSubscriptionAdded(subscription) {
    this._setDirty(1);

    if (shouldDeployFilters(subscription)) {
      for (let text of subscription.filterText()) {
        deployFilter(
          this._engine, this._storage, Filter.fromText(text), [subscription]
        );
      }
    }
  }

  _onSubscriptionRemoved(subscription) {
    this._setDirty(1);

    if (shouldDeployFilters(subscription)) {
      for (let text of subscription.filterText())
        undeployFilter(this._engine, this._storage, Filter.fromText(text));
    }
  }

  _onSubscriptionDisabled(subscription, newValue) {
    this._setDirty(1);

    if (this._storage.hasSubscription(subscription)) {
      if (newValue == false) {
        for (let text of subscription.filterText()) {
          deployFilter(
            this._engine, this._storage, Filter.fromText(text), [subscription]
          );
        }
      }
      else {
        for (let text of subscription.filterText())
          undeployFilter(this._engine, this._storage, Filter.fromText(text));
      }
    }
  }

  _onSubscriptionUpdated(subscription, textDelta) {
    this._setDirty(1);

    if (textDelta && shouldDeployFilters(subscription) &&
        this._storage.hasSubscription(subscription)) {
      for (let text of textDelta.removed) {
        undeployFilter(
          this._engine, this._storage, Filter.fromText(text)
        );
      }

      for (let text of textDelta.added) {
        deployFilter(
          this._engine, this._storage, Filter.fromText(text), [subscription]
        );
      }
    }
  }

  _onFilterAdded(filter) {
    this._setDirty(1);
    deployFilter(this._engine, this._storage, filter);
  }

  _onFilterRemoved(filter) {
    this._setDirty(1);
    undeployFilter(this._engine, this._storage, filter);
  }

  _onFilterStateEnabled(text, newValue) {
    this._setDirty(1);

    // it's difficult to tell from newValue alone if we need to add or
    // remove the filter. Luckily, deployFilter and undeployFilter do
    // full checks that the filter should be added / removed.
    let filter = Filter.fromText(text);
    if (this._engine.has(filter))
      undeployFilter(this._engine, this._storage, filter);
    else
      deployFilter(this._engine, this._storage, filter);
  }

  _onFilterStateHitCount(text, newValue) {
    if (newValue == 0)
      this._setDirty(0);
    else
      this._setDirty(0.002);
  }

  _onFilterStateLastHit() {
    this._setDirty(0.002);
  }

  _onGenericChange() {
    this._setDirty(1);
  }

  _onLoad() {
    this._isDirty = 0;

    this._engine.clear();

    for (let subscription of this._storage.subscriptions()) {
      if (shouldDeployFilters(subscription)) {
        for (let text of subscription.filterText()) {
          deployFilter(
            this._engine, this._storage, Filter.fromText(text), [subscription]
          );
        }
      }
    }
  }

  _onSave() {
    this._isDirty = 0;
  }
}

/**
 * Component synchronizing filter storage with the filter engine.
 * @package
 */
exports.FilterListener = FilterListener;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filterNotifier.js":
/*!************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filterNotifier.js ***!
  \************************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_316316__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file This component manages listeners and calls them to distribute
 * messages about filter changes.
 */

const {EventEmitter} = __nested_webpack_require_316316__(/*! ./events */ "./node_modules/adblockpluscore/lib/events.js");

/**
 * This object allows registering and triggering listeners for filter events.
 * @type {module:events.EventEmitter}
 */
exports.filterNotifier = new EventEmitter();


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filterState.js":
/*!*********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filterState.js ***!
  \*********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_317766__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



const {filterNotifier} = __nested_webpack_require_317766__(/*! ./filterNotifier */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
const {Filter} = __nested_webpack_require_317766__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");

class FilterState {
  /**
   * Construct a new FilterState.
   * As a side effect this will set the global FilterState used
   * by Filter. Avoid constructing it more than once.
   */
  constructor() {
    /**
     * Internal map containing filter state.
     * @type {Map.<string, FilterStateEntry>}
     */
    this.map = new Map();

    // For now we'll assume that this is the filter state
    Filter.useFilterState(this);
  }

  /**
   * Gets which subscriptions this filters has been disabled for.
   * @param {string} filterText The text of the filter.
   * @returns {Set<string>} Set of subscription urls that this filter
   * has been disabled for.
   */
  disabledSubscriptions(filterText) {
    let state = this.map.get(filterText);
    if (!state || typeof state.disabledSubscriptions !== "object")
      return new Set();
    return state.disabledSubscriptions;
  }

  /**
   * Reset the disabled status of this filter to the default of
   * enabled for all subscriptions.
   * @param {string} filterText The text of the filter.
   */
  resetEnabled(filterText) {
    this._updateStateObject(filterText, state => {
      state.resetEnabled();
    });
  }

  /**
   * Checks whether a filter is disabled for a subscription.
   * @param {string} filterText The text of the filter.
   * @param {string} subscriptionUrl The subscription to check for
   * enabled / disabled state.
   * @returns {boolean} Whether the filter is disabled.
   */
  isDisabledForSubscription(filterText, subscriptionUrl) {
    let state = this.map.get(filterText);
    if (state)
      return state.isDisabledForSubscription(subscriptionUrl);
    return false;
  }

  /**
   * Sets the disabled state of a filter for a subscription.
   * @param {string} filterText The text of the filter.
   * @param {string} subscriptionUrl The subscription to enable /
   * disable the filter in.
   * @param {boolean} disabled The new disabled state of the filter.
   */
  setDisabledForSubscription(filterText, subscriptionUrl, disabled) {
    this._updateStateObject(filterText, state => {
      state.setDisabledForSubscription(subscriptionUrl, disabled);
    });
  }

  /**
   * Checks whether a filter is enabled.
   * @param {string} filterText The text of the filter.
   * @returns {boolean} Whether the filter is enabled.
   * @deprecated Use
   * {@link module:filterState.FilterState#isDisabledForSubscription} instead
   */
  isEnabled(filterText) {
    let state = this.map.get(filterText);
    if (state)
      return state.enabled;
    return true;
  }

  /**
   * Sets the enabled state of a filter.
   * @param {string} filterText The text of the filter.
   * @param {boolean} enabled The new enabled state of the filter.
   * @deprecated Use
   * {@link module:filterState.FilterState#setDisabledForSubscription} instead
   */
  setEnabled(filterText, enabled) {
    this._updateStateObject(filterText, state => {
      state.enabled = enabled;
    });
  }

  /**
   * Toggles the enabled state of a filter.
   * @param {string} filterText The text of the filter.
   * @deprecated Use
   * {@link module:filterState.FilterState#setDisabledForSubscription} instead
   */
  toggleEnabled(filterText) {
    let newValue = !this.isEnabled(filterText);
    this.setEnabled(filterText, newValue);
  }

  /**
   * Returns the hit count of a filter.
   * @param {string} filterText The text of the filter.
   * @returns {number} The hit count of the filter.
   */
  getHitCount(filterText) {
    let state = this.map.get(filterText);
    if (state)
      return state.hitCount;

    return 0;
  }

  /**
   * Sets the hit count of a filter.
   * @param {string} filterText The text of the filter.
   * @param {number} hitCount The new hit count of the filter.
   */
  setHitCount(filterText, hitCount) {
    this._updateStateObject(filterText, state => {
      state.hitCount = hitCount;
    });
  }

  /**
   * Resets the hit count of a filter.
   * @param {string} filterText The text of the filter.
   */
  resetHitCount(filterText) {
    this.setHitCount(filterText, 0);
  }

  /**
   * Returns the last hit time of a filter.
   * @param {string} filterText The text of the filter.
   * @returns {number} The last hit time of the filter in milliseconds since
   *   the Unix epoch.
   */
  getLastHit(filterText) {
    let state = this.map.get(filterText);
    if (state)
      return state.lastHit;

    return 0;
  }

  /**
   * Sets the last hit time of a filter.
   * @param {string} filterText The text of the filter.
   * @param {number} lastHit The new last hit time of the filter in
   *   milliseconds since the Unix epoch.
   */
  setLastHit(filterText, lastHit) {
    this._updateStateObject(filterText, state => {
      state.lastHit = lastHit;
    });
  }

  /**
   * Resets the last hit time of a filter.
   * @param {string} filterText The text of the filter.
   */
  resetLastHit(filterText) {
    this.setLastHit(filterText, 0);
  }

  /**
   * Registers a filter hit by incrementing the hit count of the filter and
   * setting the last hit time of the filter to the current time.
   * @param {string} filterText The text of the filter.
   */
  registerHit(filterText) {
    let now = Date.now();
    this._updateStateObject(filterText, state => {
      state.hitCount++;
      state.lastHit = now;
    });
  }

  /**
   * Resets the hit count and last hit time of a filter.
   * @param {string} filterText The text of the filter.
   */
  resetHits(filterText) {
    this._updateStateObject(filterText, state => {
      state.hitCount = 0;
      state.lastHit = 0;
    });
  }

  /**
   * Resets the enabled state, hit count, and last hit time of a filter.
   * @param {string} filterText The text of the filter.
   */
  reset(filterText) {
    let state = this.map.get(filterText);
    if (!state)
      return;

    this.map.delete(filterText);

    if (state.enabled !== true) {
      filterNotifier.emit("filterState.enabled",
                          filterText,
                          true,
                          state.enabled);
    }

    if (state.disabledSubscriptions && state.disabledSubscriptions.size > 0) {
      filterNotifier.emit("filterState.disabledSubscriptions",
                          filterText,
                          new Set(),
                          state.disabledSubscriptions);
    }

    if (state.hitCount != 0) {
      filterNotifier.emit("filterState.hitCount",
                          filterText,
                          0,
                          state.hitCount);
    }

    if (state.lastHit != 0)
      filterNotifier.emit("filterState.lastHit", filterText, 0, state.lastHit);
  }

  /**
   * Serializes the state of a filter.
   * @param {string} filterText The text of the filter.
   * @yields {string} The next line in the serialized representation of the
   *   state of the filter.
   * @see module:filterState.FilterState#fromObject
   * @package
   */
  *serialize(filterText) {
    let state = this.map.get(filterText);
    if (!state)
      return;

    yield "[Filter]";
    yield "text=" + filterText;

    if (state.disabled) {
      yield "disabled=true";
    }
    else if (typeof state.disabledSubscriptions === "object") {
      for (let disabledSubscription of state.disabledSubscriptions)
        yield "disabledSubscriptions[]=" + disabledSubscription;
    }

    if (state.hitCount != 0)
      yield "hitCount=" + state.hitCount;
    if (state.lastHit != 0)
      yield "lastHit=" + state.lastHit;
  }

  /**
   * Reads the state of a filter from an object representation.
   * @param {string} filterText The text of the filter.
   * @param {Object} object An object containing at least one of `disabled`,
   *   `hitCount`, and `lastHit` properties and their appropriate values.
   * @see module:filterState.FilterState#serialize
   * @package
   */
  fromObject(filterText, object) {
    if (!("disabled" in object ||
          "disabledSubscriptions" in object ||
          "hitCount" in object ||
          "lastHit" in object))
      return;

    let state = new FilterStateEntry();
    if (String(object.disabled) == "true")
      state.disabled = true;
    else if (typeof object.disabledSubscriptions === "object")
      state.disabledSubscriptions = new Set(object.disabledSubscriptions);

    state.hitCount = parseInt(object.hitCount, 10) || 0;
    state.lastHit = parseInt(object.lastHit, 10) || 0;
    if (!state.isEmpty())
      this.map.set(filterText, state);
  }

  _updateStateObject(filterText, doUpdate) {
    let state = this.map.get(filterText);
    if (!state) {
      state = new FilterStateEntry();
      this.map.set(filterText, state);
    }

    let oldHitCount = state.hitCount;
    let oldLastHit = state.lastHit;
    let oldEnabled = state.enabled;
    let oldDisabledSubscriptions = new Set(state.disabledSubscriptions);

    doUpdate(state);

    let newHitCount = state.hitCount;
    let newLastHit = state.lastHit;
    let newEnabled = state.enabled;
    let newDisabledSubscriptions = new Set(state.disabledSubscriptions);

    if (state.isEmpty())
      this.map.delete(filterText);

    if (oldHitCount !== newHitCount) {
      filterNotifier.emit("filterState.hitCount",
                          filterText,
                          newHitCount,
                          oldHitCount);
    }

    if (oldLastHit !== newLastHit) {
      filterNotifier.emit("filterState.lastHit",
                          filterText,
                          newLastHit,
                          oldLastHit);
    }

    if (oldEnabled !== newEnabled) {
      filterNotifier.emit("filterState.enabled",
                          filterText,
                          newEnabled,
                          oldEnabled);
    }

    if (!disabledSubscriptionsEquals(oldDisabledSubscriptions,
                                     newDisabledSubscriptions)) {
      filterNotifier.emit("filterState.disabledSubscriptions",
                          filterText,
                          newDisabledSubscriptions,
                          oldDisabledSubscriptions);
    }
  }
}

/**
 * Represents the state for a single filter.
 * See {@link module:filterState.FilterState}
 */
class FilterStateEntry {
  constructor() {
    /**
     * The hit count of the filter.
     * @type {number}
     */
    this.hitCount = 0;

    /**
     * The last hit time of the filter in milliseconds since the Unix epoch.
     * @type {number}
     */
    this.lastHit = 0;
  }

  /**
   * Check if the state is empty, so we know if we can clean it up.
   * @returns {boolean}
   */
  isEmpty() {
    return this.hitCount === 0 &&
      this.lastHit === 0 &&
      !this.disabled &&
      !this.disabledSubscriptions;
  }

  /**
   * Check if a filter is disabled for a specified subscription.
   * @param {string} subscriptionUrl The subscription to check for
   * enabled / disabled state.
   * @returns {boolean}
   */
  isDisabledForSubscription(subscriptionUrl) {
    if (this.disabled === true)
      return true;
    return this.disabledSubscriptions &&
      this.disabledSubscriptions.has(subscriptionUrl);
  }

  /**
   * Sets the disabled state of a filter.
   * @param {string} subscriptionUrl The subscription to enable /
   * disable the filter in.
   * @param {boolean} disabled The new disabled state of the filter.
   */
  setDisabledForSubscription(subscriptionUrl, disabled) {
    delete this.disabled;

    if (!this.disabledSubscriptions && !disabled)
      return;

    if (!this.disabledSubscriptions)
      this.disabledSubscriptions = new Set();

    if (disabled) {
      this.disabledSubscriptions.add(subscriptionUrl);
    }
    else {
      this.disabledSubscriptions.delete(subscriptionUrl);
      if (this.disabledSubscriptions.size === 0)
        delete this.disabledSubscriptions;
    }
  }

  /**
   * Reset the disabled status of this filter to the default of
   * enabled for all subscriptions.
   */
  resetEnabled() {
    delete this.disabled;
    delete this.disabledSubscriptions;
  }

  /**
   * Representation of filter state for the deprecated global enabling
   * and disabling of filters, as well as the `filterState.enabled`
   * events.
   * @type {boolean}
   * @deprecated Prefer {@link isDisabledForSubscription}
   */
  get enabled() {
    return !this.disabled;
  }
  set enabled(value) {
    delete this.disabledSubscriptions;
    this.disabled = !value;
  }
}

/**
 * Checks if two sets of disabled subscription urls contain exactly
 * the same subscription urls.
 * @param {Set<string>} oldDisabledSubscriptions
 * @param {Set<string>} newDisabledSubscriptions
 * @returns {boolean}
 */
function disabledSubscriptionsEquals(oldDisabledSubscriptions,
                                     newDisabledSubscriptions) {
  if (oldDisabledSubscriptions.size !== newDisabledSubscriptions.size)
    return false;

  for (let old of oldDisabledSubscriptions) {
    if (!newDisabledSubscriptions.has(old))
      return false;
  }
  return true;
}

/**
 * Maintains filter state.
 */
exports.FilterState = FilterState;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filterStorage.js":
/*!***********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filterStorage.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_332123__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file `filterStorage` object responsible for managing the user's
 * subscriptions and filters.
 */

const {IO} = __nested_webpack_require_332123__(/*! io */ "./sdk/api/io.js");
const {Prefs} = __nested_webpack_require_332123__(/*! prefs */ "./sdk/api/prefs.js");
const {isActiveFilter} = __nested_webpack_require_332123__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");
const {Subscription, SpecialSubscription} = __nested_webpack_require_332123__(/*! ./subscriptionClasses */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
const {filterNotifier} = __nested_webpack_require_332123__(/*! ./filterNotifier */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
const {INIParser} = __nested_webpack_require_332123__(/*! ./iniParser */ "./node_modules/adblockpluscore/lib/iniParser.js");
const {FilterState} = __nested_webpack_require_332123__(/*! ./filterState */ "./node_modules/adblockpluscore/lib/filterState.js");
const {Synchronizer} = __nested_webpack_require_332123__(/*! ./synchronizer */ "./node_modules/adblockpluscore/lib/synchronizer.js");
const {Features} = __nested_webpack_require_332123__(/*! ./features */ "./node_modules/adblockpluscore/lib/features.js");

/**
 * The Error type returned by filter storage.
 *
 * @property {Object} detail Contains information about the error.
 * @property {string} [detail.text] The text of the filter for
     `filter_not_found`.
 * @property {Array.<string>} [detail.exist] The list of duplicate
 *   filters.
 */
class FilterStorageError extends Error {
  /** Construct a FilterParsingError
   * @constructor
   * @param {string} message The error message.
   * @param {Object} detail The `FilterStorageError` detail.
   */
  constructor(message, detail) {
    super(message);
    this.detail = detail;
  }
}

exports.FilterStorageError = FilterStorageError;

/**
 * @typedef {Object} Stats
 * @property {boolean} exists
 * @property {number} lastModified
 */

/**
 * A cache for all source files and backup stats.
 * @type {Map<string, Stats>}
 * @private
 */
let stats = new Map();

/**
 * An asynchronous guard for multiple backups renmaing operations. It gets
 * reassigned to a new Promise that rename all backups one more time.
 * @type {Promise<void>}
 * @private
 */
let backupQueue = Promise.resolve();

/**
 * Version number of the filter storage file format.
 * @type {number}
 */
const FORMAT_VERSION = 5;

/**
 * Reads the user's filters from disk, manages them in memory, and writes them
 * back to disk.
 */
class FilterStorage {
  /**
   * @typedef FilterStorageOptions
   * @type {object}
   * @property {?module:features.Features} features Enable specific features
   */
  /**
   * Construct a FilterStorage
   *
   * @param {?FilterStorageOptions} options The options to create the storage.
   */
  constructor(options) {
    /**
     * Will be set to `true` after the initial
     * `{@link module:filterStorage.FilterStorage#loadFromDisk loadFromDisk()}`
     * call completes.
     * @type {boolean}
     */
    this.initialized = false;

    /**
     * Will be set to `true` if no `patterns.ini` file exists.
     * @type {boolean}
     */
    this.firstRun = false;

    /** Activated features
     * @type {Features}
     */
    this.features = options ? options.features : Features.DEFAULT;
    Subscription.dnr = (this.features & Features.DNR) != 0;

    /**
     * Map of properties listed in the filter storage file before the sections
     * start. Right now this should be only the format version.
     * @type {Object}
     */
    this.fileProperties = Object.create(null);

    /**
     * Map of subscriptions already on the list, by their URL/identifier.
     * @type {Map.<string,module:subscriptionClasses.Subscription>}
     * @private
     */
    this._knownSubscriptions = new Map();

    /**
     * Map of subscriptions with metadata, by their URL/identifier.
     *
     * It can be used to answer "which subscriptions have metadata?".
     * @type {Map.<string,module:subscriptionClasses.Subscription>}
     * @private
     */
    this._metadataSubscriptions = new Map();

    /**
     * Will be set to `true` if
     * `{@link module:filterStorage.FilterStorage#saveToDisk saveToDisk()}`
     * is running (reentrance protection).
     * @type {boolean}
     * @private
     */
    this._saving = false;

    /**
     * Will be set to `true` if a
     * `{@link module:filterStorage.FilterStorage#saveToDisk saveToDisk()}`
     * call arrives while
     * `{@link module:filterStorage.FilterStorage#saveToDisk saveToDisk()}`
     * is already running (delayed execution).
     * @type {boolean}
     * @private
     */
    this._needsSave = false;

    /**
     * This property is for testing purpose only and it should never be used
     * directly via code.
     * @type {Map<string, Stats>}
     * @private
     */
    this._stats = stats;

    this.synchronizer = new Synchronizer(this);
    this.filterState = new FilterState();
  }

  /**
   * The version number of the `patterns.ini` format used.
   * @type {number}
   */
  get formatVersion() {
    return FORMAT_VERSION;
  }

  /**
   * The file containing the subscriptions.
   * @type {string}
   */
  static get sourceFile() {
    return "patterns.ini";
  }

  /**
   * Yields subscriptions in the storage.
   * @param {?string} [filterText] The filter text for which to look. If
   *   specified, the function yields only those subscriptions that contain the
   *   given filter text. By default the function yields all subscriptions.
   * @yields {module:subscriptionClasses.Subscription}
   */
  *subscriptions(filterText = null) {
    if (filterText == null) {
      yield* this._knownSubscriptions.values();
    }
    else {
      for (let subscription of this._knownSubscriptions.values()) {
        if (subscription.hasFilterText(filterText))
          yield subscription;
      }
    }
  }

  /**
   * Returns the number of subscriptions in the storage.
   * @param {?string} [filterText] The filter text for which to look. If
   *   specified, the function counts only those subscriptions that contain the
   *   given filter text. By default the function counts all subscriptions.
   * @returns {number}
   */
  getSubscriptionCount(filterText = null) {
    if (filterText == null)
      return this._knownSubscriptions.size;

    let count = 0;
    for (let subscription of this._knownSubscriptions.values()) {
      if (subscription.hasFilterText(filterText))
        count++;
    }
    return count;
  }

  /**
   * Finds the filter group that a filter should be added to by default. Will
   * return `null` if this group doesn't exist yet.
   * @param {Filter} filter
   * @returns {?module:subscriptionClasses.SpecialSubscription}
   */
  getGroupForFilter(filter) {
    let generalSubscription = null;
    for (let subscription of this._knownSubscriptions.values()) {
      // We ignore disabled subscriptions and subscriptions
      // without metadata
      if (
        subscription instanceof SpecialSubscription &&
        !subscription.disabled && !subscription.metadata
      ) {
        // Always prefer specialized subscriptions
        if (subscription.isDefaultFor(filter))
          return subscription;

        // If this is a general subscription - store it as fallback
        if (!generalSubscription &&
            (!subscription.defaults || !subscription.defaults.length))
          generalSubscription = subscription;
      }
    }
    return generalSubscription;
  }

  /**
   * Checks whether a given subscription is in the storage.
   * @param {module:subscriptionClasses.Subscription|string} subscription
   *   or the URL of the subscription.
   * @returns {boolean}
   */
  hasSubscription(subscription) {
    if (typeof subscription == "string")
      return this._knownSubscriptions.has(subscription);

    return this._knownSubscriptions.has(subscription.url);
  }

  /**
   * Get the the subscription from the storage.
   * @param {string} subscription The URL of the subscription.
   * @returns {module:subscriptionClasses.Subscription}
   */
  getSubscription(subscription) {
    return this._knownSubscriptions.get(subscription);
  }

  /**
   * Adds a subscription to the storage.
   * @param {module:subscriptionClasses.Subscription} subscription The
   *   subscription to be added.
   */
  addSubscription(subscription) {
    if (this._knownSubscriptions.has(subscription.url))
      return;

    this._knownSubscriptions.set(subscription.url, subscription);

    filterNotifier.emit("subscription.added", subscription);
  }

  /**
   * Removes a subscription from the storage.
   * @param {module:subscriptionClasses.Subscription} subscription The
   *   subscription to be removed.
   */
  removeSubscription(subscription) {
    if (!this._knownSubscriptions.has(subscription.url))
      return;

    this._knownSubscriptions.delete(subscription.url);
    this._metadataSubscriptions.delete(subscription.url);

    // This should be the last remaining reference to the Subscription
    // object.
    Subscription.knownSubscriptions.delete(subscription.url);

    filterNotifier.emit("subscription.removed", subscription);
  }

  /**
   * Replaces the list of filters in a subscription with a new list.
   * @param {module:subscriptionClasses.Subscription} subscription The
   *   subscription to be updated.
   * @param {Array.<string>} filterText The new filter text.
   */
  updateSubscriptionFilters(subscription, filterText) {
    filterNotifier.emit(
      "subscription.updated",
      subscription,
      subscription.updateFilterText(filterText)
    );
  }

  /**
   * Check the filters pass and return the list of the filters that exist.
   *
   * @param {Array.<Filter>} filters The filters to check.
   * @return {Array.<Filter>} The list of filters that exists. An empty
   *   list mean that none do exist.
   */
  filtersExist(filters) {
    let exist = [];

    for (let filter of filters) {
      for (let currentSubscription of this._knownSubscriptions.values()) {
        if (currentSubscription instanceof SpecialSubscription &&
            !currentSubscription.disabled &&
            currentSubscription.hasFilterText(filter.text))
          exist.push(filter);
      }
    }

    return exist;
  }

  /**
   * Adds user-defined filters to the storage with metadata.
   *
   * @async
   * @param {Filter|Array<Filter>} filters Filter(s) to add. If the list
   *   contains duplicate entries, they'll be skipped.
   * @param {Object} metadata The metadata block.
   *
   * @return {Promise<module:subscriptionClasses.SpecialSubscription>} the
   *   subscription the filter is in, or throw an error if any of the filter
   *   is already present in a `SpecialSubscription`.
   */
  async addFiltersWithMetadata(filters, metadata) {
    let list = Array.isArray(filters) ? filters : [filters];

    let exist = this.filtersExist(list);
    if (exist.length != 0)
      throw new FilterStorageError("storage_duplicate_filters", {exist});

    let subscription = null;

    for (let filter of list) {
      if (!subscription)
        subscription = SpecialSubscription.createForFilter(filter);
      // We make sure we don't have a duplicate already from `filters`.
      else if (!subscription.hasFilterText(filter.text))
        subscription.addFilter(filter);
    }

    this._metadataSubscriptions.set(subscription.url, subscription);
    this.addSubscription(subscription);

    subscription.metadata = metadata;

    return subscription;
  }

  /**
   * Get the metadata for a filter.
   *
   * @async
   * @param {string} text The filter text.
   * @return {Promise<Object>} The metadata if any found.
   *
   * This function will iterate through all the subscriptions with metadata
   * to find a `SpecialSubscription` that contains the filter text.
   */
  async getMetadataForFilter(text) {
    for (let currentSubscription of this._metadataSubscriptions.values()) {
      if (currentSubscription.hasFilterText(text))
        return currentSubscription.metadata;
    }

    throw new FilterStorageError("filter_not_found", {text});
  }

  /**
   * Set the metadata for a filter that already has metadata.
   *
   * A filter can have metadata only if it was added using
   * `addFiltersWithMetadata()`. It is currently not possible to add metadata
   * to an existing custom filter that was added with `addFilter()`. In that
   * case, the function will return a `filter_not_found` error.
   *
   * @async
   * @param {string} text The filter text.
   * @param {Object} metadata The metadata.
   *
   * @return {Promise<module:subscriptionClasses.SpecialSubscription>} The
   *   subscription whose metadata was changed.
   */
  async setMetadataForFilter(text, metadata) {
    for (let currentSubscription of this._metadataSubscriptions.values()) {
      if (currentSubscription.hasFilterText(text)) {
        currentSubscription.metadata = metadata;
        return currentSubscription;
      }
    }

    throw new FilterStorageError("filter_not_found", {text});
  }

  /**
   * Adds a user-defined filter to the storage.
   *
   * @async
   * @param {Filter} filter
   * @param {?module:subscriptionClasses.SpecialSubscription} [subscription]
   *   The subscription that the filter should be added to.
   * @param {number} [position] The position within the subscription at which
   *   the filter should be added. If not specified, the filter is added at the
   *   end of the subscription.
   *
   * @return {Promise<module:subscriptionClasses.SpecialSubscription>} The
   *   subscription the filter is in. Either existing or added.
   */
  async addFilter(filter, subscription, position) {
    if (!subscription) {
      for (let currentSubscription of this._knownSubscriptions.values()) {
        if (currentSubscription instanceof SpecialSubscription &&
            !currentSubscription.disabled &&
            currentSubscription.hasFilterText(filter.text)) {
          throw new FilterStorageError("storage_duplicate_filters",
                                       {exist: [filter]});  // No need to add
        }
      }
      subscription = this.getGroupForFilter(filter);
    }
    if (!subscription) {
      // No group for this filter exists, create one
      subscription = SpecialSubscription.createForFilter(filter);
      this.addSubscription(subscription);
      return subscription;
    }

    if (typeof position == "undefined")
      position = subscription.filterCount;

    subscription.insertFilterAt(filter, position);
    filterNotifier.emit("filter.added", filter, subscription, position);
    return subscription;
  }

  /**
   * Removes a user-defined filter from the storage.
   * @param {module:filterClasses.Filter} filter
   * @param {?module:subscriptionClasses.SpecialSubscription} [subscription]
   *   The subscription that the filter should be removed from. If not
   *   specified, the filter will be removed from all subscriptions.
   * @param {number} [position] The position within the subscription at which
   *   the filter should be removed. If not specified, all instances of the
   *   filter will be removed.
   */
  removeFilter(filter, subscription, position) {
    let subscriptions = (
      subscription ? [subscription] : this._knownSubscriptions.values()
    );
    for (let currentSubscription of subscriptions) {
      if (currentSubscription instanceof SpecialSubscription &&
          (currentSubscription == subscription ||
           currentSubscription.hasFilterText(filter.text))) {
        let positions = [];
        if (typeof position == "undefined") {
          let index = -1;
          do {
            index = currentSubscription.findFilterIndex(filter, index + 1);
            if (index >= 0)
              positions.push(index);
          } while (index >= 0);
        }
        else {
          positions.push(position);
        }

        for (let j = positions.length - 1; j >= 0; j--) {
          let currentPosition = positions[j];
          let currentFilterText =
            currentSubscription.filterTextAt(currentPosition);
          if (currentFilterText && currentFilterText == filter.text) {
            currentSubscription.deleteFilterAt(currentPosition);
            filterNotifier.emit(
              "filter.removed", filter, currentSubscription, currentPosition
            );
          }
        }
      }
    }
  }

  /**
   * Moves a user-defined filter to a new position.
   * @param {module:filterClasses.Filter} filter
   * @param {module:subscriptionClasses.SpecialSubscription} subscription The
   *   subscription where the filter is located.
   * @param {number} oldPosition The current position of the filter.
   * @param {number} newPosition The new position of the filter.
   */
  moveFilter(filter, subscription, oldPosition, newPosition) {
    if (!(subscription instanceof SpecialSubscription))
      return;

    let currentFilterText = subscription.filterTextAt(oldPosition);
    if (!currentFilterText || currentFilterText != filter.text)
      return;

    newPosition = Math.min(Math.max(newPosition, 0),
                           subscription.filterCount - 1);
    if (oldPosition == newPosition)
      return;

    subscription.deleteFilterAt(oldPosition);
    subscription.insertFilterAt(filter, newPosition);
    filterNotifier.emit(
      "filter.moved", filter, subscription, oldPosition, newPosition
    );
  }

  /**
   * Increases the hit count for a filter by one.
   * @param {Filter} filter
   */
  increaseHitCount(filter) {
    if (!Prefs.savestats || !isActiveFilter(filter))
      return;

    this.filterState.registerHit(filter.text);
  }

  /**
   * Resets hit count for some filters.
   * @param {?Array.<Filter>} [filters] The filters to be reset. If not
   *   specified, all filters will be reset.
   */
  resetHitCounts(filters) {
    if (filters) {
      for (let filter of filters)
        this.filterState.resetHits(filter.text);
    }
    else {
      for (let text of this.filterState.map.keys())
        this.filterState.resetHits(text);
    }
  }

  /**
   * @callback TextSink
   * @param {string?} line
   */

  /**
   * Allows importing previously serialized filter data.
   * @param {boolean} silent If `true`, no "load" notification will be sent
   *   out.
   * @returns {TextSink} The function to be called for each line of data.
   *   Calling it with `null` as the argument finalizes the import and replaces
   *   existing data. No changes will be applied before finalization, so import
   *   can be "aborted" by forgetting this callback.
   * @package
   */
  importData(silent) {
    let parser = new INIParser(this.filterState);
    return line => {
      parser.process(line);
      if (line === null) {
        let knownSubscriptions = new Map();
        let metadataSubscriptions = new Map();
        for (let subscription of parser.subscriptions) {
          // Convert to the new terminology when loading.
          if (Array.isArray(subscription.defaults)) {
            subscription.defaults.forEach((type, i, arr) => {
              if (type == "whitelist")
                arr[i] = "allowing";
            });
          }
          knownSubscriptions.set(subscription.url, subscription);
          if (subscription.metadata)
            metadataSubscriptions.set(subscription.url, subscription);
        }

        this.fileProperties = parser.fileProperties;
        this._knownSubscriptions = knownSubscriptions;
        this._metadataSubscriptions = metadataSubscriptions;

        if (!silent)
          filterNotifier.emit("load");
      }
    };
  }

  /**
   * Loads all subscriptions from disk.
   * @returns {Promise} A promise resolved or rejected when loading is complete.
   * @package
   */
  async loadFromDisk() {
    let tryBackup = async backupIndex => {
      try {
        await this.restoreBackup(backupIndex, true);
      }
      catch (error) {
        // Give up
      }
    };

    try {
      let statData = await statFile(FilterStorage.sourceFile);

      if (!statData.exists) {
        this.firstRun = true;
        return;
      }

      let parser = this.importData(true);
      await IO.readFromFile(FilterStorage.sourceFile, parser);
      parser(null);
    }
    catch (error) {
      console.warn(error);
      await tryBackup(1);
    }

    this.initialized = true;
    filterNotifier.emit("load");
  }

  /**
   * Constructs the file name for a `patterns.ini` backup.
   * @param {number} backupIndex Number of the backup file (1 being the most
   *   recent).
   * @returns {string} Backup file name.
   * @package
   */
  static getBackupName(backupIndex) {
    let [name, extension] = FilterStorage.sourceFile.split(".", 2);
    return (name + "-backup" + backupIndex + "." + extension);
  }

  /**
   * Restores an automatically created backup.
   * @param {number} backupIndex Number of the backup to restore (1 being the
   *   most recent).
   * @param {boolean} silent If `true`, no "load" notification will be sent
   *   out.
   * @returns {Promise} A promise resolved or rejected when restoration is
   *   complete.
   * @package
   */
  async restoreBackup(backupIndex, silent) {
    let backupFile = FilterStorage.getBackupName(backupIndex);
    let parser = this.importData(silent);
    await IO.readFromFile(backupFile, parser);
    parser(null);
    return this.saveToDisk();
  }

  /**
   * Generator serializing filter data and yielding it line by line.
   * @yields {string}
   */
  *exportData() {
    // Do not persist external subscriptions
    let subscriptions = [];
    for (let subscription of this._knownSubscriptions.values()) {
      if (!(subscription instanceof SpecialSubscription &&
            subscription.filterCount == 0))
        subscriptions.push(subscription);
    }

    yield "# Adblock Plus preferences";
    yield "version=" + this.formatVersion;

    let saved = new Set();

    // Save subscriptions
    for (let subscription of subscriptions) {
      yield* subscription.serialize();
      yield* subscription.serializeFilters();
    }

    // Save filter data
    for (let subscription of subscriptions) {
      for (let text of subscription.filterText()) {
        if (!saved.has(text)) {
          yield* this.filterState.serialize(text);
          saved.add(text);
        }
      }
    }
  }

  /**
   * Saves all subscriptions back to disk.
   * @returns {Promise} A promise resolved or rejected when saving is complete.
   * @package
   */
  async saveToDisk() {
    if (this._saving) {
      this._needsSave = true;
      return;
    }

    this._saving = true;

    try {
      let {patternsbackups} = Prefs;
      let isBackupRequired = async() => {
        // First check whether we need to create a backup
        if (patternsbackups <= 0)
          return false;

        let statData = await statFile(FilterStorage.sourceFile);
        if (!statData.exists)
          return false;

        let backupStatData = await statFile(FilterStorage.getBackupName(1));
        if (backupStatData.exists &&
            (Date.now() - backupStatData.lastModified) / 3600000 <
              Prefs.patternsbackupinterval)
          return false;

        return true;
      };

      if (await isBackupRequired()) {
        try {
          // if patternsbackups is 1 just create it, otherwise create a
          // backup-0 that will be shifted among others later on
          let i = patternsbackups > 1 ? 0 : 1;
          await renameFile(
            FilterStorage.sourceFile, FilterStorage.getBackupName(i)
          );

          // if there is more than a backup, backup-0 up to backup-X need to be
          // renamed but without blocking this callback
          if (patternsbackups > 1) {
            // keep queueing backups as these come, considering backup1 and
            // backup 0 are always safe thanks to the this._saving flag
            backupQueue = backupQueue.then(() => new Promise(resolve => {
              let renameAll = async index => {
                if (index > 0) {
                  try {
                    let source = FilterStorage.getBackupName(index - 1);
                    let dest = FilterStorage.getBackupName(index);
                    await renameFile(source, dest);
                  }
                  catch (error) {
                    // Expected error, backup file doesn't exist.
                  }
                  renameAll(index - 1);
                }
                else {
                  resolve();
                }
              };
              renameAll(patternsbackups);
            }));
          }
        }
        catch (error) {
          // This is actually an unexpected error that could happen only if
          // the disk had issues in renaming the source file.
          console.warn(error);
        }
      }
    }
    catch (error) {
      // Errors during backup creation shouldn't prevent writing filters.
      console.warn(error);
    }

    try {
      await IO.writeToFile(FilterStorage.sourceFile, this.exportData());
      stats.set(
        FilterStorage.sourceFile, {exists: true, lastModified: Date.now()}
      );
      filterNotifier.emit("save");
    }
    catch (error) {
      // If saving failed, report error but continue - we still have to process
      // flags.
      console.warn(error);
      stats.delete(FilterStorage.sourceFile);
    }

    this._saving = false;
    if (this._needsSave) {
      this._needsSave = false;
      this.saveToDisk();
    }
  }

  /**
   * @typedef {Object} FileInfo
   * @property {number} index
   * @property {number} lastModified
   */

  /**
   * Returns a promise resolving in a list of existing backup files.
   * @returns {Promise.<Array.<FileInfo>>}
   * @package
   */
  async getBackupFiles() {
    let backups = [];

    let checkBackupFile = async index => {
      try {
        let statData = await statFile(FilterStorage.getBackupName(index));
        if (!statData.exists)
          return backups;

        backups.push({
          index,
          lastModified: statData.lastModified
        });

        return checkBackupFile(index + 1);
      }
      catch (error) {
        // Something went wrong, return whatever data we got so far.
        console.warn(error);
        return backups;
      }
    };

    return checkBackupFile(1);
  }
}

exports.FilterStorage = FilterStorage;

/**
 * Given a path, return its stats, if known, or a Stats object with properties
 * exists = false and lastModified = 0.
 * @param {string} path
 * @returns {Stats}
 */
async function statFile(path) {
  let known = stats.get(path);
  if (known)
    return known;

  try {
    known = await IO.statFile(path);
  }
  catch (error) {
    known = {exists: false, lastModified: 0};
  }
  stats.set(path, known);
  return known;
}

/**
 * Given a source path and a destination path, tries to rename the source and,
 * if it succeed, remove the source from the stats and set stats for dest.
 * @param {string} source
 * @param {string} dest
 */
async function renameFile(source, dest) {
  await IO.renameFile(source, dest);
  stats.delete(source);
  stats.set(dest, {exists: true, lastModified: Date.now()});
}


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filters/index.js":
/*!***********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filters/index.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_360267__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



/** @module */

const {contentTypes, RESOURCE_TYPES} = __nested_webpack_require_360267__(/*! ../contentTypes */ "./node_modules/adblockpluscore/lib/contentTypes.js");

/**
 * Regular expression that content filters should match
 * @type {RegExp}
 */
const CONTENT_FILTER = /^([^/|@"!]*?)#([@?$])?#(.+)$/;
exports.CONTENT_FILTER = CONTENT_FILTER;

/**
 * Regular expression that options on a RegExp filter should match
 * @type {RegExp}
 */
const FILTER_OPTIONS = /\$(~?[\w-]+(?:=[^,]*)?(?:,~?[\w-]+(?:=[^,]*)?)*)$/;
exports.FILTER_OPTIONS = FILTER_OPTIONS;

// used to reduce possible short filters damage
const MIN_GENERIC_URL_FILTER_PATTERN_LENGTH = 4;

/**
 * Regular expression that matches an invalid Content Security Policy
 * @type {RegExp}
 */
const INVALID_CSP = /(;|^) ?(base-uri|referrer|report-to|report-uri|upgrade-insecure-requests)\b/i;
exports.INVALID_CSP = INVALID_CSP;

/**
 * The Error type returned by parse.
 *
 * For example `filter_unknown_option` will have `option`.
 * @property {Object} detail Contains information about the error.
 * @property {string} [detail.option] The option for `filter_unknown_option`.
 * @property {string} [detail.regexp] The regexp for `filter_invalid_regexp`.
 * @property {string} detail.text The text of the rejected filter.
 */
class FilterParsingError extends Error {
  /** Construct a FilterParsingError
   * @constructor
   * @param {string} message The error message.
   * @param {Object} detail The FilterParsingError detail. Contains at
   *   least `text`.
   */
  constructor(message, detail) {
    super(message);
    this.detail = detail;
  }
}

exports.FilterParsingError = FilterParsingError;

/**
 * @typedef {Object} ParsedFilter
 * @property {bool} blocking Whether it's a blocking filter or not.
 * @property {string} text The filter text.
 * @property {string} regexpSource The source of the matching RegExp.
 * @property {number} contentType The
 *   {@link module:contentTypes.contentTypes content types} for the filter.
 * @property {bool?} matchCase If the filter is case sensitive.
 * @property {Array<string>?} domains The domains to match
 *   (`$domains` option).
 * @property {Array<string>?} sitekeys The sitekeys to match.
 * @property {object?} headers The headers filtering.
 * @property {string?} rewrite The URL for to rewrite to.
 * @property {string?} csp The CSP directive.
 */

/**
 * Parse the filter text representation into a structure.
 *
 * This is meant to be called by
 * {module:filterClasses.URLFilter.fromText}
 *
 * @param {string} text the filter normalized text. Call normalize()
 *   on the text prior to this, unless it is already normalized.
 * @return {ParsedFilter|FilterParsingError}
 *   The parsed filter, or a FilterParsingError.
 */
exports.parse = function parse(text) {
  // exclude empty text, comments, and content filters
  if (text.length < 1)
    return new FilterParsingError("filter_empty", {text});

  if (text[0] === "!" || CONTENT_FILTER.test(text))
    return new FilterParsingError("invalid", {text});

  // parse like an ABP URLFilter
  let blocking = true;
  let origText = text;
  if (text.startsWith("@@")) {
    blocking = false;
    text = text.substring(2);
  }

  let contentType = null;
  let matchCase = null;
  let domains = null;
  let sitekeys = null;
  let thirdParty = null;
  let csp = null;
  let rewrite = null;
  let header = null;
  let options;
  let match = text.includes("$") ? FILTER_OPTIONS.exec(text) : null;
  if (match) {
    text = match.input.substring(0, match.index);

    options = match[1].split(",");
    let cspSet = false;
    let headerSet = false;

    for (let option of options) {
      let value = null;
      let separatorIndex = option.indexOf("=");
      if (separatorIndex >= 0) {
        value = option.substring(separatorIndex + 1);
        option = option.substring(0, separatorIndex);
      }

      let inverse = option[0] == "~";
      if (inverse)
        option = option.substring(1);

      let optionUpperCase = option.toUpperCase();
      let type = contentTypes[optionUpperCase.replace(/-/, "_")];
      if (type) {
        if (inverse) {
          if (contentType == null)
            contentType = RESOURCE_TYPES;
          contentType &= ~type;
        }
        else if (type === contentTypes.CSP) {
          if (blocking && !value) {
            return new FilterParsingError("filter_invalid_csp",
                                          {text: origText});
          }
          cspSet = true;
          csp = value;
        }
        else if (type === contentTypes.HEADER) {
          if (blocking && !value) {
            return new FilterParsingError("filter_invalid_header",
                                          {text: origText});
          }
          headerSet = true;
          if (value) {
            let headerRaw = value.replace(/([^\\])\\x2c/g, "$1,")
                .replace(/\\\\x2c/g, "\\x2c");
            let equal = headerRaw.indexOf("=");
            if (equal == headerRaw.length - 1) {
              // This case is "key=" with no value
              header = {
                name: headerRaw.substring(0, equal).toLowerCase()
              };
            }
            else if (equal >= 0) {
              header = {
                name: headerRaw.substring(0, equal).toLowerCase(),
                value: headerRaw.substring(equal + 1)
              };
            }
            else {
              header = {
                name: headerRaw.toLowerCase()
              };
            }

            if (header.name.length == 0) {
              return new FilterParsingError("filter_invalid_header",
                                            {text: origText});
            }
            if (/^\/[\s\S]*\/$/.test(header.value)) {
              return new FilterParsingError("filter_invalid_header",
                                            {text: origText});
            }
          }
        }
        else {
          contentType |= type;
        }
      }
      else {
        switch (optionUpperCase) {
          case "MATCH-CASE":
            matchCase = !inverse;
            break;
          case "DOMAIN":
            if (!value) {
              return new FilterParsingError("filter_unknown_option",
                                            {option, text: origText});
            }
            domains = value;
            break;
          case "THIRD-PARTY":
            thirdParty = !inverse;
            break;
          case "SITEKEY":
            if (!value) {
              return new FilterParsingError("filter_unknown_option",
                                            {option, text: origText});
            }
            // Sitekeys are case-sensitive, they shouldn't be uppercased.
            sitekeys = value;
            break;
          case "REWRITE":
            if (value == null) {
              return new FilterParsingError("filter_unknown_option",
                                            {option, text: origText});
            }
            if (!value.startsWith("abp-resource:")) {
              return new FilterParsingError("filter_invalid_rewrite",
                                            {text: origText});
            }
            rewrite = value.substring("abp-resource:".length);
            break;
          default:
            return new FilterParsingError("filter_unknown_option",
                                          {option, text: origText});
        }
      }
    }
    if (cspSet || headerSet) {
      if (contentType == null)
        contentType = RESOURCE_TYPES;
      if (cspSet)
        contentType |= contentTypes.CSP;
      if (headerSet)
        contentType |= contentTypes.HEADER;
    }
  }

  let isGeneric = !sitekeys && !domains;
  if (isGeneric) {
    let minTextLength = MIN_GENERIC_URL_FILTER_PATTERN_LENGTH;
    let {length} = text;
    if (length > 0 && text[0] === "|") {
      minTextLength++;
      if (length > 1 && text[1] === "|")
        minTextLength++;
    }
    if (length < minTextLength && !text.includes("*")) {
      return new FilterParsingError("filter_url_not_specific_enough",
                                    {text: origText});
    }
  }
  // We expect filters to use Punycode for domains these days, so let's just
  // skip filters which don't. See #6647.
  else if (domains && /[^\x00-\x7F]/.test(domains)) {
    return new FilterParsingError("filter_invalid_domain", {text: origText});
  }

  if (blocking) {
    if (csp && INVALID_CSP.test(csp))
      return new FilterParsingError("filter_invalid_csp", {text: origText});

    if (rewrite) {
      if (text.startsWith("||")) {
        if (!domains && thirdParty != false) {
          return new FilterParsingError("filter_invalid_rewrite",
                                        {text: origText});
        }
      }
      else if (text.startsWith("*")) {
        if (!domains) {
          return new FilterParsingError("filter_invalid_rewrite",
                                        {text: origText});
        }
      }
      else {
        return new FilterParsingError("filter_invalid_rewrite",
                                      {text: origText});
      }
    }
  }

  return {
    blocking,
    text: origText,
    regexpSource: text,
    contentType,
    matchCase,
    domains,
    thirdParty,
    sitekeys,
    header,
    rewrite,
    csp
  };
};

/**
 * Removes unnecessary whitespaces from filter text, will only return null if
 * the input parameter is null.
 *
 * @param {string} text
 * @param {boolean?} dontSanitize avoid expensive operations on text.
 * @return {string}
 */
exports.normalize = function(text, dontSanitize = false) {
  if (text === "")
    return text;

  // Remove line breaks, tabs etc
  text = text.replace(/[^\S ]+/g, "");

  if (dontSanitize)
    return text.trim();

  if (!text.includes(" "))
    return text;

  // Don't remove spaces inside comments
  if (/^ *!/.test(text))
    return text.trim();

  // Special treatment for content filters, right side is allowed to contain
  // spaces
  if (CONTENT_FILTER.test(text)) {
    let [, domains, separator, body] = /^(.*?)(#[@?$]?#?)(.*)$/.exec(text);
    return domains.replace(/ +/g, "") + separator + body.trim();
  }

  // For most regexp filters we strip all spaces, but $csp filter options
  // are allowed to contain single (non trailing) spaces.
  let strippedText = text.replace(/ +/g, "");
  if (!strippedText.includes("$") || !/\b(csp|header)=/i.test(strippedText))
    return strippedText;

  let optionsMatch = FILTER_OPTIONS.exec(strippedText);
  if (!optionsMatch)
    return strippedText;

  // For $csp filters we must first separate out the options part of the
  // text, being careful to preserve its spaces.
  let beforeOptions = strippedText.substring(0, optionsMatch.index);
  let strippedDollarIndex = -1;
  let dollarIndex = -1;
  do {
    strippedDollarIndex = beforeOptions.indexOf("$", strippedDollarIndex + 1);
    dollarIndex = text.indexOf("$", dollarIndex + 1);
  }
  while (strippedDollarIndex != -1);
  let optionsText = text.substring(dollarIndex + 1);

  // Then we can normalize spaces in the options part safely
  let options = optionsText.split(",");
  for (let i = 0; i < options.length; i++) {
    let option = options[i];
    let optionMatch = /^ *(c *s *p|h *e *a *d *e *r) *=/i.exec(option);
    if (optionMatch) {
      options[i] = optionMatch[0].replace(/ +/g, "") +
                   option.substring(optionMatch[0].length).trim().replace(/ +/g, " ");
    }
    else {
      options[i] = option.replace(/ +/g, "");
    }
  }

  return beforeOptions + "$" + options.join();
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filters/lists.js":
/*!***********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filters/lists.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



/** @module */

/**
 * Given some text containing a filter list, parse each line and return all
 * details.
 * @param {string} filters The filter list file/text to parse.
 * @param {boolean} exactLineNumbers Preserve empty lines.
 * @returns {Object.<error?, lines?, params?, minVersion?>} All parsed details,
 *  if available. `lines` will contain the header in the first line.
 */
function parseFilterList(filters, exactLineNumbers) {
  let lines = filters.split(exactLineNumbers ? /\r?\n{1}?/ : /[\r\n]+/);
  // The filter list always start with a header, at minimum `[Adblock]`.
  let headerMatch = /\[Adblock(?:\s*Plus\s*([\d.]+)?)?\]/i.exec(lines[0]);

  if (!headerMatch)
    return {error: "synchronize_invalid_data"};

  let minVersion = headerMatch[1];

  let params = {
    redirect: null,
    homepage: null,
    title: null,
    version: null,
    expires: null,
    abtest: null
  };

  for (let {hasOwnProperty} = Object.prototype, i = 1; i < lines.length; i++) {
    let match = /^\s*!\s*(.*?)\s*:\s*(.*)/.exec(lines[i]);
    if (!match)
      break;

    let keyword = match[1].toLowerCase();
    if (hasOwnProperty.call(params, keyword)) {
      params[keyword] = match[2];
      lines.splice(i--, 1);
    }
  }

  return {lines, params, minVersion};
}

exports.parseFilterList = parseFilterList;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/filtersByDomain.js":
/*!*************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/filtersByDomain.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * Map to be used instead when a filter has a blank `domains` property.
 * @type {Map.<string, boolean>}
 */
let defaultDomains = new Map([["", true]]);

let FilterMap =
/**
 * A `FilterMap` object contains a set of filters, each mapped to a boolean
 * value indicating whether the filter should be applied.
 *
 * It is used by
 * `{@link module:filtersByDomain.FiltersByDomain FiltersByDomain}`.
 *
 * @package
 */
exports.FilterMap = class FilterMap extends Map {};

/**
 * A `FiltersByDomain` object contains a set of domains, each mapped to a set
 * of filters along with a boolean value for each filter indicating whether the
 * filter should be applied to the domain.
 *
 * @package
 */
exports.FiltersByDomain = class FiltersByDomain extends Map {
  /**
   * Adds a filter and all of its domains to the object.
   *
   * @param {module:filterClasses.ActiveFilter} filter The filter.
   * @param {Map.<string, boolean>} [domains] The filter's domains. If not
   *   given, the `{@link module:filterClasses.ActiveFilter#domains domains}`
   *   property of `filter` is used.
   */
  add(filter, domains = filter.domains) {
    for (let [domain, include] of domains || defaultDomains) {
      if (!include && domain == "")
        continue;

      let map = this.get(domain);
      if (!map) {
        this.set(domain, include ? filter : new FilterMap([[filter, false]]));
      }
      else if (map.size == 1 && !(map instanceof FilterMap)) {
        if (filter != map)
          this.set(domain, new FilterMap([[map, true], [filter, include]]));
      }
      else {
        map.set(filter, include);
      }
    }
  }

  /**
   * Removes a filter and all of its domains from the object.
   *
   * @param {module:filterClasses.ActiveFilter} filter The filter.
   * @param {Map.<string, boolean>} [domains] The filter's domains. If not
   *   given, the `{@link module:filterClasses.ActiveFilter#domains domains}`
   *   property of `filter` is used.
   */
  remove(filter, domains = filter.domains) {
    for (let domain of (domains || defaultDomains).keys()) {
      let map = this.get(domain);
      if (map) {
        if (map.size > 1 || map instanceof FilterMap) {
          map.delete(filter);

          if (map.size == 0) {
            this.delete(domain);
          }
          else if (map.size == 1) {
            for (let [lastFilter, include] of map.entries()) {
              // Reduce Map { "example.com" => Map { filter => true } } to
              // Map { "example.com" => filter }
              if (include)
                this.set(domain, lastFilter);

              break;
            }
          }
        }
        else if (filter == map) {
          this.delete(domain);
        }
      }
    }
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/index.js":
/*!***************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/index.js ***!
  \***************************************************/
/***/ ((module, __unused_webpack_exports, __nested_webpack_require_379014__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * @module
 *
 * @borrows module:contentTypes.contentTypes as contentTypes
 * @borrows module:features.Features as Features
 * @borrows module:filterEngine.FilterEngine as FilterEngine
 * @borrows module:synchronizer.Synchronizer as Synchronizer
 * @borrows module:url.parseURL as parseURL
 */



const {contentTypes} = __nested_webpack_require_379014__(/*! ./contentTypes */ "./node_modules/adblockpluscore/lib/contentTypes.js");
const {Features} = __nested_webpack_require_379014__(/*! ./features */ "./node_modules/adblockpluscore/lib/features.js");
const {FilterEngine} = __nested_webpack_require_379014__(/*! ./filterEngine */ "./node_modules/adblockpluscore/lib/filterEngine.js");
const {Synchronizer} = __nested_webpack_require_379014__(/*! ./synchronizer */ "./node_modules/adblockpluscore/lib/synchronizer.js");
const {parseURL} = __nested_webpack_require_379014__(/*! ./url */ "./node_modules/adblockpluscore/lib/url.js");

module.exports = {
  contentTypes,
  Features,
  FilterEngine,
  Synchronizer,
  parseURL
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/iniParser.js":
/*!*******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/iniParser.js ***!
  \*******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_381007__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file INI parsing.
 */

const {isActiveFilter, Filter} = __nested_webpack_require_381007__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");
const {FilterState} = __nested_webpack_require_381007__(/*! ./filterState */ "./node_modules/adblockpluscore/lib/filterState.js");
const {Subscription} = __nested_webpack_require_381007__(/*! ./subscriptionClasses */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");

/**
 * Parses filter data.
 * @package
 */
exports.INIParser = class INIParser {
  /** @param {FilterState} filterState the filter state */
  constructor(filterState) {
    if (!(filterState instanceof FilterState))
      throw new Error("filterState must be a FilterState object");

    /**
     * Properties of the filter data.
     * @type {Object}
     */
    this.fileProperties = {};

    /**
     * The list of subscriptions in the filter data.
     * @type {Array.<module:subscriptionClasses.Subscription>}
     */
    this.subscriptions = [];

    /** @type {module:filterState.FilterState} */
    this.filterState = filterState;

    this._wantObj = true;
    this._curObj = this.fileProperties;
    this._curSection = null;
  }

  /**
   * Processes a line of filter data.
   *
   * @param {string?} line The line of filter data to process. This may be
   *   `null`, which indicates the end of the filter data.
   */
  process(line) {
    let match = null;
    if (this._wantObj === true && (match = /^(\w+)=(.*)$/.exec(line))) {
      this._curObj[match[1]] = match[2];
    }
    else if (this._wantObj === true && (match = /^(\w+)\[]=(.*)$/.exec(line))) {
      if (!this._curObj[match[1]])
        this._curObj[match[1]] = [];
      this._curObj[match[1]].push(match[2]);
    }
    else if (line === null || (match = /^\s*\[(.+)\]\s*$/.exec(line))) {
      if (this._curObj) {
        // Process current object before going to next section
        switch (this._curSection) {
          case "filter":
            if ("text" in this._curObj) {
              let {text} = this._curObj;
              if (isActiveFilter(Filter.fromText(text)))
                this.filterState.fromObject(text, this._curObj);
            }
            break;

          case "subscription":
            let subscription = Subscription.fromObject(this._curObj);
            if (subscription)
              this.subscriptions.push(subscription);
            break;

          case "subscription filters":
            if (this.subscriptions.length) {
              let currentSubscription = this.subscriptions[
              this.subscriptions.length - 1
              ];
              currentSubscription.updateFilterText(this._curObj);
            }
            break;
        }
      }

      if (line === null)
        return;

      this._curSection = match[1].toLowerCase();
      switch (this._curSection) {
        case "filter":
        case "subscription":
          this._wantObj = true;
          this._curObj = {};
          break;
        case "subscription filters":
          this._wantObj = false;
          this._curObj = [];
          break;
        default:
          this._wantObj = null;
          this._curObj = null;
      }
    }
    else if (this._wantObj === false && line) {
      this._curObj.push(line.replace(/\\\[/g, "["));
    }
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/jsbn.js":
/*!**************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/jsbn.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, exports) => {

/*
 * Copyright (c) 2003-2005  Tom Wu
 * All Rights Reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
 *
 * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
 * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER
 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF
 * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT
 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 *
 * In addition, the following condition applies:
 *
 * All redistributions must retain an intact copy of this copyright notice
 * and disclaimer.
 */

// Basic JavaScript BN library - subset useful for RSA encryption.

// Modified by eyeo GmbH to better support going to and from JS binary
// strings (base 256) and our particular use case.

// Bits per digit
var dbits;

// JavaScript engine analysis
var canary = 0xdeadbeefcafe;
var j_lm = ((canary&0xffffff)==0xefcafe);

// (public) Constructor
let BigInteger = exports.BigInteger = function BigInteger(a,b,c) {
  if(a != null)
    if("number" == typeof a) this.fromNumber(a,b,c);
    else if(b == null && "string" != typeof a) this.fromString(a,256);
    else this.fromString(a,b);
};

// return new, unset BigInteger
function nbi() { return new BigInteger(null); }

// am: Compute w_j += (x*this_i), propagate carries,
// c is initial carry, returns final carry.
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
// We need to select the fastest one that works in this environment.

// am1: use a single mult and divide to get the high bits,
// max digit bits should be 26 because
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
function am1(i,x,w,j,c,n) {
  while(--n >= 0) {
    var v = x*this[i++]+w[j]+c;
    c = Math.floor(v/0x4000000);
    w[j++] = v&0x3ffffff;
  }
  return c;
}
// am2 avoids a big mult-and-extract completely.
// Max digit bits should be <= 30 because we do bitwise ops
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
function am2(i,x,w,j,c,n) {
  var xl = x&0x7fff, xh = x>>15;
  while(--n >= 0) {
    var l = this[i]&0x7fff;
    var h = this[i++]>>15;
    var m = xh*l+h*xl;
    l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
    c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
    w[j++] = l&0x3fffffff;
  }
  return c;
}
// Alternately, set max digit bits to 28 since some
// browsers slow down when dealing with 32-bit numbers.
function am3(i,x,w,j,c,n) {
  var xl = x&0x3fff, xh = x>>14;
  while(--n >= 0) {
    var l = this[i]&0x3fff;
    var h = this[i++]>>14;
    var m = xh*l+h*xl;
    l = xl*l+((m&0x3fff)<<14)+w[j]+c;
    c = (l>>28)+(m>>14)+xh*h;
    w[j++] = l&0xfffffff;
  }
  return c;
}
if(j_lm && (typeof navigator != "undefined" && navigator.appName == "Microsoft Internet Explorer")) { /** MODIFIED **/
  BigInteger.prototype.am = am2;
  dbits = 30;
}
else if(j_lm && (typeof navigator != "undefined" && navigator.appName != "Netscape")) { /** MODIFIED **/
  BigInteger.prototype.am = am1;
  dbits = 26;
}
else { // Mozilla/Netscape seems to prefer am3
  BigInteger.prototype.am = am3;
  dbits = 28;
}

BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1<<dbits)-1);
BigInteger.prototype.DV = (1<<dbits);

var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2,BI_FP);
BigInteger.prototype.F1 = BI_FP-dbits;
BigInteger.prototype.F2 = 2*dbits-BI_FP;

// Digit conversions
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr,vv;
rr = "0".charCodeAt(0);
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
rr = "a".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
rr = "A".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;

function int2char(n) { return BI_RM.charAt(n); }
function intAt(s,i) {
  var c = BI_RC[s.charCodeAt(i)];
  return (c==null)?-1:c;
}

// (protected) copy this to r
function bnpCopyTo(r) {
  for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
  r.t = this.t;
  r.s = this.s;
}

// (protected) set from integer value x, -DV <= x < DV
function bnpFromInt(x) {
  this.t = 1;
  this.s = (x<0)?-1:0;
  if(x > 0) this[0] = x;
  else if(x < -1) this[0] = x+DV;
  else this.t = 0;
}

// return bigint initialized to value
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }

// (protected) set from string and radix
function bnpFromString(s,b) {
  var k;
  if(b == 16) k = 4;
  else if(b == 8) k = 3;
  else if(b == 256) k = 8; // byte array
  else if(b == 2) k = 1;
  else if(b == 32) k = 5;
  else if(b == 4) k = 2;
  else { this.fromRadix(s,b); return; }
  this.t = 0;
  this.s = 0;
  var i = s.length, mi = false, sh = 0;
  while(--i >= 0) {
    var x = (k==8)?s.charCodeAt(i)&0xff:intAt(s,i);   /** MODIFIED **/
    if(x < 0) {
      if(s.charAt(i) == "-") mi = true;
      continue;
    }
    mi = false;
    if(sh == 0)
      this[this.t++] = x;
    else if(sh+k > this.DB) {
      this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
      this[this.t++] = (x>>(this.DB-sh));
    }
    else
      this[this.t-1] |= x<<sh;
    sh += k;
    if(sh >= this.DB) sh -= this.DB;
  }
  if(k == 8 && (s[0]&0x80) != 0) {
    this.s = -1;
    if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
  }
  this.clamp();
  if(mi) BigInteger.ZERO.subTo(this,this);
}

// (protected) clamp off excess high words
function bnpClamp() {
  var c = this.s&this.DM;
  while(this.t > 0 && this[this.t-1] == c) --this.t;
}

// (public) return string representation in given radix
function bnToString(b) {
  if(this.s < 0) return "-"+this.negate().toString(b);
  var k;
  if(b == 16) k = 4;
  else if(b == 8) k = 3;
  else if(b == 256) k = 8; // byte array      /** MODIFIED **/
  else if(b == 2) k = 1;
  else if(b == 32) k = 5;
  else if(b == 4) k = 2;
  else return this.toRadix(b);
  var km = (1<<k)-1, d, m = false, r = "", i = this.t;
  var p = this.DB-(i*this.DB)%k;
  if(i-- > 0) {
    if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = (k==8)?String.fromCharCode(d):int2char(d); }   /** MODIFIED **/
    while(i >= 0) {
      if(p < k) {
        d = (this[i]&((1<<p)-1))<<(k-p);
        d |= this[--i]>>(p+=this.DB-k);
      }
      else {
        d = (this[i]>>(p-=k))&km;
        if(p <= 0) { p += this.DB; --i; }
      }
      if(d > 0) m = true;
      if(m) r += (k==8)?String.fromCharCode(d):int2char(d);    /** MODIFIED **/
    }
  }
  return m?r:"0";
}

// (public) -this
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }

// (public) |this|
function bnAbs() { return (this.s<0)?this.negate():this; }

// (public) return + if this > a, - if this < a, 0 if equal
function bnCompareTo(a) {
  var r = this.s-a.s;
  if(r != 0) return r;
  var i = this.t;
  r = i-a.t;
  if(r != 0) return r;
  while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
  return 0;
}

// returns bit length of the integer x
function nbits(x) {
  var r = 1, t;
  if((t=x>>>16) != 0) { x = t; r += 16; }
  if((t=x>>8) != 0) { x = t; r += 8; }
  if((t=x>>4) != 0) { x = t; r += 4; }
  if((t=x>>2) != 0) { x = t; r += 2; }
  if((t=x>>1) != 0) { x = t; r += 1; }
  return r;
}

// (public) return the number of bits in "this"
function bnBitLength() {
  if(this.t <= 0) return 0;
  return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
}

// (protected) r = this << n*DB
function bnpDLShiftTo(n,r) {
  var i;
  for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
  for(i = n-1; i >= 0; --i) r[i] = 0;
  r.t = this.t+n;
  r.s = this.s;
}

// (protected) r = this >> n*DB
function bnpDRShiftTo(n,r) {
  for(var i = n; i < this.t; ++i) r[i-n] = this[i];
  r.t = Math.max(this.t-n,0);
  r.s = this.s;
}

// (protected) r = this << n
function bnpLShiftTo(n,r) {
  var bs = n%this.DB;
  var cbs = this.DB-bs;
  var bm = (1<<cbs)-1;
  var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
  for(i = this.t-1; i >= 0; --i) {
    r[i+ds+1] = (this[i]>>cbs)|c;
    c = (this[i]&bm)<<bs;
  }
  for(i = ds-1; i >= 0; --i) r[i] = 0;
  r[ds] = c;
  r.t = this.t+ds+1;
  r.s = this.s;
  r.clamp();
}

// (protected) r = this >> n
function bnpRShiftTo(n,r) {
  r.s = this.s;
  var ds = Math.floor(n/this.DB);
  if(ds >= this.t) { r.t = 0; return; }
  var bs = n%this.DB;
  var cbs = this.DB-bs;
  var bm = (1<<bs)-1;
  r[0] = this[ds]>>bs;
  for(var i = ds+1; i < this.t; ++i) {
    r[i-ds-1] |= (this[i]&bm)<<cbs;
    r[i-ds] = this[i]>>bs;
  }
  if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
  r.t = this.t-ds;
  r.clamp();
}

// (protected) r = this - a
function bnpSubTo(a,r) {
  var i = 0, c = 0, m = Math.min(a.t,this.t);
  while(i < m) {
    c += this[i]-a[i];
    r[i++] = c&this.DM;
    c >>= this.DB;
  }
  if(a.t < this.t) {
    c -= a.s;
    while(i < this.t) {
      c += this[i];
      r[i++] = c&this.DM;
      c >>= this.DB;
    }
    c += this.s;
  }
  else {
    c += this.s;
    while(i < a.t) {
      c -= a[i];
      r[i++] = c&this.DM;
      c >>= this.DB;
    }
    c -= a.s;
  }
  r.s = (c<0)?-1:0;
  if(c < -1) r[i++] = this.DV+c;
  else if(c > 0) r[i++] = c;
  r.t = i;
  r.clamp();
}

// (protected) r = this * a, r != this,a (HAC 14.12)
// "this" should be the larger one if appropriate.
function bnpMultiplyTo(a,r) {
  var x = this.abs(), y = a.abs();
  var i = x.t;
  r.t = i+y.t;
  while(--i >= 0) r[i] = 0;
  for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
  r.s = 0;
  r.clamp();
  if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
}

// (protected) r = this^2, r != this (HAC 14.16)
function bnpSquareTo(r) {
  var x = this.abs();
  var i = r.t = 2*x.t;
  while(--i >= 0) r[i] = 0;
  for(i = 0; i < x.t-1; ++i) {
    var c = x.am(i,x[i],r,2*i,0,1);
    if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
      r[i+x.t] -= x.DV;
      r[i+x.t+1] = 1;
    }
  }
  if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
  r.s = 0;
  r.clamp();
}

// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
// r != q, this != m.  q or r may be null.
function bnpDivRemTo(m,q,r) {
  var pm = m.abs();
  if(pm.t <= 0) return;
  var pt = this.abs();
  if(pt.t < pm.t) {
    if(q != null) q.fromInt(0);
    if(r != null) this.copyTo(r);
    return;
  }
  if(r == null) r = nbi();
  var y = nbi(), ts = this.s, ms = m.s;
  var nsh = this.DB-nbits(pm[pm.t-1]);	// normalize modulus
  if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
  else { pm.copyTo(y); pt.copyTo(r); }
  var ys = y.t;
  var y0 = y[ys-1];
  if(y0 == 0) return;
  var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
  var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
  var i = r.t, j = i-ys, t = (q==null)?nbi():q;
  y.dlShiftTo(j,t);
  if(r.compareTo(t) >= 0) {
    r[r.t++] = 1;
    r.subTo(t,r);
  }
  BigInteger.ONE.dlShiftTo(ys,t);
  t.subTo(y,y);	// "negative" y so we can replace sub with am later
  while(y.t < ys) y[y.t++] = 0;
  while(--j >= 0) {
    // Estimate quotient digit
    var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
    if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {	// Try it out
      y.dlShiftTo(j,t);
      r.subTo(t,r);
      while(r[i] < --qd) r.subTo(t,r);
    }
  }
  if(q != null) {
    r.drShiftTo(ys,q);
    if(ts != ms) BigInteger.ZERO.subTo(q,q);
  }
  r.t = ys;
  r.clamp();
  if(nsh > 0) r.rShiftTo(nsh,r);	// Denormalize remainder
  if(ts < 0) BigInteger.ZERO.subTo(r,r);
}

// (public) this mod a
function bnMod(a) {
  var r = nbi();
  this.abs().divRemTo(a,null,r);
  if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
  return r;
}

// Modular reduction using "classic" algorithm
function Classic(m) { this.m = m; }
function cConvert(x) {
  if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
  else return x;
}
function cRevert(x) { return x; }
function cReduce(x) { x.divRemTo(this.m,null,x); }
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }

Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;

// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
// justification:
//         xy == 1 (mod m)
//         xy =  1+km
//   xy(2-xy) = (1+km)(1-km)
// x[y(2-xy)] = 1-k^2m^2
// x[y(2-xy)] == 1 (mod m^2)
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
// JS multiply "overflows" differently from C/C++, so care is needed here.
function bnpInvDigit() {
  if(this.t < 1) return 0;
  var x = this[0];
  if((x&1) == 0) return 0;
  var y = x&3;		// y == 1/x mod 2^2
  y = (y*(2-(x&0xf)*y))&0xf;	// y == 1/x mod 2^4
  y = (y*(2-(x&0xff)*y))&0xff;	// y == 1/x mod 2^8
  y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;	// y == 1/x mod 2^16
  // last step - calculate inverse mod DV directly;
  // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
  y = (y*(2-x*y%this.DV))%this.DV;		// y == 1/x mod 2^dbits
  // we really want the negative inverse, and -DV < y < DV
  return (y>0)?this.DV-y:-y;
}

// Montgomery reduction
function Montgomery(m) {
  this.m = m;
  this.mp = m.invDigit();
  this.mpl = this.mp&0x7fff;
  this.mph = this.mp>>15;
  this.um = (1<<(m.DB-15))-1;
  this.mt2 = 2*m.t;
}

// xR mod m
function montConvert(x) {
  var r = nbi();
  x.abs().dlShiftTo(this.m.t,r);
  r.divRemTo(this.m,null,r);
  if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
  return r;
}

// x/R mod m
function montRevert(x) {
  var r = nbi();
  x.copyTo(r);
  this.reduce(r);
  return r;
}

// x = x/R mod m (HAC 14.32)
function montReduce(x) {
  while(x.t <= this.mt2)	// pad x so am has enough room later
    x[x.t++] = 0;
  for(var i = 0; i < this.m.t; ++i) {
    // faster way of calculating u0 = x[i]*mp mod DV
    var j = x[i]&0x7fff;
    var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
    // use am to combine the multiply-shift-add into one call
    j = i+this.m.t;
    x[j] += this.m.am(0,u0,x,i,0,this.m.t);
    // propagate carry
    while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
  }
  x.clamp();
  x.drShiftTo(this.m.t,x);
  if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}

// r = "x^2/R mod m"; x != r
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }

// r = "xy/R mod m"; x,y != r
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }

Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;

// (protected) true iff this is even
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }

// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
function bnpExp(e,z) {
  if(e > 0xffffffff || e < 1) return BigInteger.ONE;
  var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
  g.copyTo(r);
  while(--i >= 0) {
    z.sqrTo(r,r2);
    if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
    else { var t = r; r = r2; r2 = t; }
  }
  return z.revert(r);
}

// (public) this^e % m, 0 <= e < 2^32
function bnModPowInt(e,m) {
  var z;
  if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
  return this.exp(e,z);
}

// protected
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;

// public
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;

// "constants"
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/matcher.js":
/*!*****************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/matcher.js ***!
  \*****************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_402520__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Matcher class implementing matching addresses against
 *               a list of filters.
 */

const {RESOURCE_TYPES, SPECIAL_TYPES, ALLOWING_TYPES,
       enumerateTypes} = __nested_webpack_require_402520__(/*! ./contentTypes */ "./node_modules/adblockpluscore/lib/contentTypes.js");
const {compilePatterns} = __nested_webpack_require_402520__(/*! ./patterns */ "./node_modules/adblockpluscore/lib/patterns.js");
const {domainSuffixes, URLRequest} = __nested_webpack_require_402520__(/*! ./url */ "./node_modules/adblockpluscore/lib/url.js");
const {Filter} = __nested_webpack_require_402520__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");
const {FiltersByDomain, FilterMap} = __nested_webpack_require_402520__(/*! ./filtersByDomain */ "./node_modules/adblockpluscore/lib/filtersByDomain.js");
const {Cache} = __nested_webpack_require_402520__(/*! ./caching */ "./node_modules/adblockpluscore/lib/caching.js");

/**
 * Returns the amount of filters per map.
 * @param {Map} map
 * @param {string} keyword
 * @returns {number}
 */
let countFilters = (map, keyword) => {
  let list = map.get(keyword);
  if (!list)
    return 0;
  if (list instanceof Filter)
    return 1;
  return list.length;
};

/**
 * Returns a list of filters, if any, or an empty list.
 * @param {Map} map
 * @param {string} keyword
 * @returns {Array.<module:filterClasses.URLFilter>}
 */
let getFilters = (map, keyword) => {
  let list = map.get(keyword);
  if (!list)
    return Array.prototype;
  if (list instanceof Filter)
    return [list];
  return list;
};

/**
 * Checks if the keyword is bad for use.
 * @param {string} keyword
 * @returns {boolean}
 */
function isBadKeyword(keyword) {
  return keyword == "https" || keyword == "http" || keyword == "com" ||
         keyword == "js";
}

/**
 * Adds a filter by a given keyword to a map.
 * @param {module:filterClasses.URLFilter} filter
 * @param {string} keyword
 * @param {Map.<string,(module:filterClasses.URLFilter|
 *                      Array.<module:filterClasses.URLFilter>)>} map
 */
function addFilterByKeyword(filter, keyword, map) {
  // this dance is to avoid storing arrays for single filters
  let list = map.get(keyword);
  // when the keyword is known, promote as array if needed
  if (list) {
    if (list instanceof Filter)
      map.set(keyword, [list, filter]);
    else
      list.push(filter);
  }
  else {
    // store just the filter without the Array
    map.set(keyword, filter);
  }
}

/**
 * Removes a filter by a given keyword from a map.
 * @param {module:filterClasses.URLFilter} filter
 * @param {string} keyword
 * @param {Map.<string,(module:filterClasses.URLFilter|
 *                      Array.<module:filterClasses.URLFilter>)>} map
 */
function removeFilterByKeyword(filter, keyword, map) {
  // this dance is to normalize back the keyword entry, if any
  let list = map.get(keyword);
  if (list) {
    // when the value is a filter, remove the keyword if filter matches
    if (list instanceof Filter) {
      if (list == filter)
        map.delete(keyword);
    }
    // otherwise find the index and drop the array if the list has 1 item
    else {
      let i = list.findIndex(item => item === filter);
      if (i >= 0) {
        list.splice(i, 1);
        if (list.length === 1)
          map.set(keyword, list[0]);
      }
    }
  }
}

/**
 * Checks whether a filter matches a given URL request.
 *
 * @param {module:filterClasses.URLFilter} filter The filter.
 * @param {module:url.URLRequest} request The URL request.
 * @param {number} typeMask A mask specifying the content type of the URL
 *   request.
 * @param {?string} [sitekey] An optional public key associated with the
 *   URL request.
 * @param {?Array} [collection] An optional list to which to append the filter
 *   if it matches. If omitted, the function directly returns the filter if it
 *   matches.
 *
 * @returns {?module:filterClasses.URLFilter} The filter if it matches and
 *   `collection` is omitted; otherwise `null`.
 */
function matchFilter(filter, request, typeMask, sitekey, collection) {
  if (filter.matches(request, typeMask, sitekey)) {
    if (!collection)
      return filter;

    collection.push(filter);
  }

  return null;
}

/**
 * Checks whether a particular filter is slow.
 * @param {module:filterClasses.URLFilter} filter
 * @returns {boolean}
 */
exports.isSlowFilter = function isSlowFilter(filter) {
  return !filter.urlPattern.hasKeywords();
};

let Matcher =
/**
 * Blocking/allowing filter matching
 */
exports.Matcher = class Matcher {
  constructor() {
    /**
     * Lookup table for keywords by their associated filter
     * @type {Map.<module:filterClasses.URLFilter,string>}
     * @private
     */
    this._keywordByFilter = new Map();

    /**
     * Lookup table for simple filters by their associated keyword
     * @type {Map.<string,(module:filterClasses.URLFilter|
     *                     Array.<module:filterClasses.URLFilter>)>}
     * @private
     */
    this._simpleFiltersByKeyword = new Map();

    /**
     * Lookup table for complex filters by their associated keyword
     * @type {Map.<string,(module:filterClasses.URLFilter|
     *                     Array.<module:filterClasses.URLFilter>)>}
     * @private
     */
    this._complexFiltersByKeyword = new Map();

    /**
     * Lookup table of compiled patterns for simple filters by their associated
     * keyword
     * @type {Map.<string,?module:patterns~CompiledPatterns>}
     * @private
     */
    this._compiledPatternsByKeyword = new Map();

    /**
     * Compiled patterns for generic complex filters with no associated
     * keyword.
     * @type {?module:patterns~CompiledPatterns|boolean}
     * @private
     */
    this._keywordlessCompiledPatterns = false;

    /**
     * Lookup table of domain maps for complex filters by their associated
     * keyword
     * @type {Map.<string,
     *             Map.<string,
     *                  (module:filterClasses.URLFilter|
     *                   Map.<module:filterClasses.URLFilter,boolean>)>>}
     * @private
     */
    this._filterDomainMapsByKeyword = new Map();

    /**
     * Lookup table of type-specific lookup tables for complex filters by their
     * associated keyword
     * @type {Map.<string,
     *             Map.<string,
     *                  (module:filterClasses.URLFilter|
     *                   Array.<module:filterClasses.URLFilter>)>>}
     * @private
     */
    this._filterMapsByType = new Map();
  }

  /**
   * Removes all known filters
   */
  clear() {
    this._keywordByFilter.clear();
    this._simpleFiltersByKeyword.clear();
    this._complexFiltersByKeyword.clear();
    this._compiledPatternsByKeyword.clear();
    this._keywordlessCompiledPatterns = false;
    this._filterDomainMapsByKeyword.clear();
    this._filterMapsByType.clear();
  }

  /**
   * Adds a filter to the matcher
   * @param {module:filterClasses.URLFilter} filter
   */
  add(filter) {
    if (this._keywordByFilter.has(filter))
      return;

    // Look for a suitable keyword
    let keyword = this.findKeyword(filter);
    let simple = filter.contentType == RESOURCE_TYPES && filter.isGeneric();

    addFilterByKeyword(filter, keyword, simple ? this._simpleFiltersByKeyword :
        this._complexFiltersByKeyword);

    this._keywordByFilter.set(filter, keyword);

    if (simple) {
      if (this._compiledPatternsByKeyword.size > 0)
        this._compiledPatternsByKeyword.delete(keyword);

      return;
    }

    if (keyword == "")
      this._keywordlessCompiledPatterns = false;

    for (let type of enumerateTypes(filter.contentType, SPECIAL_TYPES)) {
      let map = this._filterMapsByType.get(type);
      if (!map)
        this._filterMapsByType.set(type, map = new Map());

      addFilterByKeyword(filter, keyword, map);
    }

    let {domains} = filter;

    let filtersByDomain = this._filterDomainMapsByKeyword.get(keyword);
    if (!filtersByDomain) {
      // In most cases, there is only one pure generic filter to a keyword.
      // Instead of Map { "foo" => Map { "" => Map { filter => true } } }, we
      // can just reduce it to Map { "foo" => filter } and save a lot of
      // memory.
      if (!domains) {
        this._filterDomainMapsByKeyword.set(keyword, filter);
        return;
      }

      filtersByDomain = new FiltersByDomain();
      this._filterDomainMapsByKeyword.set(keyword, filtersByDomain);
    }
    else if (!(filtersByDomain instanceof FiltersByDomain)) {
      filtersByDomain = new FiltersByDomain([["", filtersByDomain]]);
      this._filterDomainMapsByKeyword.set(keyword, filtersByDomain);
    }

    filtersByDomain.add(filter, domains);
  }

  /**
   * Removes a filter from the matcher
   * @param {module:filterClasses.URLFilter} filter
   */
  remove(filter) {
    let keyword = this._keywordByFilter.get(filter);
    if (typeof keyword == "undefined")
      return;

    let simple = filter.contentType == RESOURCE_TYPES && filter.isGeneric();

    removeFilterByKeyword(
      filter,
      keyword,
      simple ?
        this._simpleFiltersByKeyword :
        this._complexFiltersByKeyword
    );

    this._keywordByFilter.delete(filter);

    if (simple) {
      if (this._compiledPatternsByKeyword.size > 0)
        this._compiledPatternsByKeyword.delete(keyword);

      return;
    }

    if (keyword == "")
      this._keywordlessCompiledPatterns = false;

    for (let type of enumerateTypes(filter.contentType, SPECIAL_TYPES)) {
      let map = this._filterMapsByType.get(type);
      if (map)
        removeFilterByKeyword(filter, keyword, map);
    }

    let filtersByDomain = this._filterDomainMapsByKeyword.get(keyword);
    if (filtersByDomain) {
      // Because of the memory optimization in the add function, most of the
      // time this will be a filter rather than a map.
      if (!(filtersByDomain instanceof FiltersByDomain)) {
        this._filterDomainMapsByKeyword.delete(keyword);
        return;
      }

      filtersByDomain.remove(filter);

      if (filtersByDomain.size == 0) {
        this._filterDomainMapsByKeyword.delete(keyword);
      }
      else if (filtersByDomain.size == 1) {
        for (let [lastDomain, map] of filtersByDomain.entries()) {
          // Reduce Map { "foo" => Map { "" => filter } } to
          // Map { "foo" => filter }
          if (lastDomain == "" && !(map instanceof FilterMap))
            this._filterDomainMapsByKeyword.set(keyword, map);

          break;
        }
      }
    }
  }

  /**
   * Checks whether a filter exists in the matcher
   * @param {module:filterClasses.URLFilter} filter
   * @returns {boolean}
   */
  has(filter) {
    return this._keywordByFilter.has(filter);
  }

  /**
   * Chooses a keyword to be associated with the filter.
   *
   * Because it will perform some internal optimizations, there is no
   * guarantee that this function will always return the same result when
   * called with the same filter.
   *
   * @param {module:filterClasses.Filter} filter
   * @returns {string} keyword or an empty string if no keyword could be found
   * @protected
   */
  findKeyword(filter) {
    let result = "";

    let candidates = filter.urlPattern.keywordCandidates();
    if (!candidates)
      return result;

    let resultCount = 0xFFFFFF;
    let resultLength = 0;

    for (let i = 0, l = candidates.length; i < l; i++) {
      let candidate = candidates[i].substring(1);

      if (isBadKeyword(candidate))
        continue;

      let simpleCount = countFilters(this._simpleFiltersByKeyword, candidate);
      let complexCount = countFilters(this._complexFiltersByKeyword,
                                      candidate);

      let count = simpleCount + complexCount;

      if (count < resultCount ||
          (count == resultCount && candidate.length > resultLength)) {
        result = candidate;
        resultCount = count;
        resultLength = candidate.length;
      }
    }

    return result;
  }

  _matchFiltersByDomain(filtersByDomain, request, typeMask, sitekey,
                        specificOnly, collection) {
    let excluded = null;

    let domain = request.documentHostname || "";
    for (let suffix of domainSuffixes(domain, !specificOnly)) {
      let map = filtersByDomain.get(suffix);
      if (map) {
        if (map instanceof FilterMap) {
          for (let [filter, include] of map.entries()) {
            if (!include) {
              if (excluded)
                excluded.add(filter);
              else
                excluded = new Set([filter]);
            }
            else if (
              (!excluded || !excluded.has(filter)) &&
              matchFilter(filter, request, typeMask, sitekey, collection)
            ) {
              return filter;
            }
          }
        }
        else if ((!excluded || !excluded.has(map)) &&
                 matchFilter(map, request, typeMask, sitekey, collection)) {
          return map;
        }
      }
    }

    return null;
  }

  _checkEntryMatchSimpleQuickCheck(keyword, request, filters) {
    let compiled = this._compiledPatternsByKeyword.get(keyword);
    if (typeof compiled == "undefined") {
      compiled = compilePatterns(filters);
      this._compiledPatternsByKeyword.set(keyword, compiled);
    }

    // If compilation failed (e.g. too many filters), return true because this
    // is only a pre-check.
    return !compiled || compiled.test(request);
  }

  _checkEntryMatchSimple(keyword, request, collection) {
    let filters = getFilters(this._simpleFiltersByKeyword, keyword);
    let {length} = filters;
    if (length) {
      // For simple filters where there's more than one filter to the keyword,
      // we do a quick check using a single compiled pattern that combines all
      // the patterns. This is a lot faster for requests that are not going to
      // be blocked (i.e. most requests).
      if (length === 1 ||
          this._checkEntryMatchSimpleQuickCheck(keyword, request, filters)) {
        for (let filter of filters) {
          // Simple filters match any resource type.
          if (matchFilter(filter, request, RESOURCE_TYPES, null, collection))
            return filter;
        }
      }
    }

    return null;
  }

  _checkEntryMatchForType(keyword, request, typeMask, sitekey, specificOnly,
                          collection) {
    let filtersForType = this._filterMapsByType.get(typeMask);
    if (filtersForType) {
      for (let filter of getFilters(filtersForType, keyword)) {
        if (specificOnly && filter.isGeneric())
          continue;

        if (matchFilter(filter, request, typeMask, sitekey, collection))
          return filter;
      }
    }

    return null;
  }

  _checkEntryMatchByDomain(keyword, request, typeMask, sitekey, specificOnly,
                           collection) {
    let filtersByDomain = this._filterDomainMapsByKeyword.get(keyword);
    if (filtersByDomain) {
      if (filtersByDomain instanceof FiltersByDomain) {
        if (keyword == "" && !specificOnly) {
          let compiled = this._keywordlessCompiledPatterns;

          // If the value is false, it indicates that we need to initialize it
          // to either a CompiledPatterns object or null.
          if (compiled == false) {
            // Compile all the patterns from the generic filters into a single
            // object. It is worth doing this for the keywordless generic
            // complex filters because they must be checked against every
            // single URL request that has not already been blocked by one of
            // the simple filters (i.e. most URL requests).
            let map = filtersByDomain.get("");
            if (map instanceof FilterMap)
              compiled = compilePatterns([...map.keys()]);

            this._keywordlessCompiledPatterns = compiled || null;
          }

          // We can skip the generic filters if none of them pass the test.
          if (compiled && !compiled.test(request))
            specificOnly = true;
        }

        return this._matchFiltersByDomain(
          filtersByDomain, request, typeMask, sitekey, specificOnly, collection
        );
      }

      // Because of the memory optimization in the add function, most of the
      // time this will be a filter rather than a map.

      // Also see #7312: If it's a single filter, it's always the equivalent of
      // Map { "" => Map { filter => true } } (i.e. applies to any domain). If
      // the specific-only flag is set, we skip it.
      if (!specificOnly) {
        return matchFilter(
          filtersByDomain, request, typeMask, sitekey, collection
        );
      }
    }

    return null;
  }

  /**
   * Checks whether the entries for a particular keyword match a URL
   * @param {string} keyword
   * @param {module:url.URLRequest} request
   * @param {number} typeMask
   * @param {?string} [sitekey]
   * @param {boolean} [specificOnly]
   * @param {?Array.<module:filterClasses.Filter>} [collection] An optional
   *   list of filters to which to append any results. If specified, the
   *   function adds *all* matching filters to the list; if omitted,
   *   the function directly returns the first matching filter.
   * @returns {?module:filterClasses.Filter}
   * @protected
   */
  checkEntryMatch(keyword, request, typeMask, sitekey, specificOnly,
                  collection) {
    // We need to skip the simple (location-only) filters if the type mask does
    // not contain any resource types.
    if (!specificOnly && (typeMask & RESOURCE_TYPES) != 0) {
      let filter = this._checkEntryMatchSimple(keyword, request, collection);
      if (filter)
        return filter;
    }

    // If the type mask contains a special type (first condition) and it is
    // the only type in the mask (second condition), we can use the
    // type-specific map, which typically contains a lot fewer filters. This
    // enables faster lookups for allowing types like $document, $elemhide,
    // and so on, as well as other special types like $csp.
    if ((typeMask & SPECIAL_TYPES) != 0 && (typeMask & typeMask - 1) == 0) {
      return this._checkEntryMatchForType(
        keyword, request, typeMask, sitekey, specificOnly, collection
      );
    }


    return this._checkEntryMatchByDomain(
      keyword, request, typeMask, sitekey, specificOnly, collection
    );
  }

  /**
   * @see #match
   * @deprecated
   * @inheritdoc
   */
  matchesAny(url, typeMask, docDomain, sitekey, specificOnly) {
    return this.match(url, typeMask, docDomain, sitekey, specificOnly);
  }

  /**
   * Tests whether the URL matches any of the known filters
   * @param {URL|module:url~URLInfo|string} url
   *   URL to be tested
   * @param {number} typeMask
   *   bitmask of content / request types to match
   * @param {?string} [docDomain]
   *   domain name of the document that loads the URL
   * @param {?string} [sitekey]
   *   public key provided by the document
   * @param {boolean} [specificOnly]
   *   should be `true` if generic matches should be ignored
   * @returns {?module:filterClasses.URLFilter}
   *   matching filter or `null`
   */
  match(url, typeMask, docDomain, sitekey, specificOnly) {
    let request = URLRequest.from(url, docDomain);
    let candidates = request.lowerCaseHref.match(/[a-z0-9%]{2,}|$/g);

    for (let i = 0, l = candidates.length; i < l; i++) {
      if (isBadKeyword(candidates[i]))
        continue;

      let result = this.checkEntryMatch(
        candidates[i], request, typeMask, sitekey, specificOnly
      );
      if (result)
        return result;
    }

    return null;
  }
};

class CombinedMatcher {
  constructor() {
    /**
     * Matcher for blocking rules.
     * @type {module:matcher.Matcher}
     * @private
     */
    this._blocking = new Matcher();

    /**
     * Matcher for exception rules.
     * @type {module:matcher.Matcher}
     * @private
     */
    this._allowing = new Matcher();

    /**
     * Lookup table of previous match results
     * @type {module:caching.Cache.<string, ?(module:filterClasses.URLFilter|
     *                                        MatcherSearchResults)>}
     * @private
     */
    this._resultCache = new Cache(10000);
  }

  /**
   * @see module:matcher.Matcher#clear
   */
  clear() {
    this._blocking.clear();
    this._allowing.clear();
    this._resultCache.clear();
  }

  /**
   * @see module:matcher.Matcher#add
   * @param {module:filterClasses.Filter} filter
   */
  add(filter) {
    if (filter.type == "allowing")
      this._allowing.add(filter);
    else
      this._blocking.add(filter);

    this._resultCache.clear();
  }

  /**
   * @see module:matcher.Matcher#remove
   * @param {module:filterClasses.Filter} filter
   */
  remove(filter) {
    if (filter.type == "allowing")
      this._allowing.remove(filter);
    else
      this._blocking.remove(filter);

    this._resultCache.clear();
  }

  /**
   * @see module:matcher.Matcher#has
   * @param {module:filterClasses.Filter} filter
   * @returns {boolean}
   */
  has(filter) {
    if (filter.type == "allowing")
      return this._allowing.has(filter);
    return this._blocking.has(filter);
  }

  /**
   * @see module:matcher.Matcher#findKeyword
   * @param {module:filterClasses.Filter} filter
   * @returns {string} keyword
   * @protected
   */
  findKeyword(filter) {
    if (filter.type == "allowing")
      return this._allowing.findKeyword(filter);
    return this._blocking.findKeyword(filter);
  }

  _matchInternal(url, typeMask, docDomain, sitekey, specificOnly,
                 exhaustiveSearch) {
    let request = URLRequest.from(url, docDomain);
    let candidates = request.lowerCaseHref.match(/[a-z0-9%]{2,}|$/g)
        .filter(candidate => !isBadKeyword(candidate));
    let typeIsOnlyAllowing = (typeMask & ~ALLOWING_TYPES) == 0;

    let allowingHit = null;
    let blockingHit = null;

    let findAllowing = () => {
      for (let i = 0, l = candidates.length; !allowingHit && i < l; i++) {
        allowingHit = this._allowing.checkEntryMatch(
          candidates[i], request, typeMask, sitekey
        );
      }
    };

    let findBlocking = () => {
      for (let i = 0, l = candidates.length; !blockingHit && i < l; i++) {
        blockingHit = this._blocking.checkEntryMatch(
          candidates[i], request, typeMask, sitekey, specificOnly
        );
      }
    };

    if (exhaustiveSearch) {
      findAllowing();
      if (!allowingHit && !typeIsOnlyAllowing)
        findBlocking();
    }
    else if (typeIsOnlyAllowing) {
      findAllowing();
    }
    else {
      findBlocking();
      if (blockingHit)
        findAllowing();
    }

    return allowingHit || blockingHit;
  }

  _searchInternal(url, typeMask, docDomain, sitekey, specificOnly, filterType) {
    let hits = {};

    let searchBlocking = filterType == "blocking" || filterType == "all";
    let searchAllowing = filterType == "allowing" || filterType == "all";

    if (searchBlocking)
      hits.blocking = [];

    if (searchAllowing)
      hits.allowing = [];

    // If the type mask includes no types other than allowing types, we
    // can skip the blocking filters.
    if ((typeMask & ~ALLOWING_TYPES) == 0)
      searchBlocking = false;

    let request = URLRequest.from(url, docDomain);
    let candidates = request.lowerCaseHref.match(/[a-z0-9%]{2,}|$/g);

    for (let i = 0, l = candidates.length; i < l; i++) {
      if (isBadKeyword(candidates[i]))
        continue;

      if (searchBlocking) {
        this._blocking.checkEntryMatch(
          candidates[i],
          request,
          typeMask,
          sitekey,
          specificOnly,
          hits.blocking
        );
      }


      if (searchAllowing) {
        this._allowing.checkEntryMatch(
          candidates[i], request, typeMask, sitekey, false, hits.allowing
        );
      }
    }

    return hits;
  }

  /**
   * @see #match
   * @deprecated
   * @inheritdoc
   */
  matchesAny(url, typeMask, docDomain, sitekey, specificOnly) {
    return this.match(url, typeMask, docDomain, sitekey, specificOnly);
  }

  /**
   * Tests whether the URL matches any of the known filters
   *
   * If both a blocking and an allowing filter matches, the allowing filter is
   * prioritized.
   *
   * If only an allowing filter matches, then the allowing filter will not be
   * returned unless it is one of the `{@link module:contentTypes.ALLOWING_TYPES
   * ALLOWING_TYPES}` used for exception rules only, or if `exhaustiveSearch` is
   * true. In other words, the allowing filter is only returned if it is
   * expected to change blocking behaviour.
   *
   * @param {URL|module:url~URLInfo|string} url
   *   URL to be tested
   * @param {number} typeMask
   *   bitmask of content / request types to match
   * @param {?string} [docDomain]
   *   domain name of the document that loads the URL
   * @param {?string} [sitekey]
   *   public key provided by the document
   * @param {boolean} [specificOnly]
   *   should be `true` if generic matches should be ignored
   * @param {boolean} [exhaustiveSearch=false]
   *   should return a matched allowing filter, even if the filter will have no
   *   effect on blocking behaviour
   * @returns {?module:filterClasses.URLFilter}
   *   matching filter or `null`
   */
  match(url, typeMask, docDomain, sitekey, specificOnly,
        exhaustiveSearch = false) {
    let key = `${url} ${typeMask} ${docDomain} ${sitekey} ${specificOnly} ${exhaustiveSearch}`;
    let result = this._resultCache.get(key);
    if (typeof result != "undefined")
      return result;

    result = this._matchInternal(
      url, typeMask, docDomain, sitekey, specificOnly, exhaustiveSearch
    );

    this._resultCache.set(key, result);

    return result;
  }

  /**
   * @typedef {Object} MatcherSearchResults
   * @property {Array.<module:filterClasses.BlockingFilter>} [blocking] List of
   *   blocking filters found.
   * @property {Array.<module:filterClasses.AllowingFilter>} [allowing] List
   *   of allowing filters found.
   */

  /**
   * Searches all blocking and allowing filters and returns results matching
   * the given parameters.
   *
   * @param {URL|module:url~URLInfo|string} url
   * @param {number} typeMask
   * @param {?string} [docDomain]
   * @param {?string} [sitekey]
   * @param {boolean} [specificOnly]
   * @param {string} [filterType] The types of filters to look for. This can be
   *   `"blocking"`, `"allowing"`, or `"all"` (default).
   *
   * @returns {MatcherSearchResults}
   */
  search(url, typeMask, docDomain, sitekey, specificOnly, filterType = "all") {
    let key = `* ${url} ${typeMask} ${docDomain} ${sitekey} ` +
              `${specificOnly} ${filterType}`;

    let result = this._resultCache.get(key);
    if (typeof result != "undefined")
      return result;

    result = this._searchInternal(
      url, typeMask, docDomain, sitekey, specificOnly, filterType
    );

    this._resultCache.set(key, result);

    return result;
  }

  /**
   * Tests whether the URL is allowlisted
   * @see module:matcher.Matcher#match
   * @inheritdoc
   * @returns {boolean}
   */
  isAllowlisted(url, typeMask, docDomain, sitekey) {
    return !!this._allowing.match(url, typeMask, docDomain, sitekey);
  }
}

/**
 * Combines a matcher for blocking and exception rules, automatically sorts
 * rules into two `{@link module:matcher.Matcher Matcher}` instances.
 */
exports.CombinedMatcher = CombinedMatcher;

/**
 * Create the `{@link module:matcher~CombinedMatcher CombinedMatcher}`
 * instance that should usually be used.
 * @returns {module:matcher.CombinedMatcher}
 */
exports.newDefaultMatcher = function() {
  return new CombinedMatcher();
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/notifications.js":
/*!***********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/notifications.js ***!
  \***********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_431223__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Handles notifications.
 */

const {Prefs} = __nested_webpack_require_431223__(/*! prefs */ "./sdk/api/prefs.js");

const {MILLIS_IN_MINUTE, MILLIS_IN_HOUR, MILLIS_IN_DAY} = __nested_webpack_require_431223__(/*! ./time */ "./node_modules/adblockpluscore/lib/time.js");
const {Downloader, Downloadable} = __nested_webpack_require_431223__(/*! ./downloader */ "./node_modules/adblockpluscore/lib/downloader.js");
const {compareVersions} = __nested_webpack_require_431223__(/*! ./versions */ "./node_modules/adblockpluscore/lib/versions.js");
const {analytics} = __nested_webpack_require_431223__(/*! ./analytics */ "./node_modules/adblockpluscore/lib/analytics.js");
const {EventEmitter} = __nested_webpack_require_431223__(/*! ./events */ "./node_modules/adblockpluscore/lib/events.js");

const INITIAL_DELAY = 1 * MILLIS_IN_MINUTE;
const CHECK_INTERVAL = 1 * MILLIS_IN_HOUR;
const EXPIRATION_INTERVAL = 1 * MILLIS_IN_DAY;

let getPreferredMillis = (field, fallback) =>
                          field in Prefs ? Prefs[field] : fallback;

/**
 * The default locale for the localization of notification texts.
 * @type {string}
 * @default
 */
const DEFAULT_LOCALE = "en-US";

/**
 * Returns the numerical severity of a notification.
 * @param {Object} notification The notification.
 * @returns {number} The numerical severity of the notification.
 */
function getNumericalSeverity(notification) {
  switch (notification.type) {
    case "information":
      return 0;
    case "newtab":
    case "relentless":
      return 1;
    case "critical":
      return 2;
  }

  return 0;
}

/**
 * Saves notification data to preferences.
 * @param {string} [key] The key to save.
 */
function saveNotificationData(key = "notificationdata") {
  // JSON values aren't saved unless they are assigned a different object.
  Prefs[key] = JSON.parse(JSON.stringify(Prefs[key]));
}

/**
 * Localizes a notification text.
 *
 * @param {Object} translations The set of translations from which to select
 *   the localization.
 * @param {string} locale The locale string to use for the selection. If no
 *   localized version is found in the `translations` object for the given
 *   locale, the
 *   {@link module:notifications~DEFAULT_LOCALE default locale} is used.
 *
 * @returns {*} The localized text; `undefined` if no localized version is
 *   found in the `translations` object.
 */
function localize(translations, locale) {
  if (locale in translations)
    return translations[locale];

  let languagePart = locale.substring(0, locale.indexOf("-"));
  if (languagePart && languagePart in translations)
    return translations[languagePart];

  return translations[DEFAULT_LOCALE];
}

function isValidNotification(notification) {
  // Only notifications that are meant to be opened in a new tab must
  // contain at least one URL to open.
  if (notification.type == "newtab" &&
      !(notification.links && notification.links.length > 0))
    return false;

  return true;
}

/**
 * `{@link module:notifications.notifications}` implementation.
 *
 * It also emits the named events `downloaded`, `ignored-category-added` and
 * `ignored-category-removed` built with `{@link module:events.EventEmitter
 *                                               EventEmitter}`
 */
class Notifications extends EventEmitter {
  /**
   * @hideconstructor
   */
  constructor() {
    super();

    /**
     * Whether the fetching of notifications has been started.
     * @private
     */
    this._started = false;

    /**
     * Whether all ignorable notifications should be ignored.
     * @type {boolean}
     */
    this.ignored = false;

    /**
     * The locale for the localization of notification texts.
     * @type {string}
     * @default {@link module:notifications~DEFAULT_LOCALE}
     */
    this.locale = DEFAULT_LOCALE;

    /**
     * The number to consider when performing the blockedTotalMin and
     * blockedTotalMax target checks.
     *
     * This property needs to be initialized at startup and updated
     * whenever a blocking filter matches. If set to null (default),
     * notifications using these target checks are ignored.
     *
     * If the deprecated preferences Prefs.show_statsinpopup and
     * Prefs.blocked_total exist they take precedence over this property.
     * @type {?number}
     */
    this.numBlocked = null;

    /**
     * Listeners for notifications to be shown.
     * @type {Set.<function>}
     * @private
     */
    this._showListeners = new Set();

    /**
     * Local notifications added via
     * `{@link module:notifications~Notifications#addNotification
     *         addNotification()}`.
     * @type {Set.<Object>}
     * @private
     */
    this._localNotifications = new Set();

    /**
     * The object providing actual downloading functionality.
     * @type {module:downloader.Downloader}
     * @private
     */
    this._downloader = new Downloader(this._getDownloadables.bind(this));

    this._downloader.onExpirationChange = this._onExpirationChange.bind(this);
    this._downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this);
    this._downloader.onDownloadError = this._onDownloadError.bind(this);
    this._onBlockedTotal = this._onBlockedTotal.bind(this);
  }

  /**
   * Starts fetching notifications.
   *
   * No notifications are fetched until this function has been called at least
   * once.
   */
  start() {
    if (this._started)
      return;

    Prefs.on("blocked_total", this._onBlockedTotal);

    this._downloader.scheduleChecks(
      getPreferredMillis("notifications_check_interval", CHECK_INTERVAL),
      getPreferredMillis("notifications_initial_delay", INITIAL_DELAY)
    );
    this._started = true;
  }

  /**
   * Stops fetching notifications.
   */
  stop() {
    this._started = false;
    this._downloader.unscheduleChecks();

    Prefs.off("blocked_total", this._onBlockedTotal);
  }

  /**
   * Sets an alternative storage backend for storing local
   * notifications. By default, local notifications are stored in
   * memory.
   *
   * The new storage backend is expected to provide similar
   * functionality to a Set. Notifications will be added to it,
   * deleted from it, and iterated over.
   *
   * @param {object} storageBackend
   * @param {function} storageBackend.add Add a new notification.
   * @param {function} storageBackend.delete Remove a notification.
   * @param {function} storageBackend.Symbol.iterator Returns an iterable of all
   *   local notifications.
   */
  setLocalNotificationStorage(storageBackend) {
    if (this._localNotifications == storageBackend)
      return;

    for (let notification of this._localNotifications)
      storageBackend.add(notification);

    this._localNotifications = storageBackend;
  }

  /**
   * Yields a `{@link module:downloader.Downloadable Downloadable}` instance
   * for the notifications download.
   * @yields {module:downloader.Downloadable}
   * @private
   */
  *_getDownloadables() {
    let {notificationurl: url, notificationdata} = Prefs;

    let downloadable = new Downloadable(url);

    if (analytics.isTrusted(url))
      downloadable.firstVersion = analytics.getFirstVersion();

    if (typeof notificationdata.lastError == "number")
      downloadable.lastError = notificationdata.lastError;
    if (typeof notificationdata.lastCheck == "number")
      downloadable.lastCheck = notificationdata.lastCheck;

    if (typeof notificationdata.data == "object" &&
        "version" in notificationdata.data)
      downloadable.lastVersion = notificationdata.data.version;

    if (typeof notificationdata.softExpiration == "number")
      downloadable.softExpiration = notificationdata.softExpiration;
    if (typeof notificationdata.hardExpiration == "number")
      downloadable.hardExpiration = notificationdata.hardExpiration;
    if (typeof notificationdata.downloadCount == "number")
      downloadable.downloadCount = notificationdata.downloadCount;

    yield downloadable;
  }

  _onExpirationChange(downloadable) {
    Prefs.notificationdata.lastCheck = downloadable.lastCheck;
    Prefs.notificationdata.softExpiration = downloadable.softExpiration;
    Prefs.notificationdata.hardExpiration = downloadable.hardExpiration;

    saveNotificationData();
  }

  _onDownloadSuccess(downloadable, responseText, errorCallback,
                     redirectCallback) {
    try {
      let data = JSON.parse(responseText);

      if (typeof data.version == "string" &&
          analytics.isTrusted(downloadable.redirectURL || downloadable.url))
        analytics.recordVersion(data.version);

      let notifications = [];
      for (let notification of data.notifications) {
        if (!isValidNotification(notification)) {
          console.warn(`Invalid notification with ID "${notification.id}"`);
          continue;
        }

        if ("severity" in notification) {
          if (!("type" in notification))
            notification.type = notification.severity;
          delete notification.severity;
        }

        notifications.push(notification);
      }
      data.notifications = notifications;

      Prefs.notificationdata.data = data;
    }
    catch (error) {
      console.warn(error);
      errorCallback("synchronize_invalid_data");
      return;
    }

    let expirationInterval = getPreferredMillis(
      "notifications_expiration_interval",
      EXPIRATION_INTERVAL
    );

    Prefs.notificationdata.lastError = 0;
    Prefs.notificationdata.downloadStatus = "synchronize_ok";
    [
      Prefs.notificationdata.softExpiration,
      Prefs.notificationdata.hardExpiration
    ] = this._downloader.processExpirationInterval(expirationInterval);
    Prefs.notificationdata.downloadCount = downloadable.downloadCount;

    saveNotificationData();

    this.emit("downloaded");
    this.showNext();
  }

  _onDownloadError(downloadable, downloadURL, error, responseStatus,
                   redirectCallback) {
    Prefs.notificationdata.lastError = Date.now();
    Prefs.notificationdata.downloadStatus = error;

    saveNotificationData();
  }

  _onBlockedTotal() {
    this.showNext();
  }

  /**
   * Adds a listener for notifications to be shown.
   * @param {function} listener Listener to be invoked when a notification is
   *   to be shown.
   */
  addShowListener(listener) {
    this._showListeners.add(listener);
  }

  /**
   * Removes the supplied listener.
   * @param {function} listener Listener that was added via
   *   `{@link module:notifications~Notifications#addShowListener
   *           addShowListener()}`.
   */
  removeShowListener(listener) {
    this._showListeners.delete(listener);
  }

  /**
   * Returns whether user preferences indicate that notifications
   * should be ignored.
   * @return {boolean}
   */
  shouldIgnoreNotifications() {
    return this.ignored ||
      Prefs.notifications_ignoredcategories.includes("*");
  }

  /**
   * Returns all local and remote notifications.
   * @returns {Array.<Object>} All local and remote notifications.
   * @private
   */
  _getNotifications() {
    let remoteNotifications = [];
    if (typeof Prefs.notificationdata.data == "object" &&
        Prefs.notificationdata.data.notifications instanceof Array)
      remoteNotifications = Prefs.notificationdata.data.notifications;

    return [...this._localNotifications, ...remoteNotifications];
  }

  /**
   * Determines which notification is to be shown next.
   * @returns {?object} The notification to be shown, or `null` if there is
   *   none.
   * @private
   */
  _getNextToShow() {
    let notifications = this._getNotifications();
    if (notifications.length == 0)
      return null;

    const {addonName, addonVersion, application, applicationVersion,
           platform, platformVersion} = __nested_webpack_require_431223__(/*! info */ "./sdk/api/info.js");

    let {numBlocked} = this;
    // Compatibility for legacy adblockpluschrome
    if ("blocked_total" in Prefs)
      numBlocked = Prefs.blocked_total;
    if (Prefs.show_statsinpopup === false)
      numBlocked = null;

    let targetChecks = {
      extension: v => v == addonName,
      extensionMinVersion:
        v => compareVersions(addonVersion, v) >= 0,
      extensionMaxVersion:
        v => compareVersions(addonVersion, v) <= 0,
      application: v => v == application,
      applicationMinVersion:
        v => compareVersions(applicationVersion, v) >= 0,
      applicationMaxVersion:
        v => compareVersions(applicationVersion, v) <= 0,
      platform: v => v == platform,
      platformMinVersion:
        v => compareVersions(platformVersion, v) >= 0,
      platformMaxVersion:
        v => compareVersions(platformVersion, v) <= 0,
      blockedTotalMin: v => numBlocked != null && numBlocked >= v,
      blockedTotalMax: v => numBlocked != null && numBlocked <= v,
      locales: v => v.includes(this.locale)
    };

    let notificationToShow = null;
    for (let notification of notifications) {
      if (notification.type != "critical") {
        let shown;
        if (typeof Prefs.notificationdata.shown == "object")
          shown = Prefs.notificationdata.shown[notification.id];

        if (typeof shown != "undefined") {
          if (typeof notification.interval == "number") {
            if (shown + notification.interval > Date.now())
              continue;
          }
          else if (shown) {
            continue;
          }
        }

        if (notification.type != "relentless" &&
            this.shouldIgnoreNotifications())
          continue;
      }

      if (notification.targets instanceof Array) {
        let match = false;

        for (let target of notification.targets) {
          let keys = Object.keys(target);
          if (keys.every(
            key => Object.prototype.hasOwnProperty.call(targetChecks, key) &&
                   targetChecks[key](target[key]))
          ) {
            match = true;
            break;
          }
        }

        if (!match)
          continue;
      }

      if (!notificationToShow || getNumericalSeverity(notification) >
                                 getNumericalSeverity(notificationToShow))
        notificationToShow = notification;
    }

    return notificationToShow;
  }

  /**
   * Shows a notification once.
   * @param {Object} notification The notification to show.
   * @param {Object} [options]
   * @param {boolean} [options.ignorable=false] If true, user preference will
   *   be considered to determine whether notification should be shown.
   */
  showNotification(notification, options = {}) {
    if (options.ignorable && this.shouldIgnoreNotifications())
      return;

    for (let showListener of this._showListeners)
      showListener(notification);
  }

  /**
   * Invokes the listeners added via
   * `{@link module:notifications~Notifications#addShowListener
   *         addShowListener()}` with the next notification to be shown.
   *
   * This method should be called whenever a page loads.
   */
  showNext() {
    let notification = this._getNextToShow();
    if (notification) {
      for (let showListener of this._showListeners)
        showListener(notification);
    }
  }

  /**
   * Marks a notification as shown.
   * @param {string} id The ID of the notification to be marked as shown.
   */
  markAsShown(id) {
    let notifications = this._getNotifications();

    // Ignore if there's no notification with the given ID.
    if (!notifications.some(notification => notification.id == id))
      return;

    let now = Date.now();
    let data = Prefs.notificationdata;

    if (data.shown instanceof Array) {
      let newShown = {};
      for (let oldId of data.shown)
        newShown[oldId] = now;
      data.shown = newShown;
    }

    if (typeof data.shown != "object")
      data.shown = {};

    data.shown[id] = now;

    saveNotificationData();
  }

  /**
   * Localizes the texts of the given notification based on the
   * {@link module:notifications~Notifications#locale locale}.
   * @param {Object} notification The notification.
   * @returns {Object} The localized texts.
   */
  getLocalizedTexts(notification) {
    let textKeys = ["title", "message"];
    let localizedTexts = {};

    for (let key of textKeys) {
      if (key in notification) {
        if (typeof notification[key] == "string")
          localizedTexts[key] = notification[key];
        else
          localizedTexts[key] = localize(notification[key], this.locale);
      }
    }

    return localizedTexts;
  }

  /**
   * Adds a local notification.
   * @param {Object} notification The notification to add.
   */
  addNotification(notification) {
    if (!isValidNotification(notification))
      throw new Error(`Invalid notification with ID "${notification.id}"`);

    this._localNotifications.add(notification);
  }

  /**
   * Removes an existing local notification.
   * @param {Object} notification The notification to remove.
   */
  removeNotification(notification) {
    this._localNotifications.delete(notification);
  }

  /**
   * Toggles whether notifications of a specific category should be ignored.
   * @param {string} category The notification category identifier.
   * @param {boolean} [forceValue] Whether to force the specified value.
   */
  toggleIgnoreCategory(category, forceValue) {
    let categories = Prefs.notifications_ignoredcategories;
    let index = categories.indexOf(category);
    if (index == -1 && forceValue != false) {
      categories.push(category);
      Prefs.notifications_ignoredcategories = categories;
      this.emit("ignored-category-added", category);
    }
    else if (index != -1 && forceValue != true) {
      categories.splice(index, 1);
      Prefs.notifications_ignoredcategories = categories;
      this.emit("ignored-category-removed", category);
    }

    saveNotificationData("notifications_ignoredcategories");
  }

  /**
   * Returns the number of times the notifications data have been downloaded.
   * @returns {number}
   */
  getDownloadCount() {
    return Prefs.notificationdata.downloadCount || 0;
  }

  /**
   * Returns the list of ignored categories.
   * @returns {Array.<string>}
   */
  getIgnoredCategories() {
    return Prefs.notifications_ignoredcategories;
  }
}

/**
 * Regularly fetches notifications and decides which notification to show.
 * @type {module:notifications~Notifications}
 */
exports.notifications = new Notifications();


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/patterns.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/patterns.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * The maximum number of patterns that
 * `{@link module:patterns.compilePatterns compilePatterns()}` will compile
 * into regular expressions.
 * @type {number}
 */
const COMPILE_PATTERNS_MAX = 100;

/**
 * Regular expression used to match the `^` suffix in an otherwise literal
 * pattern.
 * @type {RegExp}
 */
let separatorRegExp = /[\x00-\x24\x26-\x2C\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]/;

let filterToRegExp =
/**
 * Converts filter text into regular expression string
 * @param {string} text as in Filter()
 * @return {string} regular expression representation of filter text
 * @package
 */
exports.filterToRegExp = function filterToRegExp(text) {
  // remove multiple wildcards
  text = text.replace(/\*+/g, "*");

  // remove leading wildcard
  if (text[0] == "*")
    text = text.substring(1);

  // remove trailing wildcard
  if (text[text.length - 1] == "*")
    text = text.substring(0, text.length - 1);

  return text
    // remove anchors following separator placeholder
    .replace(/\^\|$/, "^")
    // escape special symbols
    .replace(/\W/g, "\\$&")
    // replace wildcards by .*
    .replace(/\\\*/g, ".*")
    // process separator placeholders (all ANSI characters but alphanumeric
    // characters and _%.-)
    .replace(/\\\^/g, `(?:${separatorRegExp.source}|$)`)
    // process extended anchor at expression start
    .replace(/^\\\|\\\|/, "^[\\w\\-]+:\\/+(?:[^\\/]+\\.)?")
    // process anchor at expression start
    .replace(/^\\\|/, "^")
    // process anchor at expression end
    .replace(/\\\|$/, "$");
};

/**
 * Regular expression used to match the `||` prefix in an otherwise literal
 * pattern.
 * @type {RegExp}
 */
let extendedAnchorRegExp = new RegExp(filterToRegExp("||") + "$");

/**
 * Regular expression for matching a keyword in a filter.
 * @type {RegExp}
 */
let keywordRegExp = /[^a-z0-9%*][a-z0-9%]{2,}(?=[^a-z0-9%*])/;

/**
 * Regular expression for matching all keywords in a filter.
 * @type {RegExp}
 */
let allKeywordsRegExp = new RegExp(keywordRegExp, "g");

/**
 * A `CompiledPatterns` object represents the compiled version of multiple URL
 * request patterns. It is returned by
 * `{@link module:patterns.compilePatterns compilePatterns()}`.
 */
class CompiledPatterns {
  /**
   * Creates an object with the given regular expressions for case-sensitive
   * and case-insensitive matching respectively.
   * @param {?RegExp} [caseSensitive]
   * @param {?RegExp} [caseInsensitive]
   * @private
   */
  constructor(caseSensitive, caseInsensitive) {
    this._caseSensitive = caseSensitive;
    this._caseInsensitive = caseInsensitive;
  }

  /**
   * Tests whether the given URL request matches the patterns used to create
   * this object.
   * @param {module:url.URLRequest} request
   * @returns {boolean}
   */
  test(request) {
    return ((this._caseSensitive &&
             this._caseSensitive.test(request.href)) ||
            (this._caseInsensitive &&
             this._caseInsensitive.test(request.lowerCaseHref)));
  }
}

/**
 * Compiles patterns from the given filters into a single
 * `{@link module:patterns~CompiledPatterns CompiledPatterns}` object.
 *
 * @param {module:filterClasses.URLFilter|
 *         Set.<module:filterClasses.URLFilter>} filters
 *   The filters. If the number of filters exceeds
 *   `{@link module:patterns~COMPILE_PATTERNS_MAX COMPILE_PATTERNS_MAX}`, the
 *   function returns `null`.
 *
 * @returns {?module:patterns~CompiledPatterns}
 *
 * @package
 */
exports.compilePatterns = function compilePatterns(filters) {
  let list = Array.isArray(filters) ? filters : [filters];

  // If the number of filters is too large, it may choke especially on low-end
  // platforms. As a precaution, we refuse to compile. Ideally we would check
  // the length of the regular expression source rather than the number of
  // filters, but this is far more straightforward and practical.
  if (list.length > COMPILE_PATTERNS_MAX)
    return null;

  let caseSensitive = "";
  let caseInsensitive = "";

  for (let filter of filters) {
    let source = filter.urlPattern.regexpSource;

    if (filter.matchCase)
      caseSensitive += source + "|";
    else
      caseInsensitive += source + "|";
  }

  let caseSensitiveRegExp = null;
  let caseInsensitiveRegExp = null;

  try {
    if (caseSensitive)
      caseSensitiveRegExp = new RegExp(caseSensitive.slice(0, -1));

    if (caseInsensitive)
      caseInsensitiveRegExp = new RegExp(caseInsensitive.slice(0, -1));
  }
  catch (error) {
    // It is possible in theory for the regular expression to be too large
    // despite COMPILE_PATTERNS_MAX
    return null;
  }

  return new CompiledPatterns(caseSensitiveRegExp, caseInsensitiveRegExp);
};

/**
 * Patterns for matching against URLs.
 *
 * Internally, this may be a RegExp or match directly against the
 * pattern for simple literal patterns.
 */
exports.Pattern = class Pattern {
  /**
   * @param {string} pattern pattern that requests URLs should be
   * matched against in filter text notation
   * @param {bool} matchCase `true` if comparisons must be case
   * sensitive
   */
  constructor(pattern, matchCase) {
    this.matchCase = matchCase || false;

    if (!this.matchCase)
      pattern = pattern.toLowerCase();

    if (pattern.length >= 2 &&
        pattern[0] == "/" &&
        pattern[pattern.length - 1] == "/") {
      // The filter is a regular expression - convert it immediately to
      // catch syntax errors
      pattern = pattern.substring(1, pattern.length - 1);
      this._regexp = new RegExp(pattern);
    }
    else {
      // Patterns like /foo/bar/* exist so that they are not treated as regular
      // expressions. We drop any superfluous wildcards here so our
      // optimizations can kick in.
      pattern = pattern.replace(/^\*+/, "").replace(/\*+$/, "");

      // No need to convert this filter to regular expression yet, do it on
      // demand
      this.pattern = pattern;
    }
  }

  /**
   * Checks whether the pattern is a string of literal characters with
   * no wildcards or any other special characters.
   *
   * If the pattern is prefixed with a `||` or suffixed with a `^` but otherwise
   * contains no special characters, it is still considered to be a literal
   * pattern.
   *
   * @returns {boolean}
   */
  isLiteralPattern() {
    return typeof this.pattern !== "undefined" &&
      !/[*^|]/.test(this.pattern.replace(/^\|{1,2}/, "").replace(/[|^]$/, ""));
  }

  /**
   * Regular expression to be used when testing against this pattern.
   *
   * null if the pattern is matched without using regular expressions.
   * @type {RegExp}
   */
  get regexp() {
    if (typeof this._regexp == "undefined") {
      this._regexp = this.isLiteralPattern() ?
        null : new RegExp(filterToRegExp(this.pattern));
    }
    return this._regexp;
  }

  /**
   * Pattern in regular expression notation. This will have a value
   * even if `regexp` returns null.
   * @type {string}
   */
  get regexpSource() {
    return this._regexp ? this._regexp.source : filterToRegExp(this.pattern);
  }

  /**
   * Checks whether the given URL request matches this filter's pattern.
   * @param {module:url.URLRequest} request The URL request to check.
   * @returns {boolean} `true` if the URL request matches.
   */
  matchesLocation(request) {
    let location = this.matchCase ? request.href : request.lowerCaseHref;
    let regexp = this.regexp;
    if (regexp)
      return regexp.test(location);

    let pattern = this.pattern;
    let startsWithAnchor = pattern[0] == "|";
    let startsWithExtendedAnchor = startsWithAnchor && pattern[1] == "|";
    let endsWithSeparator = pattern[pattern.length - 1] == "^";
    let endsWithAnchor = !endsWithSeparator &&
        pattern[pattern.length - 1] == "|";

    if (startsWithExtendedAnchor)
      pattern = pattern.substr(2);
    else if (startsWithAnchor)
      pattern = pattern.substr(1);

    if (endsWithSeparator || endsWithAnchor)
      pattern = pattern.slice(0, -1);

    let index = location.indexOf(pattern);

    while (index != -1) {
      // The "||" prefix requires that the text that follows does not start
      // with a forward slash.
      if ((startsWithExtendedAnchor ?
           location[index] != "/" &&
           extendedAnchorRegExp.test(location.substring(0, index)) :
           startsWithAnchor ?
           index == 0 :
           true) &&
          (endsWithSeparator ?
           !location[index + pattern.length] ||
           separatorRegExp.test(location[index + pattern.length]) :
           endsWithAnchor ?
           index == location.length - pattern.length :
           true))
        return true;

      if (pattern == "")
        return true;

      index = location.indexOf(pattern, index + 1);
    }

    return false;
  }

  /**
   * Checks whether the pattern has keywords
   * @returns {boolean}
   */
  hasKeywords() {
    return this.pattern && keywordRegExp.test(this.pattern);
  }

  /**
   * Finds all keywords that could be associated with this pattern
   * @returns {string[]}
   */
  keywordCandidates() {
    if (!this.pattern)
      return null;
    return this.pattern.toLowerCase().match(allKeywordsRegExp);
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/polyfill.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/polyfill.js ***!
  \******************************************************/
/***/ (() => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



// Promise.prototype.finally is not supported in Firefox < 58
if (!Promise.prototype.finally) {
  Promise.prototype.finally = function(fn) {
    return this.then(fn, fn);
  };
}


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/profiler.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/profiler.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_461973__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/* eslint no-console: "off" */
/* global self */

/** @module */



const {performance, PerformanceObserver} = __nested_webpack_require_461973__(/*! perf_hooks */ "perf_hooks");

/**
 * Default profiler("...") returned object when profile mode is disabled.
 * @type {Profiler}
 * @private
 */
let noopProfiler = {
  start() {},
  mark() {},
  end() {},
  toString() {
    return "{start(){},mark(){},end(){}}";
  }
};

let inactiveProfiling = true;
let obs = null;

/** Enable or disable profiling
 *
 * @param {bool} enable the profiling is enabled. If true it will
 * create a PerformanceObserver and start observing, profiler() will then
 * create a proper profiler object. If false, observing is cancelled and
 * the profiler object will be a noop.
 * @param {?Function} reporter The reporter function called by the observer.
 * If falsy, the default reporter will be used.
 */
function enableProfiling(enable, reporter) {
  inactiveProfiling = !enable;
  if (enable) {
    performance.mark("start_profile");
    if (!reporter) {
      reporter = list => {
        for (let entry of list.getEntriesByType("measure"))
          console.log(`${entry.name}: ${entry.duration}ms`);
      };
    }
    obs = new PerformanceObserver(reporter);

    obs.observe({entryTypes: ["measure"]});
  }
  else if (obs) {
    obs.disconnect();
    obs = null;
  }
}

/**
 * Create a profiler object with `start()` `mark()` and `end()` methods to
 * either start, keep marking a specific profiled name, or ending it.
 *
 * @example
 * let {mark, end} = profiler('console.log');
 * mark();
 * console.log(1, 2, 3);
 * end();
 *
 * @param {string} id the unique ID to profile.
 * @returns {Profiler} The profiler with `start()`, `mark()` and
 * `end(clear = false)` methods.
 * @private
 */
function profiler(id) {
  if (inactiveProfiling)
    return noopProfiler;

  return {
    id,
    start() {
      performance.mark(`${id}:start`);
      performance.measure(`${id}:startup`, "start_profile", `${id}:start`);
    },
    mark(event) {
      performance.mark(`${id}:${event}`);
      performance.measure(
        `${id}:${event}_measure`, "start_profile", `${id}:${event}`
      );
    },
    end() {
      performance.mark(`${id}:end`);
      performance.measure(id, "start_profile", `${id}:end`);
    }
  };
}

function isProfilingEnabled() {
  return !inactiveProfiling;
}

exports.profiler = profiler;
exports.enable = enableProfiling;
exports.isEnabled = isProfilingEnabled;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/recommendations.js":
/*!*************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/recommendations.js ***!
  \*************************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_465482__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * A `Recommendation` object represents a recommended filter subscription.
 */
class Recommendation {
  /**
   * Creates a `Recommendation` object from the given source object.
   * @param {object} source The source object.
   * @private
   */
  constructor(source) {
    this._source = source;
  }

  /**
   * The id (UUID) of the subscription.
   * If the id is not null, there is a 1:1 relationship with `id` : `url`.
   * @type {?string}
   */
  get id() {
    return this._source.id;
  }

  /**
   * The required subscription ids.
   * @type {?Array.<string>}
   */
  get requires() {
    return this._source.requires;
  }

  /**
   * The type of the recommended filter subscription.
   * @type {string}
   */
  get type() {
    return this._source.type;
  }

  /**
   * The languages of the recommended filter subscription.
   * @type {Array.<string>}
   */
  get languages() {
    return this._source.languages ? [...this._source.languages] : [];
  }

  /**
   * The title of the recommended filter subscription.
   * @type {string}
   */
  get title() {
    return this._source.title;
  }

  /**
   * The URL of the recommended filter subscription.
   * @type {string}
   */
  get url() {
    return this._source.url;
  }

  /**
   * The home page of the recommended filter subscription.
   * @type {string}
   */
  get homepage() {
    return this._source.homepage;
  }

  /**
   * The manifest v2 URL
   * @type {?string}
   */
  get mv2URL() {
    return this._source.mv2_url;
  }
}

let _recommendations = null;

/**
 * Set the recommendations. This is required. It should be done before
 * any other operation on subscriptions, and shouldn't be called more
 * than once.
 *
 * @param {object} recommendations The available recommended subscriptions.
 */
exports.setRecommendations = function(recommendations) {
  _recommendations = recommendations;
};

/**
 * Yields `{@link module:recommendations~Recommendation Recommendation}` objects
 * representing recommended filter subscriptions.
 *
 * @generator
 * @yields {module:recommendations~Recommendation} An object representing a
 *   recommended filter subscription.
 */
exports.recommendations = function* recommendations() {
  if (!_recommendations)
    _recommendations = __nested_webpack_require_465482__(/*! ../data/subscriptions.json */ "./node_modules/adblockpluscore/data/subscriptions.json");

  for (let source of _recommendations)
    yield new Recommendation(source);
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/rsa.js":
/*!*************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/rsa.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_468946__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/* global crypto, TextEncoder */

/** @module */



const Rusha = __nested_webpack_require_468946__(/*! ./rusha.js */ "./node_modules/adblockpluscore/lib/rusha.js");
const {BigInteger} = __nested_webpack_require_468946__(/*! ./jsbn.js */ "./node_modules/adblockpluscore/lib/jsbn.js");

/**
 * @file Provides ASN.1 sitekeys verifications.
 */

let base64ToArrayBuffer =
/**
 * Converts a base64 string to an array buffer byte array.
 * @param {string} base64 Base64 encoded string.
 * @return {Uint8Array} The same data, encoded as an array buffer.
 */
exports.base64ToArrayBuffer = function base64ToArrayBuffer(base64) {
  let binaryString = atob(base64);
  return Uint8Array.from(binaryString, c => c.charCodeAt(0));
};

/**
 * Converts an array buffer byte array into a base64 string.
 * @param {Uint8Array} buffer Byte array of any data.
 * @return {string} The same data, encoded as a base64 string.
 */
exports.arrayBufferToBase64 = function arrayBufferToBase64(buffer) {
  let binary = "";
  let bytes = new Uint8Array(buffer);
  for (let i = 0; i < bytes.byteLength; i++)
    binary += String.fromCharCode(bytes[i]);

  return btoa(binary);
};

/**
 * Checks whether the signature is valid for the given public key and data.
 * The verification is based on ASN.1 over SHA-1. This procedure is known as
 * RSA_PKCS1_SHA1 and it is the default kind of procedure, in OpenSSL, when
 * SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE is used to create the key/signature pair.
 * @param {string} key a base 64 public key used to verify.
 * @param {string} signature a base 64 signature used to verify.
 * @param {string} data a unique identifier of the resource to verify.
 * @returns {Promise<boolean>} resolves with true if the signature is valid
 */
exports.verifySignature = async function verifySignature(key, signature, data) {
  let signAlgorithm = {
    name: "RSASSA-PKCS1-v1_5",
    hash: {name: "SHA-1"}
  };
  try {
    return await crypto.subtle.verify(
      signAlgorithm,
      await crypto.subtle.importKey(
        "spki",
        base64ToArrayBuffer(key),
        signAlgorithm,
        true,
        ["verify"]
      ),
      base64ToArrayBuffer(signature),
      new TextEncoder().encode(data)
    );
  }
  catch ({message}) {
    console.warn("Invalid encrypted signature: " + message);
    return false;
  }
};

// Define ASN.1 templates for the data structures used
function seq(...args) {
  return {type: 0x30, children: args};
}
function obj(id) {
  return {type: 0x06, content: id};
}
function bitStr(contents) {
  return {type: 0x03, encapsulates: contents};
}
function intResult(id) {
  return {type: 0x02, out: id};
}
function octetResult(id) {
  return {type: 0x04, out: id};
}

// See http://www.cryptopp.com/wiki/Keys_and_Formats#RSA_PublicKey
// 2A 86 48 86 F7 0D 01 01 01 means 1.2.840.113549.1.1.1
let publicKeyTemplate = seq(
  seq(obj("\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01"), {}),
  bitStr(seq(intResult("n"), intResult("e")))
);

// See http://tools.ietf.org/html/rfc3447#section-9.2 step 2
// 2B 0E 03 02 1A means 1.3.14.3.2.26
let signatureTemplate = seq(
  seq(obj("\x2B\x0E\x03\x02\x1A"), {}),
  octetResult("sha1")
);

/**
 * Reads ASN.1 data matching the template passed in. This will throw an
 * exception if the data format doesn't match the template. On success an
 * object containing result properties is returned.
 * @see http://luca.ntop.org/Teaching/Appunti/asn1.html for info on the format.
 * @param {string} data
 * @param {Object} templ
 * @returns {Object}
 */
function readASN1(data, templ) {
  let pos = 0;
  function next() {
    return data.charCodeAt(pos++);
  }

  function readLength() {
    let len = next();
    if (len & 0x80) {
      let cnt = len & 0x7F;
      if (cnt > 2 || cnt == 0)
        throw "Unsupported length";

      len = 0;
      for (let i = 0; i < cnt; i++)
        len += next() << (cnt - 1 - i) * 8;
      return len;
    }
    return len;
  }

  function readNode(curTempl) {
    let type = next();
    let len = readLength();
    if ("type" in curTempl && curTempl.type != type)
      throw "Unexpected type";
    if ("content" in curTempl &&
        curTempl.content != data.substring(pos, pos + len))
      throw "Unexpected content";
    if ("out" in curTempl)
      out[curTempl.out] = new BigInteger(data.substring(pos, pos + len), 256);
    if ("children" in curTempl) {
      let i;
      let end;
      for (i = 0, end = pos + len; pos < end; i++) {
        if (i >= curTempl.children.length)
          throw "Too many children";
        readNode(curTempl.children[i]);
      }
      if (i < curTempl.children.length)
        throw "Too few children";
      if (pos > end)
        throw "Children too large";
    }
    else if ("encapsulates" in curTempl) {
      if (next() != 0)
        throw "Encapsulation expected";
      readNode(curTempl.encapsulates);
    }
    else {
      pos += len;
    }
  }

  let out = {};
  readNode(templ);
  if (pos != data.length)
    throw "Too much data";
  return out;
}

/**
 * Reads a BER-encoded RSA public key. On success returns an object with the
 * properties n and e (the components of the key), otherwise null.
 * @param {string} key
 * @return {?Object}
 */
function readPublicKey(key) {
  try {
    return readASN1(atob(key), publicKeyTemplate);
  }
  catch (e) {
    console.warn("Invalid RSA public key: " + e);
    return null;
  }
}

let rusha;

/**
 * Checks whether the signature is valid for the given public key and data.
 * The verification is based on ASN.1 over SHA-1. This procedure is known as
 * RSA_PKCS1_SHA1 and it is the default kind of procedure, in OpenSSL, when
 * SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE is used to create the key/signature pair.
 *
 * This function is synchronous, and so does not return a
 * promise. It's recommended to use the asynchronous version,
 * `{@link module:rsa.verifySignature verifySignature}`, if possible.
 * @param {string} key a base 64 public key used to verify.
 * @param {string} signature a base 64 signature used to verify.
 * @param {string} data a unique identifier of the resource to verify.
 * @returns {boolean} true if the signature is valid.
 */
exports.verifySignatureSync =
function verifySignatureSync(key, signature, data) {
  if (typeof rusha == "undefined")
    rusha = new Rusha();

  let keyData = readPublicKey(key);
  if (!keyData)
    return false;

  // We need the exponent as regular number
  keyData.e = parseInt(keyData.e.toString(16), 16);

  // Decrypt signature data using RSA algorithm
  let sigInt = new BigInteger(atob(signature), 256);
  let digest = sigInt.modPowInt(keyData.e, keyData.n).toString(256);

  try {
    let pos = 0;
    let next = () => digest.charCodeAt(pos++);

    // Skip padding, see http://tools.ietf.org/html/rfc3447#section-9.2 step 5
    if (next() != 1)
      throw "Wrong padding in signature digest";
    while (next() == 255) {}
    if (digest.charCodeAt(pos - 1) != 0)
      throw "Wrong padding in signature digest";

    // Rest is an ASN.1 structure, get the SHA1 hash from it and compare to
    // the real one
    let {sha1} = readASN1(digest.substring(pos), signatureTemplate);
    let expected = new BigInteger(rusha.digest(data), 16);
    return (sha1.compareTo(expected) == 0);
  }
  catch (e) {
    console.warn("Invalid encrypted signature: " + e);
    return false;
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/rusha.js":
/*!***************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/rusha.js ***!
  \***************************************************/
/***/ ((module, exports, __nested_webpack_require_477254__) => {

(function () {
    var /*
 * Rusha, a JavaScript implementation of the Secure Hash Algorithm, SHA-1,
 * as defined in FIPS PUB 180-1, tuned for high performance with large inputs.
 * (http://github.com/srijs/rusha)
 *
 * Inspired by Paul Johnstons implementation (http://pajhome.org.uk/crypt/md5).
 *
 * Copyright (c) 2013 Sam Rijs (http://awesam.de).
 * Released under the terms of the MIT license as follows:
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 * IN THE SOFTWARE.
 */
    util = {
        getDataType: function (data) {
            if (typeof data === 'string') {
                return 'string';
            }
            if (data instanceof Array) {
                return 'array';
            }
            if (typeof __nested_webpack_require_477254__.g !== 'undefined' && __nested_webpack_require_477254__.g.Buffer && __nested_webpack_require_477254__.g.Buffer.isBuffer(data)) {
                return 'buffer';
            }
            if (data instanceof ArrayBuffer) {
                return 'arraybuffer';
            }
            if (data.buffer instanceof ArrayBuffer) {
                return 'view';
            }
            if (data instanceof Blob) {
                return 'blob';
            }
            throw new Error('Unsupported data type.');
        }
    };
    function Rusha(chunkSize) {
        'use strict';
        var // Private object structure.
        self$2 = { fill: 0 };
        var // Calculate the length of buffer that the sha1 routine uses
        // including the padding.
        padlen = function (len) {
            for (len += 9; len % 64 > 0; len += 1);
            return len;
        };
        var padZeroes = function (bin, len) {
            for (var i$2 = len >> 2; i$2 < bin.length; i$2++)
                bin[i$2] = 0;
        };
        var padData = function (bin, chunkLen, msgLen) {
            bin[chunkLen >> 2] |= 128 << 24 - (chunkLen % 4 << 3);
            // To support msgLen >= 2 GiB, use a float division when computing the
            // high 32-bits of the big-endian message length in bits.
            bin[((chunkLen >> 2) + 2 & ~15) + 14] = msgLen / (1 << 29) | 0;
            bin[((chunkLen >> 2) + 2 & ~15) + 15] = msgLen << 3;
        };
        var // Convert a binary string and write it to the heap.
        // A binary string is expected to only contain char codes < 256.
        convStr = function (H8, H32, start, len, off) {
            var str = this, i$2, om = off % 4, lm = len % 4, j = len - lm;
            if (j > 0) {
                switch (om) {
                case 0:
                    H8[off + 3 | 0] = str.charCodeAt(start);
                case 1:
                    H8[off + 2 | 0] = str.charCodeAt(start + 1);
                case 2:
                    H8[off + 1 | 0] = str.charCodeAt(start + 2);
                case 3:
                    H8[off | 0] = str.charCodeAt(start + 3);
                }
            }
            for (i$2 = om; i$2 < j; i$2 = i$2 + 4 | 0) {
                H32[off + i$2 >> 2] = str.charCodeAt(start + i$2) << 24 | str.charCodeAt(start + i$2 + 1) << 16 | str.charCodeAt(start + i$2 + 2) << 8 | str.charCodeAt(start + i$2 + 3);
            }
            switch (lm) {
            case 3:
                H8[off + j + 1 | 0] = str.charCodeAt(start + j + 2);
            case 2:
                H8[off + j + 2 | 0] = str.charCodeAt(start + j + 1);
            case 1:
                H8[off + j + 3 | 0] = str.charCodeAt(start + j);
            }
        };
        var // Convert a buffer or array and write it to the heap.
        // The buffer or array is expected to only contain elements < 256.
        convBuf = function (H8, H32, start, len, off) {
            var buf = this, i$2, om = off % 4, lm = len % 4, j = len - lm;
            if (j > 0) {
                switch (om) {
                case 0:
                    H8[off + 3 | 0] = buf[start];
                case 1:
                    H8[off + 2 | 0] = buf[start + 1];
                case 2:
                    H8[off + 1 | 0] = buf[start + 2];
                case 3:
                    H8[off | 0] = buf[start + 3];
                }
            }
            for (i$2 = 4 - om; i$2 < j; i$2 = i$2 += 4 | 0) {
                H32[off + i$2 >> 2] = buf[start + i$2] << 24 | buf[start + i$2 + 1] << 16 | buf[start + i$2 + 2] << 8 | buf[start + i$2 + 3];
            }
            switch (lm) {
            case 3:
                H8[off + j + 1 | 0] = buf[start + j + 2];
            case 2:
                H8[off + j + 2 | 0] = buf[start + j + 1];
            case 1:
                H8[off + j + 3 | 0] = buf[start + j];
            }
        };
        var convBlob = function (H8, H32, start, len, off) {
            var blob = this, i$2, om = off % 4, lm = len % 4, j = len - lm;
            var buf = new Uint8Array(reader.readAsArrayBuffer(blob.slice(start, start + len)));
            if (j > 0) {
                switch (om) {
                case 0:
                    H8[off + 3 | 0] = buf[0];
                case 1:
                    H8[off + 2 | 0] = buf[1];
                case 2:
                    H8[off + 1 | 0] = buf[2];
                case 3:
                    H8[off | 0] = buf[3];
                }
            }
            for (i$2 = 4 - om; i$2 < j; i$2 = i$2 += 4 | 0) {
                H32[off + i$2 >> 2] = buf[i$2] << 24 | buf[i$2 + 1] << 16 | buf[i$2 + 2] << 8 | buf[i$2 + 3];
            }
            switch (lm) {
            case 3:
                H8[off + j + 1 | 0] = buf[j + 2];
            case 2:
                H8[off + j + 2 | 0] = buf[j + 1];
            case 1:
                H8[off + j + 3 | 0] = buf[j];
            }
        };
        var convFn = function (data) {
            switch (util.getDataType(data)) {
            case 'string':
                return convStr.bind(data);
            case 'array':
                return convBuf.bind(data);
            case 'buffer':
                return convBuf.bind(data);
            case 'arraybuffer':
                return convBuf.bind(new Uint8Array(data));
            case 'view':
                return convBuf.bind(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));
            case 'blob':
                return convBlob.bind(data);
            }
        };
        var slice = function (data, offset) {
            switch (util.getDataType(data)) {
            case 'string':
                return data.slice(offset);
            case 'array':
                return data.slice(offset);
            case 'buffer':
                return data.slice(offset);
            case 'arraybuffer':
                return data.slice(offset);
            case 'view':
                return data.buffer.slice(offset);
            }
        };
        var // Precompute 00 - ff strings
        precomputedHex = new Array(256);
        for (var i = 0; i < 256; i++) {
            precomputedHex[i] = (i < 16 ? '0' : '') + i.toString(16);
        }
        var // Convert an ArrayBuffer into its hexadecimal string representation.
        hex = function (arrayBuffer) {
            var binarray = new Uint8Array(arrayBuffer);
            var res = new Array(arrayBuffer.byteLength);
            for (var i$2 = 0; i$2 < res.length; i$2++) {
                res[i$2] = precomputedHex[binarray[i$2]];
            }
            return res.join('');
        };
        var ceilHeapSize = function (v) {
            // The asm.js spec says:
            // The heap object's byteLength must be either
            // 2^n for n in [12, 24) or 2^24 * n for n ≥ 1.
            // Also, byteLengths smaller than 2^16 are deprecated.
            var p;
            if (// If v is smaller than 2^16, the smallest possible solution
                // is 2^16.
                v <= 65536)
                return 65536;
            if (// If v < 2^24, we round up to 2^n,
                // otherwise we round up to 2^24 * n.
                v < 16777216) {
                for (p = 1; p < v; p = p << 1);
            } else {
                for (p = 16777216; p < v; p += 16777216);
            }
            return p;
        };
        var // Initialize the internal data structures to a new capacity.
        init = function (size) {
            if (size % 64 > 0) {
                throw new Error('Chunk size must be a multiple of 128 bit');
            }
            self$2.maxChunkLen = size;
            self$2.padMaxChunkLen = padlen(size);
            // The size of the heap is the sum of:
            // 1. The padded input message size
            // 2. The extended space the algorithm needs (320 byte)
            // 3. The 160 bit state the algoritm uses
            self$2.heap = new ArrayBuffer(ceilHeapSize(self$2.padMaxChunkLen + 320 + 20));
            self$2.h32 = new Int32Array(self$2.heap);
            self$2.h8 = new Int8Array(self$2.heap);
            self$2.core = new Rusha._core({
                Int32Array: Int32Array,
                DataView: DataView
            }, {}, self$2.heap);
            self$2.buffer = null;
        };
        // Initialize the data structures according
        // to a chunk size.
        init(chunkSize || 64 * 1024);
        var initState = function (heap, padMsgLen) {
            var io = new Int32Array(heap, padMsgLen + 320, 5);
            io[0] = 1732584193;
            io[1] = -271733879;
            io[2] = -1732584194;
            io[3] = 271733878;
            io[4] = -1009589776;
        };
        var padChunk = function (chunkLen, msgLen) {
            var padChunkLen = padlen(chunkLen);
            var view = new Int32Array(self$2.heap, 0, padChunkLen >> 2);
            padZeroes(view, chunkLen);
            padData(view, chunkLen, msgLen);
            return padChunkLen;
        };
        var // Write data to the heap.
        write = function (data, chunkOffset, chunkLen) {
            convFn(data)(self$2.h8, self$2.h32, chunkOffset, chunkLen, 0);
        };
        var // Initialize and call the RushaCore,
        // assuming an input buffer of length len * 4.
        coreCall = function (data, chunkOffset, chunkLen, msgLen, finalize) {
            var padChunkLen = chunkLen;
            if (finalize) {
                padChunkLen = padChunk(chunkLen, msgLen);
            }
            write(data, chunkOffset, chunkLen);
            self$2.core.hash(padChunkLen, self$2.padMaxChunkLen);
        };
        var getRawDigest = function (heap, padMaxChunkLen) {
            var io = new Int32Array(heap, padMaxChunkLen + 320, 5);
            var out = new Int32Array(5);
            var arr = new DataView(out.buffer);
            arr.setInt32(0, io[0], false);
            arr.setInt32(4, io[1], false);
            arr.setInt32(8, io[2], false);
            arr.setInt32(12, io[3], false);
            arr.setInt32(16, io[4], false);
            return out;
        };
        var // Calculate the hash digest as an array of 5 32bit integers.
        rawDigest = this.rawDigest = function (str) {
            var msgLen = str.byteLength || str.length || str.size || 0;
            initState(self$2.heap, self$2.padMaxChunkLen);
            var chunkOffset = 0, chunkLen = self$2.maxChunkLen, last;
            for (chunkOffset = 0; msgLen > chunkOffset + chunkLen; chunkOffset += chunkLen) {
                coreCall(str, chunkOffset, chunkLen, msgLen, false);
            }
            coreCall(str, chunkOffset, msgLen - chunkOffset, msgLen, true);
            return getRawDigest(self$2.heap, self$2.padMaxChunkLen);
        };
        // The digest and digestFrom* interface returns the hash digest
        // as a hex string.
        this.digest = this.digestFromString = this.digestFromBuffer = this.digestFromArrayBuffer = function (str) {
            return hex(rawDigest(str).buffer);
        };
    }
    ;
    // The low-level RushCore module provides the heart of Rusha,
    // a high-speed sha1 implementation working on an Int32Array heap.
    // At first glance, the implementation seems complicated, however
    // with the SHA1 spec at hand, it is obvious this almost a textbook
    // implementation that has a few functions hand-inlined and a few loops
    // hand-unrolled.
    Rusha._core = function RushaCore(stdlib, foreign, heap) {
        'use asm';
        var H = new stdlib.Int32Array(heap);
        function hash(k, x) {
            // k in bytes
            k = k | 0;
            x = x | 0;
            var i = 0, j = 0, y0 = 0, z0 = 0, y1 = 0, z1 = 0, y2 = 0, z2 = 0, y3 = 0, z3 = 0, y4 = 0, z4 = 0, t0 = 0, t1 = 0;
            y0 = H[x + 320 >> 2] | 0;
            y1 = H[x + 324 >> 2] | 0;
            y2 = H[x + 328 >> 2] | 0;
            y3 = H[x + 332 >> 2] | 0;
            y4 = H[x + 336 >> 2] | 0;
            for (i = 0; (i | 0) < (k | 0); i = i + 64 | 0) {
                z0 = y0;
                z1 = y1;
                z2 = y2;
                z3 = y3;
                z4 = y4;
                for (j = 0; (j | 0) < 64; j = j + 4 | 0) {
                    t1 = H[i + j >> 2] | 0;
                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
                    y4 = y3;
                    y3 = y2;
                    y2 = y1 << 30 | y1 >>> 2;
                    y1 = y0;
                    y0 = t0;
                    H[k + j >> 2] = t1;
                }
                for (j = k + 64 | 0; (j | 0) < (k + 80 | 0); j = j + 4 | 0) {
                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
                    y4 = y3;
                    y3 = y2;
                    y2 = y1 << 30 | y1 >>> 2;
                    y1 = y0;
                    y0 = t0;
                    H[j >> 2] = t1;
                }
                for (j = k + 80 | 0; (j | 0) < (k + 160 | 0); j = j + 4 | 0) {
                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) + 1859775393 | 0) | 0;
                    y4 = y3;
                    y3 = y2;
                    y2 = y1 << 30 | y1 >>> 2;
                    y1 = y0;
                    y0 = t0;
                    H[j >> 2] = t1;
                }
                for (j = k + 160 | 0; (j | 0) < (k + 240 | 0); j = j + 4 | 0) {
                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | y1 & y3 | y2 & y3) | 0) + ((t1 + y4 | 0) - 1894007588 | 0) | 0;
                    y4 = y3;
                    y3 = y2;
                    y2 = y1 << 30 | y1 >>> 2;
                    y1 = y0;
                    y0 = t0;
                    H[j >> 2] = t1;
                }
                for (j = k + 240 | 0; (j | 0) < (k + 320 | 0); j = j + 4 | 0) {
                    t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
                    t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) - 899497514 | 0) | 0;
                    y4 = y3;
                    y3 = y2;
                    y2 = y1 << 30 | y1 >>> 2;
                    y1 = y0;
                    y0 = t0;
                    H[j >> 2] = t1;
                }
                y0 = y0 + z0 | 0;
                y1 = y1 + z1 | 0;
                y2 = y2 + z2 | 0;
                y3 = y3 + z3 | 0;
                y4 = y4 + z4 | 0;
            }
            H[x + 320 >> 2] = y0;
            H[x + 324 >> 2] = y1;
            H[x + 328 >> 2] = y2;
            H[x + 332 >> 2] = y3;
            H[x + 336 >> 2] = y4;
        }
        return { hash: hash };
    };
    exports = Rusha;
    if (// If we'e running in Node.JS, export a module.
        true) {
        module.exports = Rusha;
    } else {}
    if (// If we're running in a webworker, accept
        // messages containing a jobid and a buffer
        // or blob object, and return the hash result.
        typeof FileReaderSync !== 'undefined') {
        var reader = new FileReaderSync(), hasher = new Rusha(4 * 1024 * 1024);
        self.onmessage = function onMessage(event) {
            var hash, data = event.data.data;
            try {
                hash = hasher.digest(data);
                self.postMessage({
                    id: event.data.id,
                    hash: hash
                });
            } catch (e) {
                self.postMessage({
                    id: event.data.id,
                    error: e.name
                });
            }
        };
    }
}());


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/snippets.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/snippets.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_495579__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Snippets implementation.
 */

const {EventEmitter} = __nested_webpack_require_495579__(/*! ./events */ "./node_modules/adblockpluscore/lib/events.js");

let singleCharacterEscapes = new Map([
  ["n", "\n"], ["r", "\r"], ["t", "\t"]
]);

/**
 * `{@link module:snippets.snippets snippets}` implementation.
 */
class Snippets extends EventEmitter {
  /**
   * @hideconstructor
   */
  constructor() {
    super();

    /**
     * All known snippet filters.
     * @type {Set.<module:filterClasses.SnippetFilter>}
     * @private
     */
    this._filters = new Set();
  }

  /**
   * Removes all known snippet filters.
   */
  clear() {
    let {_filters} = this;

    if (_filters.size == 0)
      return;

    _filters.clear();

    this.emit("snippets.filtersCleared");
  }

  /**
   * Adds a new snippet filter.
   * @param {module:filterClasses.SnippetFilter} filter
   */
  add(filter) {
    let {_filters} = this;
    let {size} = _filters;

    _filters.add(filter);

    if (size != _filters.size)
      this.emit("snippets.filterAdded", filter);
  }

  /**
   * Removes an existing snippet filter.
   * @param {module:filterClasses.SnippetFilter} filter
   */
  remove(filter) {
    let {_filters} = this;
    let {size} = _filters;

    _filters.delete(filter);

    if (size != _filters.size)
      this.emit("snippets.filterRemoved", filter);
  }

  /**
   * Checks whether a snippet filter exists.
   * @param {module:filterClasses.SnippetFilter} filter
   * @returns {boolean}
   */
  has(filter) {
    return this._filters.has(filter);
  }

  /**
   * Returns a list of all snippet filters active on the given domain.
   * @param {string} domain The domain.
   * @returns {Array.<module:filterClasses.SnippetFilter>} A list of snippet
   *   filters.
   */
  getFilters(domain) {
    let result = [];

    for (let filter of this._filters) {
      if (filter.isActiveOnDomain(domain))
        result.push(filter);
    }

    return result;
  }

  /**
   * Returns a list of all snippet filters active on the given domain.
   * @param {string} domain The domain.
   * @returns {Array.<module:filterClasses.SnippetFilter>} A list of snippet
   *   filters.
   *
   * @deprecated Use <code>{@link module:snippets~Snippets#getFilters}</code>
   *   instead.
   * @see module:snippets~Snippets#getFilters
   */
  getFiltersForDomain(domain) {
    return this.getFilters(domain);
  }
}

/**
 * Container for snippet filters.
 */
exports.Snippets = Snippets;

let parseScript =
/**
 * Parses a script and returns a list of all its commands and their arguments.
 * @param {string} script The script.
 * @returns {Array.<string[]>} A list of commands and their arguments.
 * @package
 */
exports.parseScript = function parseScript(script) {
  let tree = [];

  let escape = false;
  let withinQuotes = false;

  let unicodeEscape = null;

  let quotesClosed = false;

  let call = [];
  let argument = "";

  for (let character of script.trim() + ";") {
    let afterQuotesClosed = quotesClosed;
    quotesClosed = false;

    if (unicodeEscape != null) {
      unicodeEscape += character;

      if (unicodeEscape.length == 4) {
        let codePoint = parseInt(unicodeEscape, 16);
        if (!isNaN(codePoint))
          argument += String.fromCodePoint(codePoint);

        unicodeEscape = null;
      }
    }
    else if (escape) {
      escape = false;

      if (character == "u")
        unicodeEscape = "";
      else
        argument += singleCharacterEscapes.get(character) || character;
    }
    else if (character == "\\") {
      escape = true;
    }
    else if (character == "'") {
      withinQuotes = !withinQuotes;

      if (!withinQuotes)
        quotesClosed = true;
    }
    else if (withinQuotes || character != ";" && !/\s/.test(character)) {
      argument += character;
    }
    else {
      if (argument || afterQuotesClosed) {
        call.push(argument);
        argument = "";
      }

      if (character == ";" && call.length > 0) {
        tree.push(call);
        call = [];
      }
    }
  }

  return tree;
};

/**
 * Compiles a script against a given list of libraries, passed as JSON
 * serialized string, or a an array of strings, into executable code.
 * @param {string|Array.<string>} scripts One or more scripts to convert into
 *  executable code.
 * @param {string} isolatedSnippetsLibrary The stringified bundle to be executed
 * in the isolated content script context.
 * @param {string} injectedSnippetsLibrary The stringified bundle to be injected
 * and executed in the main context.
 * @param {string|Array.<string>} injectedSnippetsList An array containing the
 * available injectable snippets.
 * @param {object} [environment] An object containing environment variables.
 * @returns {string} Executable code.
 */
exports.compileScript = function compileScript(scripts,
                                               isolatedSnippetsLibrary,
                                               injectedSnippetsLibrary,
                                               injectedSnippetsList,
                                               environment = {}) {
  let isolatedLib = JSON.stringify(isolatedSnippetsLibrary);
  let injectedLib = JSON.stringify(injectedSnippetsLibrary);
  let jsonEnv = JSON.stringify(environment);
  return `
    "use strict";
    (() => 
    {
      let scripts = ${JSON.stringify([].concat(scripts).map(parseScript))};

      let isolatedLib = ${isolatedLib};
      let imports = Object.create(null);
      let injectedSnippetsCount = 0;
      let loadLibrary = new Function("exports", "environment", isolatedLib);
      loadLibrary(imports, ${jsonEnv});
      const isolatedSnippets = imports.snippets;

      let injectedLib = ${injectedLib};
      let injectedSnippetsList = ${JSON.stringify(injectedSnippetsList)};
      let executable = "(() => {";
      executable += "let environment = ${jsonEnv.replace(/[\\"]/g, "\\$&")};";
      executable += injectedLib;

      let {hasOwnProperty} = Object.prototype;
      for (let script of scripts)
      {
        for (let [name, ...args] of script)
        {
          if (hasOwnProperty.call(isolatedSnippets, name))
          {
            let value = isolatedSnippets[name];
            if (typeof value == "function")
              value(...args);
          }
          if (injectedSnippetsList.includes(name))
          {
            executable += stringifyFunctionCall(name, ...args);
            injectedSnippetsCount++;
          }
        }
      }

      executable += "})();";

      if (injectedSnippetsCount > 0)
        injectSnippetsInMainContext(executable);

      function stringifyFunctionCall(func, ...params)
      {
        // Call JSON.stringify on the arguments to avoid any arbitrary code
        // execution.
        const f = "snippets['" + func + "']";
        const parameters = params.map(JSON.stringify).join(",");
        return f + "(" + parameters + ");";
      }

      function injectSnippetsInMainContext(exec)
      {
        // injecting phase
        let script = document.createElement("script");
        script.type = "application/javascript";
        script.async = false;

        // Firefox 58 only bypasses site CSPs when assigning to 'src',
        // while Chrome 67 and Microsoft Edge (tested on 44.17763.1.0)
        // only bypass site CSPs when using 'textContent'.
        if (typeof netscape != "undefined" && typeof browser != "undefined")
        {
          let url = URL.createObjectURL(new Blob([exec]));
          script.src = url;
          document.documentElement.appendChild(script);
          URL.revokeObjectURL(url);
        }
        else
        {
          script.textContent = exec;
          document.documentElement.appendChild(script);
        }

        document.documentElement.removeChild(script);
      }
    })();
  `;
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/subscriptionClasses.js":
/*!*****************************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/subscriptionClasses.js ***!
  \*****************************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_504501__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Definition of Subscription class and its subclasses.
 */

const {recommendations} = __nested_webpack_require_504501__(/*! ./recommendations */ "./node_modules/adblockpluscore/lib/recommendations.js");
const {isActiveFilter, Filter} = __nested_webpack_require_504501__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");
const {filterNotifier} = __nested_webpack_require_504501__(/*! ./filterNotifier */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
const {Downloader} = __nested_webpack_require_504501__(/*! ./downloader */ "./node_modules/adblockpluscore/lib/downloader.js");
const {profiler} = __nested_webpack_require_504501__(/*! ./profiler */ "./node_modules/adblockpluscore/lib/profiler.js");

let _recommendationsByURL = null;

/**
 * Subscription recommendation by URL.
 *
 * If `Subscription.dnr` is falsey then the mv2URL is the actual URL
 * as we would have with manifest v2.
 *
 * @returns {Map.<string, Recommendation>}
 */
function recommendationsByURL() {
  if (!_recommendationsByURL) {
    if (Subscription.dnr) {
      _recommendationsByURL = new Map(
        (function*() {
          for (let recommendation of recommendations())
            yield [recommendation.url, recommendation];
        })()
      );
    }
    else {
      _recommendationsByURL = new Map(
        (function*() {
          for (let recommendation of recommendations()) {
            if (recommendation.mv2URL)
              yield [recommendation.mv2URL, recommendation];
          }
        })()
      );
    }
  }
  return _recommendationsByURL;
}

let _urlByMv2URL = null;

/**
 * Subscription URL by mv2_url.
 *
 * @returns {Map.<string, string>}
 */
function urlByMv2URL() {
  if (!_urlByMv2URL) {
    _urlByMv2URL = new Map(
      (function*() {
        for (let {mv2URL, url} of recommendations()) {
          if (mv2URL)
            yield [mv2URL, url];
        }
      })()
    );
  }
  return _urlByMv2URL;
}

let Subscription =
/**
 * The `Subscription` class represents a filter subscription.
 * @abstract
 */
exports.Subscription = class Subscription {
  /**
   * Creates a `Subscription` object.
   * @param {string} url The URL of the subscription.
   * @param {string} [title] The title of the subscription.
   * @private
   */
  constructor(url, title) {
    /**
     * The URL of the subscription.
     * @type {string}
     * @see module:subscriptionClasses.Subscription#url
     * @private
     */
    this._url = url;

    /**
     * Whether the URL of the subscription is a valid subscription URL.
     * @type {boolean}
     * @private
     * @see module:subscriptionClasses.Subscription#valid
     */
    this._urlValid = Subscription.isValidURL(url);

    let recommendation = recommendationsByURL().get(url);
    /**
     * The type of the subscription.
     * @type {?string}
     * @default <code>null</code>
     * @private
     * @see module:subscriptionClasses.Subscription#type
     */
    this._type = recommendation ? recommendation.type : null;

    /**
     * The id (UUID) of the subscription.
     * @type {?string}
     * @default <code>null</code>
     * @private
     */
    this._id = recommendation ? recommendation.id : null;

    /**
     * Filter text contained in the subscription.
     * @type {Array.<string>}
     * @private
     */
    this._filterText = [];

    /**
     * A searchable index of filter text in the subscription.
     * @type {Set.<string>}
     * @private
     */
    this._filterTextIndex = new Set();

    /**
     * The title of the subscription.
     * @type {?string}
     * @default <code>null</code>
     * @private
     * @see module:subscriptionClasses.Subscription#title
     */
    this._title = null;

    if (title)
      this._title = title;

    /**
     * Whether the title of the subscription is non-editable.
     * @type {boolean}
     * @default <code>false</code>
     * @private
     * @see module:subscriptionClasses.Subscription#fixedTitle
     */
    this._fixedTitle = false;

    /**
     * Whether the subscription is disabled.
     * @type {boolean}
     * @default <code>false</code>
     * @private
     * @see module:subscriptionClasses.Subscription#disabled
     */
    this._disabled = false;

    Subscription.knownSubscriptions.set(url, this);
  }

  /**
   * The id (UUID) of the subscription.
   * @type {string}
   */
  get id() {
    return this._id;
  }

  /**
   * The URL of the subscription.
   * @type {string}
   */
  get url() {
    return this._url;
  }

  /**
   * Whether the subscription is valid.
   * @type {boolean}
   * @package
   */
  get valid() {
    // This should return a value based on Subscription#_urlValid after
    // https://gitlab.com/eyeo/adblockplus/abpui/adblockplusui/-/issues/753
    return true;
  }

  /**
   * The type of the subscription.
   * @type {?string}
   * @default <code>null</code>
   */
  get type() {
    return this._type;
  }

  /**
   * True if this subscription can load filters that require
   * privileged access, like snippets.
   * @type {bool}
   */
  get privileged() {
    return this.type === "circumvention";
  }

  /**
   * The title of the subscription.
   * @type {string}
   */
  get title() {
    return this._title;
  }

  set title(value) {
    if (value != this._title) {
      let oldValue = this._title;
      this._title = value;
      filterNotifier.emit("subscription.title", this, value, oldValue);
    }
  }

  /**
   * Whether the title of the subscription is non-editable.
   * @type {boolean}
   * @default <code>false</code>
   */
  get fixedTitle() {
    return this._fixedTitle;
  }

  set fixedTitle(value) {
    if (value != this._fixedTitle) {
      let oldValue = this._fixedTitle;
      this._fixedTitle = value;
      filterNotifier.emit("subscription.fixedTitle", this, value, oldValue);
    }
  }

  /**
   * Whether the subscription is downloadable.
   * @type {boolean}
   * @default <code>false</code>
   */
  get downloadable() {
    return false;
  }

  /**
   * Whether the subscription is disabled.
   * @type {boolean}
   * @default <code>false</code>
   */
  get disabled() {
    return this._disabled;
  }

  set disabled(value) {
    if (value != this._disabled) {
      let oldValue = this._disabled;
      this._disabled = value;
      filterNotifier.emit("subscription.disabled", this, value, oldValue);
    }
  }

  /**
   * The number of filters in the subscription.
   * @type {number}
   * @default <code>0</code>
   */
  get filterCount() {
    return this._filterText.length;
  }

  /**
   * Returns an iterator that yields the text for each filter in the
   * subscription.
   * @returns {Iterator.<string>}
   */
  filterText() {
    return this._filterText[Symbol.iterator]();
  }

  // Lots of this fromSynchronizer._onDownloadSuccess()
  /**
   * Set parameters for Countable subscriptions.
   *
   * @param {object} params The params from the filter list. `params` is
   *   the `params` field as returned by
   *   `{@link module:filters/lists.parseFilterList parseFilterList()}`.
   */
  setParams(params) {
    if (params.homepage) {
      let url;
      try {
        url = new URL(params.homepage);
      }
      catch (e) {
        url = null;
      }

      if (url && (url.protocol == "http:" || url.protocol == "https:"))
        this.homepage = url.href;
    }

    if (params.title) {
      this.title = params.title;
      this.fixedTitle = true;
    }
    else {
      this.fixedTitle = false;
    }

    if (params.version)
      this.version = parseInt(params.version, 10);

    if (this.type)
      this.abtest = params.abtest;
  }

  /**
   * Set the filter text, and reset the index. Call this before adding
   * to the storage.
   *
   * The filter texts will be normalized with `{@link
   * module:filterClasses.Filter#normalize Filter.normalize()}` like
   * if they were loaded from a filter list.
   *
   * It is important to not call this beside the initialisation of the
   * subscription as it doesn't notify of changes
   *
   * @param {Array.<string>} text The text strings.
   * @param {object?} params The filter list params if any. `params` is
   *   the `params` field as returned by
   *   `{@link module:filters/lists.parseFilterList parseFilterList()}`.
   *
   * An error will be thrown if `text` isn't an array.
   */
  setFilterText(text, params = null) {
    if (!Array.isArray(text))
      throw new Error("setFilterText() must be called with an Array");

    this._filterText = text.map(t => Filter.normalize(t));
    this._filterTextIndex = new Set(this._filterText);

    if (params)
      this.setParams(params);
  }

  /**
   * Checks whether the subscription has the given filter text.
   * @param {string} filterText The filter text.
   * @returns {boolean} Whether the subscription has the filter text.
   * @package
   */
  hasFilterText(filterText) {
    return this._filterTextIndex.has(filterText);
  }

  /**
   * Returns the filter text at the given `0`-based index.
   * @param {number} index The `0`-based index. If the index is out of bounds,
   *   the return value is `null`.
   * @returns {?module:filterClasses.Filter} The filter text.
   */
  filterTextAt(index) {
    return this._filterText[index] || null;
  }

  /**
   * Returns the `0`-based index of the given filter.
   *
   * @param {module:filterClasses.Filter} filter The filter.
   * @param {number} [fromIndex] The `0`-based index from which to start the
   *   search.
   *
   * @returns {number} The `0`-based index at which the filter is found. If the
   *   filter is not found in the subscription, the return value is `-1`.
   */
  findFilterIndex(filter, fromIndex = 0) {
    return this._filterText.indexOf(filter.text, fromIndex);
  }

  /**
   * Removes all filters from the subscription.
   */
  clearFilters() {
    this._filterText = [];
    this._filterTextIndex.clear();
  }

  /**
   * Adds a filter to the subscription.
   * @param {Filter} filter The filter.
   */
  addFilter(filter) {
    this._filterText.push(filter.text);
    this._filterTextIndex.add(filter.text);
  }

  /**
   * Inserts a filter into the subscription at the given `0`-based index.
   *
   * @param {module:filterClasses.Filter} filter The filter.
   * @param {number} index The `0`-based index. If the index is out of bounds,
   *   the filter is inserted at the beginning or at the end accordingly.
   */
  insertFilterAt(filter, index) {
    this._filterText.splice(index, 0, filter.text);
    this._filterTextIndex.add(filter.text);
  }

  /**
   * Deletes a filter from the subscription at the given `0`-based index.
   * @param {number} index The `0`-based index. If the index is out of bounds,
   *   no filter is deleted.
   */
  deleteFilterAt(index) {
    // Ignore index if out of bounds on the negative side, for consistency.
    if (index < 0)
      return;

    let [filterText] = this._filterText.splice(index, 1);
    if (!this._filterText.includes(filterText))
      this._filterTextIndex.delete(filterText);
  }

  /**
   * Updates the filter text of the subscription.
   * @param {Array.<string>} filterText The new filter text.
   * @returns {{added: Array.<string>, removed: Array.<string>}} An object
   *   containing two lists of the text of added and removed filters
   *   respectively.
   * @package
   */
  updateFilterText(filterText) {
    let added = [];
    let removed = [];

    if (this._filterText.length == 0) {
      added = [...filterText];
    }
    else if (filterText.length > 0) {
      for (let text of filterText) {
        if (!this._filterTextIndex.has(text))
          added.push(text);
      }
    }

    this._filterTextIndex = new Set(filterText);

    if (filterText.length == 0) {
      removed = [...this._filterText];
    }
    else if (this._filterText.length > 0) {
      for (let text of this._filterText) {
        if (!this._filterTextIndex.has(text))
          removed.push(text);
      }
    }

    this._filterText = [...filterText];

    return {added, removed};
  }

  /**
   * Serializes the subscription for writing out on disk.
   * @yields {string}
   * @package
   */
  *serialize() {
    let {url, _title, _fixedTitle, _disabled, _id} = this;

    yield "[Subscription]";
    yield "url=" + url;

    if (_title)
      yield "title=" + _title;
    if (_fixedTitle)
      yield "fixedTitle=true";
    if (_disabled)
      yield "disabled=true";
    if (_id)
      yield "id=" + _id;
  }

  /**
   * Serializes the subscription's filter text for writing out on disk.
   * @yields {string}
   * @package
   */
  *serializeFilters() {
    let {_filterText} = this;

    yield "[Subscription filters]";

    for (let text of _filterText)
      yield text.replace(/\[/g, "\\[");
  }

  /**
   * Returns a string representing the subscription.
   * @returns {string}
   */
  toString() {
    return [...this.serialize()].join("\n");
  }
};

/**
 * Cache for known filter subscriptions that maps subscription URLs to
 * subscription objects.
 * @type {Map.<string, module:subscriptionClasses.Subscription>}
 * @package
 */
exports.Subscription.knownSubscriptions = new Map();
/**
 * We operate in DNR mode. Default is false.
 * @type {bool}
 * @package
 */
exports.Subscription.dnr = false;

/**
 * Returns the subscription object for a subscription URL.
 *
 * Every subscription URL maps to its own unique object. If no such object
 * exists, a new one is created internally; otherwise the existing object is
 * used.
 *
 * If `Subscription.dnr` is true, it will remap `mv2_url` to the canonical
 * `url` if necessary.
 *
 * @param {string} url The subscription URL.
 *
 * @returns {module:subscriptionClasses.Subscription} A subscription
 * object (can be any subclass thereof.
 */
exports.Subscription.fromURL = function(url) {
  let subscription = Subscription.knownSubscriptions.get(url);
  if (subscription)
    return subscription;

  if (url[0] != "~") {
    let downloadable = true;
    let title = null;
    let params = null;
    if (Subscription.dnr) {
      // In DNR we check if we got a mv2 URL and remap.
      let actualUrl = urlByMv2URL().get(url);
      if (actualUrl) {
        subscription = Subscription.knownSubscriptions.get(actualUrl);
        if (subscription)
          return subscription;

        url = actualUrl;
      }

      let recommendation = recommendationsByURL().get(url);
      if (recommendation) {
        // In DNR we use the recommendation title.
        title = recommendation.title;

        // In DNR currently "circumvention" list is downloadable.
        // This until we can tag subscription to be downloadable.
        downloadable = recommendation.type == "circumvention";
        if (!downloadable) {
          // We have to set the params like if the list was downloaded.
          params = {
            homepage: recommendation.homepage,
            // The effect of setting title here is that it will make the
            // fixedTitle property to be true.
            // This is the equivalent of the title being set by the
            // filter list.
            title
          };
        }
      }
    }

    if (downloadable)
      subscription = new DownloadableSubscription(url, title);
    else
      subscription = new CountableSubscription(url, title, params);

    return subscription;
  }

  return new SpecialSubscription(url);
};

/**
 * Deserializes a subscription.
 * @param {Object} obj A map of serialized properties and their values.
 * @returns {module:subscriptionClasses.Subscription} A subscription object.
 * @package
 */
exports.Subscription.fromObject = function(obj) {
  let result;
  if (obj.url[0] != "~") {
    // URL is valid - this is a regular subscription
    // Unless indicated otherwise it is downloadable.
    if (("downloadable" in obj) && (obj.downloadable == "false"))
      result = new CountableSubscription(obj.url, obj.title);
    else
      result = new DownloadableSubscription(obj.url, obj.title);

    if (result.type)
      result.abtest = obj.abtest;

    if ("downloadStatus" in obj)
      result._downloadStatus = obj.downloadStatus;
    if ("lastSuccess" in obj)
      result.lastSuccess = parseInt(obj.lastSuccess, 10) || 0;
    if ("lastCheck" in obj)
      result._lastCheck = parseInt(obj.lastCheck, 10) || 0;
    if ("expires" in obj)
      result.expires = parseInt(obj.expires, 10) || 0;
    if ("softExpiration" in obj)
      result.softExpiration = parseInt(obj.softExpiration, 10) || 0;
    if ("errors" in obj)
      result._errors = parseInt(obj.errors, 10) || 0;
    if ("version" in obj)
      result.version = parseInt(obj.version, 10) || 0;
    if ("requiredVersion" in obj)
      result.requiredVersion = obj.requiredVersion;
    if ("homepage" in obj)
      result._homepage = obj.homepage;
    if ("lastDownload" in obj)
      result._lastDownload = parseInt(obj.lastDownload, 10) || 0;
    if ("downloadCount" in obj)
      result.downloadCount = parseInt(obj.downloadCount, 10) || 0;
  }
  else {
    result = new SpecialSubscription(obj.url, obj.title);
    if ("defaults" in obj)
      result.defaults = obj.defaults.split(" ");
    if ("metadata" in obj)
      result._metadata = JSON.parse(obj.metadata);
  }
  if ("id" in obj)
    result._id = obj.id;
  if ("fixedTitle" in obj)
    result._fixedTitle = (obj.fixedTitle == "true");
  if ("disabled" in obj)
    result._disabled = (obj.disabled == "true");

  return result;
};

/**
 * Checks whether a URL is a valid subscription URL.
 * @param {string} url The URL.
 * @returns {boolean} Whether the URL is a valid subscription URL.
 */
exports.Subscription.isValidURL = function isValidURL(url) {
  return url.startsWith("~user~") || Downloader.isValidURL(url);
};

let SpecialSubscription =
/**
 * The `SpecialSubscription` class represents a special filter subscription.
 *
 * This type of subscription is used for keeping user-defined filters.
 * @extends module:subscriptionClasses.Subscription
 */
exports.SpecialSubscription = class SpecialSubscription extends Subscription {
  /**
   * Creates a `SpecialSubscription` object.
   * @param {string} url The URL of the subscription.
   * @param {string} [title] The title of the subscription.
   * @private
   */
  constructor(url, title) {
    super(url, title);

    /**
     * Filter types that should be added to this subscription by default.
     *
     * Entries should correspond to keys in
     * `{@link module:subscriptionClasses.SpecialSubscription.defaultsMap}`.
     *
     * @type {?Array.<string>}
     *
     * @package
     */
    this.defaults = null;

    this._metadata = null;
  }

  get privileged() {
    return true;
  }

  /**
   * Checks whether the given filter should be added to this subscription by
   * default.
   * @param {Filter} filter The filter.
   * @returns {boolean} Whether the filter should be added to this subscription
   *   by default.
   * @package
   */
  isDefaultFor(filter) {
    if (this.defaults && this.defaults.length) {
      for (let type of this.defaults) {
        if (SpecialSubscription.defaultsMap.get(type).includes(filter.type))
          return true;
        if (!isActiveFilter(filter) && type == "blocking")
          return true;
      }
    }

    return false;
  }

  /**
   * Set the metadata block for the special subscription
   *
   * @param {object} [value] The metadata
   */
  set metadata(value) {
    let oldValue = this._metadata;
    this._metadata = value;
    filterNotifier.emit("subscription.metadata", this, value, oldValue);
  }

  /**
   * Get the metadata block.
   * @return {?object} the metadata object or null
   */
  get metadata() {
    return this._metadata;
  }

  /**
   * Serializes the subscription for writing out on disk.
   * @yields {string}
   * @package
   */
  *serialize() {
    let {defaults, _lastDownload, _metadata} = this;

    yield* super.serialize();

    if (defaults) {
      yield "defaults=" +
            defaults.map(
              // remap for the stored format.
              type => type == "allowing" ? "whitelist" : type
            ).filter(
              type => SpecialSubscription.defaultsMap.has(type)
            ).join(" ");
    }
    // Metadata is encoded as a JSON on a single line.
    // This should be safe.
    if (_metadata)
      yield "metadata=" + JSON.stringify(_metadata);

    if (_lastDownload)
      yield "lastDownload=" + _lastDownload;
  }
};

/**
 * A map of filter types.
 * @type {Map.<string, Array.<string>>}
 * @package
 */
exports.SpecialSubscription.defaultsMap = new Map([
  ["allowing", ["allowing"]],
  // deprecated terminology
  ["whitelist", ["allowing"]],
  ["blocking", ["blocking"]],
  ["elemhide", ["elemhide", "elemhideexception", "elemhideemulation"]]
]);

/**
 * Creates a new special subscription.
 * @param {string} [title] The title of the subscription.
 * @returns {module:subscriptionClasses.SpecialSubscription} A new special
 *   subscription.
 * @package
 */
exports.SpecialSubscription.create = function(title) {
  let url;
  do
    url = "~user~" + Math.round(Math.random() * 1000000);
  while (Subscription.knownSubscriptions.has(url));
  return new SpecialSubscription(url, title);
};

/**
 * Creates a new special subscription and adds the given filter to it.
 *
 * Once created, the subscription acts as the default for all filters of the
 * {@link module:filterClasses.Filter#type type}.
 *
 * @param {module:filterClasses.Filter} filter The filter.
 *
 * @returns {module:subscriptionClasses.SpecialSubscription} A new special
 *   subscription.
 *
 * @package
 */
exports.SpecialSubscription.createForFilter = function(filter) {
  let subscription = SpecialSubscription.create();
  subscription.addFilter(filter);
  for (let [type, mappedTypes] of SpecialSubscription.defaultsMap) {
    if (mappedTypes.includes(filter.type))
      subscription.defaults = [type];
  }
  if (!subscription.defaults)
    subscription.defaults = ["blocking"];
  return subscription;
};

let RegularSubscription =
/**
 * The `RegularSubscription` class represents a regular filter subscription
 * that is not by default downloaded off the internet.
 * `CountableSubscription` is a subclass of this.
 *
 * In a manifest v2 context it shouldn't be encountered. In manifest v3, it's
 * the default.
 *
 * @extends module:subscriptionClasses.Subscription
 */
exports.RegularSubscription = class RegularSubscription extends Subscription {
  /**
   * Creates a `RegularSubscription` object.
   * @param {string} url The URL of the subscription.
   * @param {string} [title] The title of the subscription.
   * @private
   */
  constructor(url, title) {
    super(url, title || url);

    /**
     * The homepage of the subscription.
     * @type {?string}
     * @default <code>null</code>
     * @private
     * @see module:subscriptionClasses.RegularSubscription#homepage
     */
    this._homepage = null;

    /**
     * The last time the subscription was downloaded, in seconds since the
     * beginning of the Unix epoch.
     * @type {number}
     * @default <code>0</code>
     * @private
     * @see module:subscriptionClasses.RegularSubscription#lastDownload
     */
    this._lastDownload = 0;

    let recommendation = recommendationsByURL().get(url);
    /**
     * The languages that apply for this subscription.
     * @type {?Array.<string>}
     */
    this._languages = recommendation ? recommendation.languages : null;
  }

  /**
   * The homepage of the subscription.
   * @type {?string}
   * @default <code>null</code>
   */
  get homepage() {
    return this._homepage;
  }

  set homepage(value) {
    if (value != this._homepage) {
      let oldValue = this._homepage;
      this._homepage = value;
      filterNotifier.emit("subscription.homepage", this, value, oldValue);
    }
  }

  /**
   * The languages that apply for this subscription.
   * @type {?Array.<string>}
   * @default <code>null</code>
   */
  get languages() {
    return this._languages;
  }

  /**
   * The last time the subscription was downloaded, in seconds since the
   * beginning of the Unix epoch.
   * @type {number}
   * @default <code>0</code>
   */
  get lastDownload() {
    return this._lastDownload;
  }

  set lastDownload(value) {
    if (value != this._lastDownload) {
      let oldValue = this._lastDownload;
      this._lastDownload = value;
      filterNotifier.emit("subscription.lastDownload", this, value, oldValue);
    }
  }

  /**
   * Serializes the subscription for writing out on disk.
   * @yields {string}
   * @package
   */
  *serialize() {
    let {_homepage, _lastDownload} = this;

    yield* super.serialize();

    // To keep compatibility dowloadable is true if missing
    if (!this.downloadable)
      yield "downloadable=false";
    if (_homepage)
      yield "homepage=" + _homepage;
    if (_lastDownload)
      yield "lastDownload=" + _lastDownload;
  }
};

/**
 * Once initialized, the shared Synchronizer singleton will be stored in here.
 * @type {module:synchronizer.Synchronizer}
 */
let synchronizer = null;

let CountableSubscription =
/**
 * The `CountableSubscription` class represents a regular filter
 * subscription which will indicate it to the remote `url` it is in
 * use by issuing a `HEAD` http request instead of a `GET`.
 *
 * However it will have its property `downloadable` still set to
 * `false`.
 *
 * @extends module:subscriptionClasses.RegularSubscription
 */
exports.CountableSubscription =
class CountableSubscription extends RegularSubscription {
  /**
   * Allows downloadable subscriptions to update themselves once re-enabled,
   * via receiving the Synchronizer singleton.
   * @param {module:synchronizer~Synchronizer} reference the Synchronizer
   */
  static useSynchronizer(reference) {
    synchronizer = reference;
  }

  /**
   * Creates a `CountableSubscription` object.
   *
   * @param {string} url The URL of the subscription.
   * @param {string} [title] The title of the subscription.
   * @param {?object} [params] The params to pass to
   *    `{@link Subscription.setParams}`. Can be omitted or `null`.
   * @private
   */
  constructor(url, title, params) {
    super(url, title);

    if (params)
      this.setParams(params);

    /**
     * The status of the last download.
     * @type {?string}
     * @default <code>null</code>
     * @private
     * @see module:subscriptionClasses.CountableSubscription#downloadStatus
     */
    this._downloadStatus = null;

    /**
     * The last time the subscription was considered for an update, in seconds
     * since the beginning of the Unix epoch.
     * @type {number}
     * @default <code>0</code>
     * @private
     * @see module:subscriptionClasses.CountableSubscription#lastCheck
     */
    this._lastCheck = 0;

    /**
     * The number of download failures since the last successful download.
     * @type {number}
     * @default <code>0</code>
     * @private
     * @see module:subscriptionClasses.CountableSubscription#errors
     */
    this._errors = 0;

    /**
     * The last time the subscription was successfully downloaded, in seconds
     * since the beginning of the Unix epoch.
     * @type {number}
     * @default <code>0</code>
     */
    this.lastSuccess = 0;

    /**
     * The hard expiration time of the subscription, in seconds since the
     * beginning of the Unix epoch.
     *
     * Updates should be downloaded if `{@link
     * module:subscriptionClasses.CountableSubscription#softExpiration}`
     * or `expires` are in the past.
     * @type {number}
     * @default <code>0</code>
     */
    this.expires = 0;

    /**
     * The soft expiration time of the subscription, in seconds since the
     * beginning of the Unix epoch.
     *
     * Updates should be downloaded if `softExpiration` or
     * `{@link module:subscriptionClasses.CountableSubscription#expires}`
     * are in the past.
     * @type {number}
     * @default <code>0</code>
     */
    this.softExpiration = 0;

    /**
     * The version of the subscription data that was retrieved on last
     * successful download.
     * @type {number}
     * @default <code>0</code>
     */
    this.version = 0;

    /**
     * The minimal Adblock Plus version required for the subscription.
     * @type {?string}
     * @default <code>null</code>
     */
    this.requiredVersion = null;

    /**
     * The number of times the subscription has been downloaded.
     * @type {number}
     * @default <code>0</code>
     */
    this.downloadCount = 0;

    this._p = profiler(`CountableSubscription@${url}`);
    this._p.start();
  }

  /**
   * Whether this is a countable subscription, i.e. a subscription that
   * will connect to the URL. A downloadable subscription is countable,
   * but not the other way around.
   *
   * @type {boolean}
   * @default <code>true</code>
   */
  get countable() {
    return true;
  }

  /**
   * Whether the subscription is disabled. Once re-enabled, it ensures the
   * synchronizer downloads latest version of this subscription.
   * @type {boolean}
   * @default <code>false</code>
   */
  get disabled() {
    return super.disabled;
  }

  set disabled(value) {
    let {_disabled} = this;
    super.disabled = value;
    if (synchronizer && _disabled && !value)
      synchronizer.execute(this);
  }

  /**
   * The status of the last download.
   *
   * A message ID which can have the following values: `synchronize_ok`,
   * `synchronize_connection_error` or `synchronize_invalid_url`. If the
   * initial download is not completed yet, then it is null.
   *
   * @type {?string}
   * @default <code>null</code>
   */
  get downloadStatus() {
    return this._downloadStatus;
  }

  set downloadStatus(value) {
    let oldValue = this._downloadStatus;
    this._downloadStatus = value;
    filterNotifier.emit("subscription.downloadStatus", this, value, oldValue);
  }

  /**
   * The last time the subscription was considered for an update, in seconds
   * since the beginning of the Unix epoch.
   *
   * This is used to increase the soft expiration time if the user doesn't use
   * Adblock Plus for some time.
   *
   * @type {number}
   * @default <code>0</code>
   */
  get lastCheck() {
    return this._lastCheck;
  }

  set lastCheck(value) {
    if (value != this._lastCheck) {
      let oldValue = this._lastCheck;
      this._lastCheck = value;
      filterNotifier.emit("subscription.lastCheck", this, value, oldValue);
    }
  }

  /**
   * The number of download failures since the last successful download.
   * @type {number}
   * @default <code>0</code>
   */
  get errors() {
    return this._errors;
  }

  set errors(value) {
    if (value != this._errors) {
      let oldValue = this._errors;
      this._errors = value;
      filterNotifier.emit("subscription.errors", this, value, oldValue);
    }
  }

  /**
   * Serializes the subscription for writing out on disk.
   * @yields {string}
   * @package
   */
  *serialize() {
    let {downloadStatus, lastSuccess, lastCheck, expires,
         softExpiration, errors, version, requiredVersion,
         downloadCount} = this;

    yield* super.serialize();

    if (downloadStatus)
      yield "downloadStatus=" + downloadStatus;
    if (lastSuccess)
      yield "lastSuccess=" + lastSuccess;
    if (lastCheck)
      yield "lastCheck=" + lastCheck;
    if (expires)
      yield "expires=" + expires;
    if (softExpiration)
      yield "softExpiration=" + softExpiration;
    if (errors)
      yield "errors=" + errors;
    if (version)
      yield "version=" + version;
    if (requiredVersion)
      yield "requiredVersion=" + requiredVersion;
    if (downloadCount)
      yield "downloadCount=" + downloadCount;
  }

  /**
   * Put a benchmarking event
   * @param {string} event benchmarking event
   */
  mark(event) {
    this._p.mark(event);
  }
};

let DownloadableSubscription =
/**
 * The `DownloadableSubscription` class represents a regular filter
 * subscription whose content (filter text) is downloaded from a filter list
 * off the internet from `url`.
 *
 * It will have its property `downloadable` set to `true`.
 *
 * @extends module:subscriptionClasses.CountableSubscription
 */
exports.DownloadableSubscription =
class DownloadableSubscription extends CountableSubscription {
  /** Construct a new DownloadableSubscription
   *
   * @param {string} url The URL of the subscription.
   * @param {string} [title] The title of the subscription.
   *
   * @private
   */
  constructor(url, title) {
    super(url, title);
  }

  /**
   * Whether the subscription is downloadable.
   * @type {boolean}
   * @default <code>true</code>
   */
  get downloadable() {
    return true;
  }
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/synchronizer.js":
/*!**********************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/synchronizer.js ***!
  \**********************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_538133__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * @file Manages synchronization of filter subscriptions.
 */

const {Prefs} = __nested_webpack_require_538133__(/*! prefs */ "./sdk/api/prefs.js");

const {MILLIS_IN_SECOND, MILLIS_IN_MINUTE, MILLIS_IN_HOUR,
       MILLIS_IN_DAY} = __nested_webpack_require_538133__(/*! ./time */ "./node_modules/adblockpluscore/lib/time.js");
const {Downloader, Downloadable} = __nested_webpack_require_538133__(/*! ./downloader */ "./node_modules/adblockpluscore/lib/downloader.js");
const {Filter} = __nested_webpack_require_538133__(/*! ./filterClasses */ "./node_modules/adblockpluscore/lib/filterClasses.js");
const {filterNotifier} = __nested_webpack_require_538133__(/*! ./filterNotifier */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
const {Subscription,
       CountableSubscription} = __nested_webpack_require_538133__(/*! ./subscriptionClasses */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
const {analytics} = __nested_webpack_require_538133__(/*! ./analytics */ "./node_modules/adblockpluscore/lib/analytics.js");
const {parseFilterList} = __nested_webpack_require_538133__(/*! ./filters/lists.js */ "./node_modules/adblockpluscore/lib/filters/lists.js");

const INITIAL_DELAY = 1 * MILLIS_IN_MINUTE;
const CHECK_INTERVAL = 1 * MILLIS_IN_HOUR;
const DEFAULT_EXPIRATION_INTERVAL = 5 * MILLIS_IN_DAY;

let getPreferredMillis = (field, fallback) =>
                          field in Prefs ? Prefs[field] : fallback;

/**
 * Downloads filter subscriptions whenever necessary.
 */
class Synchronizer {
  /**
   * Construct a new synchronizer.
   * @param {FilterStorage} [filterStorage] The associated filter storage.
   */
  constructor(filterStorage) {
    if (filterStorage == null || typeof filterStorage != "object")
      throw Error("filterStorage must be a valid object");

    /**
     * Whether the downloading of subscriptions has been started.
     * @private
     */
    this._started = false;

    /**
     * The object providing actual downloading functionality.
     * @type {module:downloader.Downloader}
     */
    this._downloader = new Downloader(this._getDownloadables.bind(this));

    this._downloader.onExpirationChange = this._onExpirationChange.bind(this);
    this._downloader.onDownloadStarted = this._onDownloadStarted.bind(this);
    this._downloader.onDownloadSuccess = this._onDownloadSuccess.bind(this);
    this._downloader.onDownloadError = this._onDownloadError.bind(this);

    this._filterStorage = filterStorage;

    // allow subscription to update themselves once re-enabled if needed.
    CountableSubscription.useSynchronizer(this);
  }

  /**
   * Starts downloading subscriptions.
   *
   * No subscriptions are downloaded until this function has been called at
   * least once.
   */
  start() {
    if (this._started)
      return;

    this._downloader.scheduleChecks(
      getPreferredMillis("subscriptions_check_interval", CHECK_INTERVAL),
      getPreferredMillis("subscriptions_initial_delay", INITIAL_DELAY)
    );
    this._started = true;
  }

  /**
   * Clear any further downloader scheduled check and set its internal state
   * as not started.
   */
  stop() {
    this._started = false;
    this._downloader.unscheduleChecks();
  }

  /**
   * Checks whether a subscription is currently being downloaded.
   * @param {string} url  URL of the subscription
   * @returns {boolean}
   */
  isExecuting(url) {
    return this._downloader.isDownloading(url);
  }

  /**
   * Starts the download of a subscription if it is downloadable.
   *
   * @param {module:subscriptionClasses.CountableSubscription} subscription
   *   Subscription to be downloaded
   * @param {boolean} manual
   *   `true` for a manually started download (should not trigger fallback
   *   requests)
   */
  execute(subscription, manual) {
    this._downloader.download(this._getDownloadable(subscription, manual));
  }

  /**
   * Yields `{@link module:downloader.Downloadable Downloadable}` instances for
   * all subscriptions that can be downloaded.
   * @yields {module:downloader.Downloadable}
   */
  *_getDownloadables() {
    if (!Prefs.subscriptions_autoupdate)
      return;

    for (let subscription of this._filterStorage.subscriptions()) {
      if (subscription instanceof CountableSubscription)
        yield this._getDownloadable(subscription, false);
    }
  }

  /**
   * Creates a `{@link module:downloader.Downloadable Downloadable}` instance
   * for a subscription.
   * @param {module:subscriptionClasses.Subscription} subscription
   * @param {boolean} manual
   * @returns {module:downloader.Downloadable}
   */
  _getDownloadable(subscription, manual) {
    let {url, lastDownload, lastSuccess, lastCheck, version, softExpiration,
         expires, downloadCount, disabled, downloadable,
         countable} = subscription;

    let result = new Downloadable(url);

    if (analytics.isTrusted(url))
      result.firstVersion = analytics.getFirstVersion();

    if (lastDownload != lastSuccess)
      result.lastError = lastDownload * MILLIS_IN_SECOND;

    result.lastCheck = lastCheck * MILLIS_IN_SECOND;
    result.lastVersion = version;
    result.softExpiration = softExpiration * MILLIS_IN_SECOND;
    result.hardExpiration = expires * MILLIS_IN_SECOND;
    result.manual = manual;
    result.downloadCount = downloadCount;
    result.disabled = disabled;
    if (disabled || (countable && !downloadable))
      result.method = "HEAD";

    return result;
  }

  _onExpirationChange(downloadable) {
    let subscription = Subscription.fromURL(downloadable.url);
    subscription.lastCheck = Math.round(
      downloadable.lastCheck / MILLIS_IN_SECOND
    );
    subscription.softExpiration = Math.round(
      downloadable.softExpiration / MILLIS_IN_SECOND
    );
    subscription.expires = Math.round(
      downloadable.hardExpiration / MILLIS_IN_SECOND
    );
  }

  _onDownloadStarted(downloadable) {
    let subscription = Subscription.fromURL(downloadable.url);
    filterNotifier.emit("subscription.downloading", subscription);
    subscription.mark("downloading.started");
  }

  _onDownloadSuccess(downloadable, responseText, errorCallback,
                     redirectCallback) {
    let subscription = Subscription.fromURL(downloadable.redirectURL ||
                                            downloadable.url);
    subscription.mark("downloading.finished");
    subscription.mark("parsing.started");

    let isHEAD = downloadable.method === "HEAD";

    let {error, lines, params,
         minVersion} = isHEAD ? {params: {}} : parseFilterList(responseText);

    if (error)
      return errorCallback(error);

    if (params.redirect)
      return redirectCallback(params.redirect);

    subscription.mark("parsing.finished");

    // Handle redirects
    if (downloadable.redirectURL &&
        downloadable.redirectURL != downloadable.url) {
      let oldSubscription = Subscription.fromURL(downloadable.url);
      subscription.title = oldSubscription.title;
      subscription.disabled = oldSubscription.disabled;
      subscription.lastCheck = oldSubscription.lastCheck;

      let listed = this._filterStorage.hasSubscription(oldSubscription);
      if (listed)
        this._filterStorage.removeSubscription(oldSubscription);

      Subscription.knownSubscriptions.delete(oldSubscription.url);

      if (listed)
        this._filterStorage.addSubscription(subscription);
    }

    // The download actually succeeded
    subscription.lastSuccess = subscription.lastDownload = Math.round(
      Date.now() / MILLIS_IN_SECOND
    );
    subscription.downloadStatus = "synchronize_ok";
    subscription.downloadCount = downloadable.downloadCount;
    subscription.errors = 0;

    // Process parameters
    if (params.homepage) {
      let url;
      try {
        url = new URL(params.homepage);
      }
      catch (e) {
        url = null;
      }

      if (url && (url.protocol == "http:" || url.protocol == "https:"))
        subscription.homepage = url.href;
    }

    if (params.title) {
      subscription.title = params.title;
      subscription.fixedTitle = true;
    }
    else {
      subscription.fixedTitle = false;
    }

    if (params.version) {
      subscription.version = parseInt(params.version, 10);

      if (analytics.isTrusted(downloadable.redirectURL || downloadable.url))
        analytics.recordVersion(params.version);
    }
    else {
      subscription.version = isHEAD ? downloadable.lastVersion : 0;
    }

    if (subscription.type)
      subscription.abtest = params.abtest;

    let headExpInterval = getPreferredMillis(
      "subscriptions_head_expiration_interval",
      MILLIS_IN_DAY
    );

    let defaultExpInterval = getPreferredMillis(
      "subscriptions_default_expiration_interval",
      DEFAULT_EXPIRATION_INTERVAL
    );

    let expirationInterval = isHEAD ? headExpInterval : defaultExpInterval;

    if (params.expires) {
      let match = /^(\d+)\s*(h)?/.exec(params.expires);
      if (match) {
        let interval = parseInt(match[1], 10);
        if (match[2])
          expirationInterval = interval * MILLIS_IN_HOUR;
        else
          expirationInterval = interval * MILLIS_IN_DAY;
      }
    }

    let [
      softExpiration,
      hardExpiration
    ] = this._downloader.processExpirationInterval(expirationInterval);
    subscription.softExpiration = Math.round(softExpiration / MILLIS_IN_SECOND);
    subscription.expires = Math.round(hardExpiration / MILLIS_IN_SECOND);

    if (minVersion)
      subscription.requiredVersion = minVersion;
    else
      delete subscription.requiredVersion;

    // In case of HEAD request (disabled subscription) notify an update so that
    // the last version of the subscription will be stored for the next time.
    if (isHEAD)
      filterNotifier.emit("subscription.updated", subscription);
    else
      this._processFilters(subscription, lines);
  }

  _onDownloadError(downloadable, downloadURL, error, responseStatus,
                   redirectCallback) {
    let subscription = Subscription.fromURL(downloadable.url);
    subscription.mark("downloading.finished");
    subscription.lastDownload = Math.round(Date.now() / MILLIS_IN_SECOND);
    subscription.downloadStatus = error;

    // Request fallback URL if necessary - for automatic updates only
    if (!downloadable.manual) {
      subscription.errors++;

      if (redirectCallback &&
          subscription.errors >= Prefs.subscriptions_fallbackerrors &&
          /^https?:\/\//i.test(subscription.url)) {
        subscription.errors = 0;

        let fallbackURL = Prefs.subscriptions_fallbackurl;
        const {addonVersion} = __nested_webpack_require_538133__(/*! info */ "./sdk/api/info.js");
        fallbackURL = fallbackURL.replace(/%VERSION%/g,
                                          encodeURIComponent(addonVersion));
        fallbackURL = fallbackURL.replace(/%SUBSCRIPTION%/g,
                                          encodeURIComponent(subscription.url));
        fallbackURL = fallbackURL.replace(/%URL%/g,
                                          encodeURIComponent(downloadURL));
        fallbackURL = fallbackURL.replace(/%ERROR%/g,
                                          encodeURIComponent(error));
        fallbackURL = fallbackURL.replace(/%RESPONSESTATUS%/g,
                                          encodeURIComponent(responseStatus));

        let initObj = {
          cache: "no-store",
          credentials: "omit",
          referrer: "no-referrer",
          method: downloadable.method
        };

        fetch(fallbackURL, initObj).then(response => response.text())
          .then(responseText => {
            if (!this._filterStorage.hasSubscription(subscription))
              return;

            let match = /^(\d+)(?:\s+(\S+))?$/.exec(responseText);
            if (match && match[1] == "301" &&    // Moved permanently
              match[2] && /^https?:\/\//i.test(match[2])) {
              redirectCallback(match[2]);
            }
            // Gone
            else if (match && match[1] == "410") {
              let data = "[Adblock]\n" +
              [...subscription.filterText()].join("\n");
              redirectCallback("data:text/plain," + encodeURIComponent(data));
            }
          });
      }
    }
  }

  /**
   * Given a valid subscription and some text, it parses all filters and add
   * these in bulk to the specified subscription.
   * @param {module:subscriptionClasses.Subscription} subscription The
   *  Subscription to use as reference for manually added filters.
   * @param {string} filters The filters file/text to add.
   * @param {function} errorCallback A callback invoked if errors occur.
   */
  addSubscriptionFilters(
    subscription, filters, errorCallback
  ) {
    let {error, lines} = parseFilterList(filters);
    if (error)
      errorCallback(error);
    else
      this._processFilters(subscription, lines);
  }

  /**
   * Given a list of parsed filters, normalize each line and update the
   * subscription.
   * @private
   * @param {module:subscriptionClasses.Subscription} subscription The
   *  Subscription to use as reference for manually added filters.
   * @param {string[]} lines The parsed filters lines. The first line
   will be skipped over as it is supposed to contain the header.
  */
  _processFilters(subscription, lines) {
    subscription.mark("processing.started");

    lines.shift();
    let filterText = [];
    for (let line of lines) {
      line = Filter.normalize(line);
      if (line)
        filterText.push(line);
    }

    this._filterStorage.updateSubscriptionFilters(subscription, filterText);

    subscription.mark("processing.finished");
  }
}

exports.Synchronizer = Synchronizer;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/time.js":
/*!**************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/time.js ***!
  \**************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



/**
 * Number of milliseconds in a second.
 * @const {number}
 * @default 1000
 * @package
 */
exports.MILLIS_IN_SECOND = 1000;

/**
 * Number of milliseconds in a minute.
 * @const {number}
 * @default 60000
 * @package
 */
exports.MILLIS_IN_MINUTE = 60000;

/**
 * Number of milliseconds in an hour.
 * @const {number}
 * @default 3600000
 * @package
 */
exports.MILLIS_IN_HOUR = 3600000;

/**
 * Number of milliseconds in a day.
 * @const {number}
 * @default 86400000
 * @package
 */
exports.MILLIS_IN_DAY = 86400000;


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/url.js":
/*!*************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/url.js ***!
  \*************************************************/
/***/ ((__unused_webpack_module, exports, __nested_webpack_require_554296__) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



const {Cache} = __nested_webpack_require_554296__(/*! ./caching */ "./node_modules/adblockpluscore/lib/caching.js");

const {publicSuffixes} = __nested_webpack_require_554296__(/*! ../data/publicSuffixList.js */ "./node_modules/adblockpluscore/data/publicSuffixList.js");

// ensure no conflict ever happens with inherited properties
Object.setPrototypeOf(publicSuffixes, null);

/**
 * Cache of domain maps.
 *
 * The domains part of filter text (e.g. `example.com,~mail.example.com`) is
 * often repeated across filters. This cache enables deduplication of the
 * `Map` objects that specify on which domains the filter does and does not
 * apply, which reduces memory usage and improves performance.
 *
 * @type {Map.<string, Map.<string, boolean>>}
 */
let domainsCache = new Cache(1000);

/**
 * A `URLInfo` object represents information about a URL.
 *
 * It is returned by `{@link module:url.parseURL parseURL()}`.
 */
class URLInfo {
  /**
   * Creates a `URLInfo` object.
   *
   * @param {string} href The entire URL.
   * @param {string} protocol The protocol scheme of the URL, including the
   *   final `:`.
   * @param {string} [hostname] The hostname of the URL.
   *
   * @private
   */
  constructor(href, protocol, hostname = "") {
    this._href = href;
    this._protocol = protocol;
    this._hostname = hostname;
  }

  /**
   * The entire URL.
   * @type {string}
   */
  get href() {
    return this._href;
  }

  /**
   * The protocol scheme of the URL, including the final `:`.
   * @type {string}
   */
  get protocol() {
    return this._protocol;
  }

  /**
   * The hostname of the URL.
   * @type {string}
   */
  get hostname() {
    return this._hostname;
  }

  /**
   * Returns the entire URL.
   * @returns {string} The entire URL.
   */
  toString() {
    return this._href;
  }
}

let parseURL =
/**
 * Parses a URL to extract the protocol and the hostname.
 *
 * __This is a lightweight alternative to the native `URL` object intended for
 * use primarily within Adblock Plus. Unlike the `URL` object, the `parseURL()`
 * function is not robust and will give incorrect results for invalid URLs. Use
 * this function with valid,
 * [normalized](https://url.spec.whatwg.org/#concept-basic-url-parser),
 * properly encoded (IDNA, etc.) URLs only.__
 *
 * @param {string} url The URL.
 *
 * @returns {module:url~URLInfo} Information about the URL.
 *
 * @public
 */
exports.parseURL = function parseURL(url) {
  let match = /^([^:]+:)(?:\/\/(?:[^/]*@)?(\[[^\]]*\]|[^:/]+))?/.exec(url);
  return new URLInfo(url, match[1], match[2]);
};

let domainSuffixes =
/**
 * Yields all suffixes for a domain.
 *
 * For example, given the domain `www.example.com`, this function yields
 * `www.example.com`, `example.com`, and `com`, in that order.
 *
 * If the domain ends with a dot, the dot is ignored.
 *
 * @param {string} domain The domain.
 * @param {boolean} [includeBlank] Whether to include the blank suffix at the
 *   end.
 *
 * @generator
 * @yields {string} The next suffix for the domain.
 *
 * @package
 */
exports.domainSuffixes = function* domainSuffixes(
  domain, includeBlank = false
) {
  // Since any IP address is already expected to be normalized, there's no need
  // to validate it.
  if (isIPAddress(domain)) {
    yield domain;
  }
  else {
    if (domain[domain.length - 1] == ".")
      domain = domain.substring(0, domain.length - 1);

    while (domain != "") {
      yield domain;

      let dotIndex = domain.indexOf(".");
      domain = dotIndex == -1 ? "" : domain.substr(dotIndex + 1);
    }
  }

  if (includeBlank)
    yield "";
};

/**
 * Checks whether the given hostname refers to
 * {@link https://en.wikipedia.org/wiki/Localhost localhost}.
 *
 * If the hostname is `localhost`, `127.0.0.1`, or `[::1]`, the function
 * returns `true`; otherwise, it returns `false`.
 *
 * @param {string} hostname The hostname.
 *
 * @returns {boolean} Whether the hostname refers to localhost.
 *
 * @package
 */
exports.isLocalhost = function isLocalhost(hostname) {
  return hostname == "localhost" || hostname == "127.0.0.1" ||
         hostname == "[::1]";
};

/**
 * Checks whether the given hostname is an IP address.
 *
 * Unlike `{@link module:url~isValidIPv4Address isValidIPv4Address()}`, this
 * function only checks whether the hostname _looks like_ an IP address. Use
 * this function with valid, normalized, properly encoded (IDNA) hostnames
 * only.
 *
 * @param {string} hostname An IDNA-encoded hostname.
 *
 * @returns {boolean} Whether the hostname is an IP address.
 */
function isIPAddress(hostname) {
  // Does it look like an IPv6 address?
  if (hostname[0] == "[" && hostname[hostname.length - 1] == "]")
    return true;

  // Note: The first condition helps us avoid the more expensive regular
  // expression match for most hostnames.
  return hostname[hostname.length - 1] >= 0 &&
         /^\d+\.\d+\.\d+\.\d+$/.test(hostname);
}

/**
 * Checks whether a given address is a valid IPv4 address.
 *
 * Only a normalized IPv4 address is considered valid. e.g. `0x7f.0x0.0x0.0x1`
 * is invalid, whereas `127.0.0.1` is valid.
 *
 * @param {string} address The address to check.
 *
 * @returns {boolean} Whether the address is a valid IPv4 address.
 */
function isValidIPv4Address(address) {
  return /^(((2[0-4]|1[0-9]|[1-9])?[0-9]|25[0-5])\.){4}$/.test(address + ".");
}

/**
 * Checks whether a given hostname is valid.
 *
 * This function is used for filter validation.
 *
 * A hostname occurring in a filter must be normalized. For example,
 * <code>&#x1f642;</code> (slightly smiling face) should be normalized to
 * `xn--938h`; otherwise this function returns `false` for such a hostname.
 * Similarly, IP addresses should be normalized.
 *
 * @param {string} hostname The hostname to check.
 *
 * @returns {boolean} Whether the hostname is valid.
 */
exports.isValidHostname = function isValidHostname(hostname) {
  if (isValidIPv4Address(hostname))
    return true;

  // This does not in fact validate the IPv6 address but it's alright for now.
  if (hostname[0] == "[" && hostname[hostname.length - 1] == "]")
    return true;

  // Based on
  // https://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_hostnames
  if (hostname[hostname.length - 1] == ".")
    hostname = hostname.substring(0, hostname.length - 1);

  if (hostname.length > 253)
    return false;

  let labels = hostname.split(".");

  for (let label of labels) {
    if (!/^[a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?$/i.test(label))
      return false;
  }

  // Based on https://tools.ietf.org/html/rfc3696#section-2
  if (!/\D/.test(labels[labels.length - 1]))
    return false;

  return true;
};

let getBaseDomain =
/**
 * Gets the base domain for the given hostname.
 *
 * @param {string} hostname
 *
 * @returns {string}
 *
 * @package
 */
exports.getBaseDomain = function getBaseDomain(hostname) {
  let slices = [];
  let cutoff = NaN;

  for (let suffix of domainSuffixes(hostname)) {
    slices.push(suffix);

    let offset = publicSuffixes[suffix];

    if (typeof offset == "number") {
      cutoff = slices.length - 1 - offset;
      break;
    }
  }

  if (isNaN(cutoff))
    return slices.length > 2 ? slices[slices.length - 2] : hostname;

  if (cutoff <= 0)
    return hostname;

  return slices[cutoff];
};

/**
 * Checks whether a request's origin is different from its document's origin.
 *
 * @param {string} requestHostname The IDNA-encoded hostname of the request.
 * @param {string} documentHostname The IDNA-encoded hostname of the document.
 *
 * @returns {boolean}
 */
function isThirdParty(requestHostname, documentHostname) {
  if (requestHostname[requestHostname.length - 1] == ".")
    requestHostname = requestHostname.substring(0, requestHostname.length - 1);

  if (documentHostname[documentHostname.length - 1] == ".") {
    documentHostname =
      documentHostname.substring(0, documentHostname.length - 1);
  }

  if (requestHostname == documentHostname)
    return false;

  if (!requestHostname || !documentHostname)
    return true;

  if (isIPAddress(requestHostname) || isIPAddress(documentHostname))
    return true;

  return getBaseDomain(requestHostname) != getBaseDomain(documentHostname);
}

let URLRequest =
/**
 * The `URLRequest` class represents a URL request.
 */
exports.URLRequest = class URLRequest {
  /**
   * @private
   */
  constructor() {}

  /**
   * The URL of the request.
   * @type {string}
   */
  get href() {
    return this._href;
  }

  /**
   * Information about the URL of the request.
   * @type {module:url~URLInfo}
   * @package
   */
  get urlInfo() {
    if (!this._urlInfo)
      this._urlInfo = parseURL(this._href);

    return this._urlInfo;
  }

  /**
   * The hostname of the document making the request.
   * @type {?string}
   */
  get documentHostname() {
    return this._documentHostname == null ? null : this._documentHostname;
  }

  /**
   * Whether this is a third-party request.
   * @type {boolean}
   */
  get thirdParty() {
    if (typeof this._thirdParty == "undefined") {
      this._thirdParty = this._documentHostname == null ? false :
        isThirdParty(this.urlInfo.hostname,
          this._documentHostname);
    }

    return this._thirdParty;
  }

  /**
   * Returns the URL of the request.
   * @returns {string}
   */
  toString() {
    return this._href;
  }

  /**
   * The lower-case version of the URL of the request.
   * @type {string}
   * @package
   */
  get lowerCaseHref() {
    if (this._lowerCaseHref == null)
      this._lowerCaseHref = this._href.toLowerCase();

    return this._lowerCaseHref;
  }
};

/**
 * Returns a `{@link module:url.URLRequest URLRequest}` object for the given
 * URL.
 *
 * @param {string|module:url~URLInfo|URL} url The URL. If this is a `string`,
 *   it must be a canonicalized URL (see
 *   `{@link module:url.parseURL parseURL()}`).
 * @param {?string} [documentHostname] The IDNA-encoded hostname of the
 *   document making the request.
 *
 * @returns {module:url.URLRequest}
 */
exports.URLRequest.from = function(url, documentHostname = null) {
  let request = new URLRequest();

  if (typeof url == "string") {
    request._href = url;
  }
  else {
    request._urlInfo = url instanceof URLInfo ? url :
      new URLInfo(url.href, url.protocol, url.hostname);
    request._href = url.href;
  }

  if (documentHostname != null)
    request._documentHostname = documentHostname;

  return request;
};

/**
 * Parses the domains part of a filter text
 * (e.g. `example.com,~mail.example.com`) into a `Map` object.
 *
 * @param {string} source The domains part of a filter text.
 * @param {string} separator The string used to separate two or more domains in
 *   the domains part of a filter text.
 *
 * @returns {?Map.<string, boolean>}
 *
 * @package
 */
exports.parseDomains = function parseDomains(source, separator) {
  let domains = domainsCache.get(source);
  if (typeof domains != "undefined")
    return domains;

  if (source[0] != "~" && !source.includes(separator)) {
    // Fast track for the common one-domain scenario.
    domains = new Map([["", false], [source, true]]);
  }
  else {
    domains = null;

    let hasIncludes = false;
    for (let domain of source.split(separator)) {
      if (domain == "")
        continue;

      let include;
      if (domain[0] == "~") {
        include = false;
        domain = domain.substring(1);
      }
      else {
        include = true;
        hasIncludes = true;
      }

      if (!domains)
        domains = new Map();

      domains.set(domain, include);
    }

    if (domains)
      domains.set("", !hasIncludes);
  }

  domainsCache.set(source, domains);

  return domains;
};


/***/ }),

/***/ "./node_modules/adblockpluscore/lib/versions.js":
/*!******************************************************!*\
  !*** ./node_modules/adblockpluscore/lib/versions.js ***!
  \******************************************************/
/***/ ((__unused_webpack_module, exports) => {

"use strict";
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */



function parseVersionComponent(comp) {
  if (comp == "*")
    return Infinity;
  return parseInt(comp, 10) || 0;
}

/**
 * Compares two versions.
 *
 * @param {string} v1 The first version.
 * @param {string} v2 The second version.
 *
 * @returns {number} `-1` if `v1` is older than `v2`; `1` if `v1` is newer than
 *   `v2`; otherwise `0`.
 *
 * @package
 */
exports.compareVersions = function compareVersions(v1, v2) {
  let regexp = /^(.*?)([a-z].*)?$/i;
  let [, head1, tail1] = regexp.exec(v1);
  let [, head2, tail2] = regexp.exec(v2);
  let components1 = head1.split(".");
  let components2 = head2.split(".");

  for (let i = 0; i < components1.length ||
                  i < components2.length; i++) {
    let result = parseVersionComponent(components1[i]) -
                 parseVersionComponent(components2[i]) || 0;

    if (result < 0)
      return -1;
    else if (result > 0)
      return 1;
  }

  // Compare version suffix (e.g. 0.1alpha < 0.1b1 < 01.b2 < 0.1).
  // However, note that this is a simple string comparision, meaning: b10 < b2
  if (tail1 == tail2)
    return 0;
  if (!tail1 || tail2 && tail1 > tail2)
    return 1;
  return -1;
};


/***/ }),

/***/ "./node_modules/webextension-polyfill/dist/browser-polyfill.js":
/*!*********************************************************************!*\
  !*** ./node_modules/webextension-polyfill/dist/browser-polyfill.js ***!
  \*********************************************************************/
/***/ (function(module, exports) {

var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
  if (true) {
    !(__WEBPACK_AMD_DEFINE_ARRAY__ = [module], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
		__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
		(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
		__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
  } else { var mod; }
})(typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : this, function (module) {
  /* webextension-polyfill - v0.8.0 - Tue Apr 20 2021 11:27:38 */

  /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */

  /* vim: set sts=2 sw=2 et tw=80: */

  /* This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  "use strict";

  if (typeof browser === "undefined" || Object.getPrototypeOf(browser) !== Object.prototype) {
    const CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE = "The message port closed before a response was received.";
    const SEND_RESPONSE_DEPRECATION_WARNING = "Returning a Promise is the preferred way to send a reply from an onMessage/onMessageExternal listener, as the sendResponse will be removed from the specs (See https://developer.mozilla.org/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage)"; // Wrapping the bulk of this polyfill in a one-time-use function is a minor
    // optimization for Firefox. Since Spidermonkey does not fully parse the
    // contents of a function until the first time it's called, and since it will
    // never actually need to be called, this allows the polyfill to be included
    // in Firefox nearly for free.

    const wrapAPIs = extensionAPIs => {
      // NOTE: apiMetadata is associated to the content of the api-metadata.json file
      // at build time by replacing the following "include" with the content of the
      // JSON file.
      const apiMetadata = {
        "alarms": {
          "clear": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "clearAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "get": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "bookmarks": {
          "create": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getChildren": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getRecent": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getSubTree": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTree": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "move": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeTree": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "browserAction": {
          "disable": {
            "minArgs": 0,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "enable": {
            "minArgs": 0,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "getBadgeBackgroundColor": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getBadgeText": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getPopup": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTitle": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "openPopup": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "setBadgeBackgroundColor": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setBadgeText": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setIcon": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "setPopup": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setTitle": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "browsingData": {
          "remove": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "removeCache": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeCookies": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeDownloads": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeFormData": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeHistory": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeLocalStorage": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removePasswords": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removePluginData": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "settings": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "commands": {
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "contextMenus": {
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "cookies": {
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAllCookieStores": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "set": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "devtools": {
          "inspectedWindow": {
            "eval": {
              "minArgs": 1,
              "maxArgs": 2,
              "singleCallbackArg": false
            }
          },
          "panels": {
            "create": {
              "minArgs": 3,
              "maxArgs": 3,
              "singleCallbackArg": true
            },
            "elements": {
              "createSidebarPane": {
                "minArgs": 1,
                "maxArgs": 1
              }
            }
          }
        },
        "downloads": {
          "cancel": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "download": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "erase": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getFileIcon": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "open": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "pause": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeFile": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "resume": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "show": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "extension": {
          "isAllowedFileSchemeAccess": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "isAllowedIncognitoAccess": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "history": {
          "addUrl": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "deleteAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "deleteRange": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "deleteUrl": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getVisits": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "search": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "i18n": {
          "detectLanguage": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAcceptLanguages": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "identity": {
          "launchWebAuthFlow": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "idle": {
          "queryState": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "management": {
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getSelf": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "setEnabled": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "uninstallSelf": {
            "minArgs": 0,
            "maxArgs": 1
          }
        },
        "notifications": {
          "clear": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "create": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getPermissionLevel": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        },
        "pageAction": {
          "getPopup": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getTitle": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "hide": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setIcon": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "setPopup": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "setTitle": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          },
          "show": {
            "minArgs": 1,
            "maxArgs": 1,
            "fallbackToNoCallback": true
          }
        },
        "permissions": {
          "contains": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "request": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "runtime": {
          "getBackgroundPage": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getPlatformInfo": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "openOptionsPage": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "requestUpdateCheck": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "sendMessage": {
            "minArgs": 1,
            "maxArgs": 3
          },
          "sendNativeMessage": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "setUninstallURL": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "sessions": {
          "getDevices": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getRecentlyClosed": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "restore": {
            "minArgs": 0,
            "maxArgs": 1
          }
        },
        "storage": {
          "local": {
            "clear": {
              "minArgs": 0,
              "maxArgs": 0
            },
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "remove": {
              "minArgs": 1,
              "maxArgs": 1
            },
            "set": {
              "minArgs": 1,
              "maxArgs": 1
            }
          },
          "managed": {
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            }
          },
          "sync": {
            "clear": {
              "minArgs": 0,
              "maxArgs": 0
            },
            "get": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "getBytesInUse": {
              "minArgs": 0,
              "maxArgs": 1
            },
            "remove": {
              "minArgs": 1,
              "maxArgs": 1
            },
            "set": {
              "minArgs": 1,
              "maxArgs": 1
            }
          }
        },
        "tabs": {
          "captureVisibleTab": {
            "minArgs": 0,
            "maxArgs": 2
          },
          "create": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "detectLanguage": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "discard": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "duplicate": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "executeScript": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getCurrent": {
            "minArgs": 0,
            "maxArgs": 0
          },
          "getZoom": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getZoomSettings": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "goBack": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "goForward": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "highlight": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "insertCSS": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "move": {
            "minArgs": 2,
            "maxArgs": 2
          },
          "query": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "reload": {
            "minArgs": 0,
            "maxArgs": 2
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "removeCSS": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "sendMessage": {
            "minArgs": 2,
            "maxArgs": 3
          },
          "setZoom": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "setZoomSettings": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "update": {
            "minArgs": 1,
            "maxArgs": 2
          }
        },
        "topSites": {
          "get": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "webNavigation": {
          "getAllFrames": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "getFrame": {
            "minArgs": 1,
            "maxArgs": 1
          }
        },
        "webRequest": {
          "handlerBehaviorChanged": {
            "minArgs": 0,
            "maxArgs": 0
          }
        },
        "windows": {
          "create": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "get": {
            "minArgs": 1,
            "maxArgs": 2
          },
          "getAll": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getCurrent": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "getLastFocused": {
            "minArgs": 0,
            "maxArgs": 1
          },
          "remove": {
            "minArgs": 1,
            "maxArgs": 1
          },
          "update": {
            "minArgs": 2,
            "maxArgs": 2
          }
        }
      };

      if (Object.keys(apiMetadata).length === 0) {
        throw new Error("api-metadata.json has not been included in browser-polyfill");
      }
      /**
       * A WeakMap subclass which creates and stores a value for any key which does
       * not exist when accessed, but behaves exactly as an ordinary WeakMap
       * otherwise.
       *
       * @param {function} createItem
       *        A function which will be called in order to create the value for any
       *        key which does not exist, the first time it is accessed. The
       *        function receives, as its only argument, the key being created.
       */


      class DefaultWeakMap extends WeakMap {
        constructor(createItem, items = undefined) {
          super(items);
          this.createItem = createItem;
        }

        get(key) {
          if (!this.has(key)) {
            this.set(key, this.createItem(key));
          }

          return super.get(key);
        }

      }
      /**
       * Returns true if the given object is an object with a `then` method, and can
       * therefore be assumed to behave as a Promise.
       *
       * @param {*} value The value to test.
       * @returns {boolean} True if the value is thenable.
       */


      const isThenable = value => {
        return value && typeof value === "object" && typeof value.then === "function";
      };
      /**
       * Creates and returns a function which, when called, will resolve or reject
       * the given promise based on how it is called:
       *
       * - If, when called, `chrome.runtime.lastError` contains a non-null object,
       *   the promise is rejected with that value.
       * - If the function is called with exactly one argument, the promise is
       *   resolved to that value.
       * - Otherwise, the promise is resolved to an array containing all of the
       *   function's arguments.
       *
       * @param {object} promise
       *        An object containing the resolution and rejection functions of a
       *        promise.
       * @param {function} promise.resolve
       *        The promise's resolution function.
       * @param {function} promise.reject
       *        The promise's rejection function.
       * @param {object} metadata
       *        Metadata about the wrapped method which has created the callback.
       * @param {boolean} metadata.singleCallbackArg
       *        Whether or not the promise is resolved with only the first
       *        argument of the callback, alternatively an array of all the
       *        callback arguments is resolved. By default, if the callback
       *        function is invoked with only a single argument, that will be
       *        resolved to the promise, while all arguments will be resolved as
       *        an array if multiple are given.
       *
       * @returns {function}
       *        The generated callback function.
       */


      const makeCallback = (promise, metadata) => {
        return (...callbackArgs) => {
          if (extensionAPIs.runtime.lastError) {
            promise.reject(new Error(extensionAPIs.runtime.lastError.message));
          } else if (metadata.singleCallbackArg || callbackArgs.length <= 1 && metadata.singleCallbackArg !== false) {
            promise.resolve(callbackArgs[0]);
          } else {
            promise.resolve(callbackArgs);
          }
        };
      };

      const pluralizeArguments = numArgs => numArgs == 1 ? "argument" : "arguments";
      /**
       * Creates a wrapper function for a method with the given name and metadata.
       *
       * @param {string} name
       *        The name of the method which is being wrapped.
       * @param {object} metadata
       *        Metadata about the method being wrapped.
       * @param {integer} metadata.minArgs
       *        The minimum number of arguments which must be passed to the
       *        function. If called with fewer than this number of arguments, the
       *        wrapper will raise an exception.
       * @param {integer} metadata.maxArgs
       *        The maximum number of arguments which may be passed to the
       *        function. If called with more than this number of arguments, the
       *        wrapper will raise an exception.
       * @param {boolean} metadata.singleCallbackArg
       *        Whether or not the promise is resolved with only the first
       *        argument of the callback, alternatively an array of all the
       *        callback arguments is resolved. By default, if the callback
       *        function is invoked with only a single argument, that will be
       *        resolved to the promise, while all arguments will be resolved as
       *        an array if multiple are given.
       *
       * @returns {function(object, ...*)}
       *       The generated wrapper function.
       */


      const wrapAsyncFunction = (name, metadata) => {
        return function asyncFunctionWrapper(target, ...args) {
          if (args.length < metadata.minArgs) {
            throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
          }

          if (args.length > metadata.maxArgs) {
            throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
          }

          return new Promise((resolve, reject) => {
            if (metadata.fallbackToNoCallback) {
              // This API method has currently no callback on Chrome, but it return a promise on Firefox,
              // and so the polyfill will try to call it with a callback first, and it will fallback
              // to not passing the callback if the first call fails.
              try {
                target[name](...args, makeCallback({
                  resolve,
                  reject
                }, metadata));
              } catch (cbError) {
                console.warn(`${name} API method doesn't seem to support the callback parameter, ` + "falling back to call it without a callback: ", cbError);
                target[name](...args); // Update the API method metadata, so that the next API calls will not try to
                // use the unsupported callback anymore.

                metadata.fallbackToNoCallback = false;
                metadata.noCallback = true;
                resolve();
              }
            } else if (metadata.noCallback) {
              target[name](...args);
              resolve();
            } else {
              target[name](...args, makeCallback({
                resolve,
                reject
              }, metadata));
            }
          });
        };
      };
      /**
       * Wraps an existing method of the target object, so that calls to it are
       * intercepted by the given wrapper function. The wrapper function receives,
       * as its first argument, the original `target` object, followed by each of
       * the arguments passed to the original method.
       *
       * @param {object} target
       *        The original target object that the wrapped method belongs to.
       * @param {function} method
       *        The method being wrapped. This is used as the target of the Proxy
       *        object which is created to wrap the method.
       * @param {function} wrapper
       *        The wrapper function which is called in place of a direct invocation
       *        of the wrapped method.
       *
       * @returns {Proxy<function>}
       *        A Proxy object for the given method, which invokes the given wrapper
       *        method in its place.
       */


      const wrapMethod = (target, method, wrapper) => {
        return new Proxy(method, {
          apply(targetMethod, thisObj, args) {
            return wrapper.call(thisObj, target, ...args);
          }

        });
      };

      let hasOwnProperty = Function.call.bind(Object.prototype.hasOwnProperty);
      /**
       * Wraps an object in a Proxy which intercepts and wraps certain methods
       * based on the given `wrappers` and `metadata` objects.
       *
       * @param {object} target
       *        The target object to wrap.
       *
       * @param {object} [wrappers = {}]
       *        An object tree containing wrapper functions for special cases. Any
       *        function present in this object tree is called in place of the
       *        method in the same location in the `target` object tree. These
       *        wrapper methods are invoked as described in {@see wrapMethod}.
       *
       * @param {object} [metadata = {}]
       *        An object tree containing metadata used to automatically generate
       *        Promise-based wrapper functions for asynchronous. Any function in
       *        the `target` object tree which has a corresponding metadata object
       *        in the same location in the `metadata` tree is replaced with an
       *        automatically-generated wrapper function, as described in
       *        {@see wrapAsyncFunction}
       *
       * @returns {Proxy<object>}
       */

      const wrapObject = (target, wrappers = {}, metadata = {}) => {
        let cache = Object.create(null);
        let handlers = {
          has(proxyTarget, prop) {
            return prop in target || prop in cache;
          },

          get(proxyTarget, prop, receiver) {
            if (prop in cache) {
              return cache[prop];
            }

            if (!(prop in target)) {
              return undefined;
            }

            let value = target[prop];

            if (typeof value === "function") {
              // This is a method on the underlying object. Check if we need to do
              // any wrapping.
              if (typeof wrappers[prop] === "function") {
                // We have a special-case wrapper for this method.
                value = wrapMethod(target, target[prop], wrappers[prop]);
              } else if (hasOwnProperty(metadata, prop)) {
                // This is an async method that we have metadata for. Create a
                // Promise wrapper for it.
                let wrapper = wrapAsyncFunction(prop, metadata[prop]);
                value = wrapMethod(target, target[prop], wrapper);
              } else {
                // This is a method that we don't know or care about. Return the
                // original method, bound to the underlying object.
                value = value.bind(target);
              }
            } else if (typeof value === "object" && value !== null && (hasOwnProperty(wrappers, prop) || hasOwnProperty(metadata, prop))) {
              // This is an object that we need to do some wrapping for the children
              // of. Create a sub-object wrapper for it with the appropriate child
              // metadata.
              value = wrapObject(value, wrappers[prop], metadata[prop]);
            } else if (hasOwnProperty(metadata, "*")) {
              // Wrap all properties in * namespace.
              value = wrapObject(value, wrappers[prop], metadata["*"]);
            } else {
              // We don't need to do any wrapping for this property,
              // so just forward all access to the underlying object.
              Object.defineProperty(cache, prop, {
                configurable: true,
                enumerable: true,

                get() {
                  return target[prop];
                },

                set(value) {
                  target[prop] = value;
                }

              });
              return value;
            }

            cache[prop] = value;
            return value;
          },

          set(proxyTarget, prop, value, receiver) {
            if (prop in cache) {
              cache[prop] = value;
            } else {
              target[prop] = value;
            }

            return true;
          },

          defineProperty(proxyTarget, prop, desc) {
            return Reflect.defineProperty(cache, prop, desc);
          },

          deleteProperty(proxyTarget, prop) {
            return Reflect.deleteProperty(cache, prop);
          }

        }; // Per contract of the Proxy API, the "get" proxy handler must return the
        // original value of the target if that value is declared read-only and
        // non-configurable. For this reason, we create an object with the
        // prototype set to `target` instead of using `target` directly.
        // Otherwise we cannot return a custom object for APIs that
        // are declared read-only and non-configurable, such as `chrome.devtools`.
        //
        // The proxy handlers themselves will still use the original `target`
        // instead of the `proxyTarget`, so that the methods and properties are
        // dereferenced via the original targets.

        let proxyTarget = Object.create(target);
        return new Proxy(proxyTarget, handlers);
      };
      /**
       * Creates a set of wrapper functions for an event object, which handles
       * wrapping of listener functions that those messages are passed.
       *
       * A single wrapper is created for each listener function, and stored in a
       * map. Subsequent calls to `addListener`, `hasListener`, or `removeListener`
       * retrieve the original wrapper, so that  attempts to remove a
       * previously-added listener work as expected.
       *
       * @param {DefaultWeakMap<function, function>} wrapperMap
       *        A DefaultWeakMap object which will create the appropriate wrapper
       *        for a given listener function when one does not exist, and retrieve
       *        an existing one when it does.
       *
       * @returns {object}
       */


      const wrapEvent = wrapperMap => ({
        addListener(target, listener, ...args) {
          target.addListener(wrapperMap.get(listener), ...args);
        },

        hasListener(target, listener) {
          return target.hasListener(wrapperMap.get(listener));
        },

        removeListener(target, listener) {
          target.removeListener(wrapperMap.get(listener));
        }

      });

      const onRequestFinishedWrappers = new DefaultWeakMap(listener => {
        if (typeof listener !== "function") {
          return listener;
        }
        /**
         * Wraps an onRequestFinished listener function so that it will return a
         * `getContent()` property which returns a `Promise` rather than using a
         * callback API.
         *
         * @param {object} req
         *        The HAR entry object representing the network request.
         */


        return function onRequestFinished(req) {
          const wrappedReq = wrapObject(req, {}
          /* wrappers */
          , {
            getContent: {
              minArgs: 0,
              maxArgs: 0
            }
          });
          listener(wrappedReq);
        };
      }); // Keep track if the deprecation warning has been logged at least once.

      let loggedSendResponseDeprecationWarning = false;
      const onMessageWrappers = new DefaultWeakMap(listener => {
        if (typeof listener !== "function") {
          return listener;
        }
        /**
         * Wraps a message listener function so that it may send responses based on
         * its return value, rather than by returning a sentinel value and calling a
         * callback. If the listener function returns a Promise, the response is
         * sent when the promise either resolves or rejects.
         *
         * @param {*} message
         *        The message sent by the other end of the channel.
         * @param {object} sender
         *        Details about the sender of the message.
         * @param {function(*)} sendResponse
         *        A callback which, when called with an arbitrary argument, sends
         *        that value as a response.
         * @returns {boolean}
         *        True if the wrapped listener returned a Promise, which will later
         *        yield a response. False otherwise.
         */


        return function onMessage(message, sender, sendResponse) {
          let didCallSendResponse = false;
          let wrappedSendResponse;
          let sendResponsePromise = new Promise(resolve => {
            wrappedSendResponse = function (response) {
              if (!loggedSendResponseDeprecationWarning) {
                console.warn(SEND_RESPONSE_DEPRECATION_WARNING, new Error().stack);
                loggedSendResponseDeprecationWarning = true;
              }

              didCallSendResponse = true;
              resolve(response);
            };
          });
          let result;

          try {
            result = listener(message, sender, wrappedSendResponse);
          } catch (err) {
            result = Promise.reject(err);
          }

          const isResultThenable = result !== true && isThenable(result); // If the listener didn't returned true or a Promise, or called
          // wrappedSendResponse synchronously, we can exit earlier
          // because there will be no response sent from this listener.

          if (result !== true && !isResultThenable && !didCallSendResponse) {
            return false;
          } // A small helper to send the message if the promise resolves
          // and an error if the promise rejects (a wrapped sendMessage has
          // to translate the message into a resolved promise or a rejected
          // promise).


          const sendPromisedResult = promise => {
            promise.then(msg => {
              // send the message value.
              sendResponse(msg);
            }, error => {
              // Send a JSON representation of the error if the rejected value
              // is an instance of error, or the object itself otherwise.
              let message;

              if (error && (error instanceof Error || typeof error.message === "string")) {
                message = error.message;
              } else {
                message = "An unexpected error occurred";
              }

              sendResponse({
                __mozWebExtensionPolyfillReject__: true,
                message
              });
            }).catch(err => {
              // Print an error on the console if unable to send the response.
              console.error("Failed to send onMessage rejected reply", err);
            });
          }; // If the listener returned a Promise, send the resolved value as a
          // result, otherwise wait the promise related to the wrappedSendResponse
          // callback to resolve and send it as a response.


          if (isResultThenable) {
            sendPromisedResult(result);
          } else {
            sendPromisedResult(sendResponsePromise);
          } // Let Chrome know that the listener is replying.


          return true;
        };
      });

      const wrappedSendMessageCallback = ({
        reject,
        resolve
      }, reply) => {
        if (extensionAPIs.runtime.lastError) {
          // Detect when none of the listeners replied to the sendMessage call and resolve
          // the promise to undefined as in Firefox.
          // See https://github.com/mozilla/webextension-polyfill/issues/130
          if (extensionAPIs.runtime.lastError.message === CHROME_SEND_MESSAGE_CALLBACK_NO_RESPONSE_MESSAGE) {
            resolve();
          } else {
            reject(new Error(extensionAPIs.runtime.lastError.message));
          }
        } else if (reply && reply.__mozWebExtensionPolyfillReject__) {
          // Convert back the JSON representation of the error into
          // an Error instance.
          reject(new Error(reply.message));
        } else {
          resolve(reply);
        }
      };

      const wrappedSendMessage = (name, metadata, apiNamespaceObj, ...args) => {
        if (args.length < metadata.minArgs) {
          throw new Error(`Expected at least ${metadata.minArgs} ${pluralizeArguments(metadata.minArgs)} for ${name}(), got ${args.length}`);
        }

        if (args.length > metadata.maxArgs) {
          throw new Error(`Expected at most ${metadata.maxArgs} ${pluralizeArguments(metadata.maxArgs)} for ${name}(), got ${args.length}`);
        }

        return new Promise((resolve, reject) => {
          const wrappedCb = wrappedSendMessageCallback.bind(null, {
            resolve,
            reject
          });
          args.push(wrappedCb);
          apiNamespaceObj.sendMessage(...args);
        });
      };

      const staticWrappers = {
        devtools: {
          network: {
            onRequestFinished: wrapEvent(onRequestFinishedWrappers)
          }
        },
        runtime: {
          onMessage: wrapEvent(onMessageWrappers),
          onMessageExternal: wrapEvent(onMessageWrappers),
          sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
            minArgs: 1,
            maxArgs: 3
          })
        },
        tabs: {
          sendMessage: wrappedSendMessage.bind(null, "sendMessage", {
            minArgs: 2,
            maxArgs: 3
          })
        }
      };
      const settingMetadata = {
        clear: {
          minArgs: 1,
          maxArgs: 1
        },
        get: {
          minArgs: 1,
          maxArgs: 1
        },
        set: {
          minArgs: 1,
          maxArgs: 1
        }
      };
      apiMetadata.privacy = {
        network: {
          "*": settingMetadata
        },
        services: {
          "*": settingMetadata
        },
        websites: {
          "*": settingMetadata
        }
      };
      return wrapObject(extensionAPIs, staticWrappers, apiMetadata);
    };

    if (typeof chrome != "object" || !chrome || !chrome.runtime || !chrome.runtime.id) {
      throw new Error("This script should only be loaded in a browser extension.");
    } // The build process adds a UMD wrapper around this file, which makes the
    // `module` variable available.


    module.exports = wrapAPIs(chrome);
  } else {
    module.exports = browser;
  }
});


/***/ }),

/***/ "./sdk/api/allowlisting.js":
/*!*********************************!*\
  !*** ./sdk/api/allowlisting.js ***!
  \*********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_608726__) => {

"use strict";
__nested_webpack_require_608726__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_608726__.d(__webpack_exports__, {
/* harmony export */   "allowlistPage": () => (/* binding */ allowlistPage),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_608726__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_608726__(/*! adblockpluscore/lib/url.js */ "./node_modules/adblockpluscore/lib/url.js");
/* harmony import */ var adblockpluscore_lib_time_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_608726__(/*! adblockpluscore/lib/time.js */ "./node_modules/adblockpluscore/lib/time.js");
/* harmony import */ var adblockpluscore_lib_rsa_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_608726__(/*! adblockpluscore/lib/rsa.js */ "./node_modules/adblockpluscore/lib/rsa.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_608726__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_608726__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/* harmony import */ var _filters_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_608726__(/*! ./filters.js */ "./sdk/api/filters.js");
/* harmony import */ var _types_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_608726__(/*! ./types.js */ "./sdk/api/types.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */











// Note that this is a default implementation, but it might be
// replaced using `setAllowlistingCallback`. Don't rely on this
// behaviour.
let allowlistingCallback = function(domain) {
  return _filters_js__WEBPACK_IMPORTED_MODULE_6__.default.add([`@@||${domain}^$document`]);
};
let dispatchUnauthorized = () => {};

let authorizedPublicKeys = [];
let publicKeysUpdated = Promise.resolve();

let algorithm = {
  name: "RSASSA-PKCS1-v1_5",
  modulusLength: 4096,
  publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
  hash: {name: "SHA-512"}
};

function getAllowData(domain, timestamp) {
  let str = `${domain},${timestamp}`;
  return (new TextEncoder()).encode(str);
}

async function verifySignature(data, signature, pubKey) {
  return crypto.subtle.verify(
    algorithm,
    pubKey,
    signature,
    data
  );
}

function verifyTimestamp(timestamp) {
  if (typeof timestamp != "number" || isNaN(timestamp))
    return false;

  let msSinceSigning = Date.now() - timestamp;
  return msSinceSigning >= 0 && msSinceSigning < adblockpluscore_lib_time_js__WEBPACK_IMPORTED_MODULE_2__.MILLIS_IN_HOUR;
}

async function verifyAnySignatures(domain, timestamp, signature) {
  if (typeof signature != "string")
    return false;

  await publicKeysUpdated;

  let data = getAllowData(domain, timestamp);
  let abSignature = (0,adblockpluscore_lib_rsa_js__WEBPACK_IMPORTED_MODULE_3__.base64ToArrayBuffer)(signature);
  for (let key of authorizedPublicKeys) {
    if (await verifySignature(data, abSignature, key))
      return true;
  }
  return false;
}

async function succeedAllowlisting(domain) {
  await allowlistingCallback(domain);
  return true;
}

function failAllowlisting(error) {
  dispatchUnauthorized(error);
  return false;
}

async function allowlistPage(tabId, frameId, timestamp, signature) {
  let frame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_5__.getFrameInfo)(tabId, frameId);
  if (!frame) {
    return failAllowlisting({
      reason: "invalid_frame",
      request: {domain: null, timestamp, signature}
    });
  }

  let domain = frame.hostname;
  let request = {domain, timestamp, signature};

  if (frameId != 0) {
    return failAllowlisting({
      reason: "invalid_frame",
      request
    });
  }

  let urlInfo = (0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_1__.parseURL)(frame.url);
  let alreadyAllowlistedDomain = _core_js__WEBPACK_IMPORTED_MODULE_4__.filterEngine.defaultMatcher.isAllowlisted(
    `${urlInfo.protocol}//${domain}`,
    adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_0__.contentTypes.DOCUMENT,
    domain,
    frame.sitekey
  );
  if (alreadyAllowlistedDomain) {
    return failAllowlisting({
      reason: "already_allowlisted",
      request
    });
  }

  let validTimestamp = verifyTimestamp(timestamp);
  if (!validTimestamp) {
    return failAllowlisting({
      reason: "invalid_timestamp",
      request
    });
  }

  let validSignature = await verifyAnySignatures(domain, timestamp, signature);
  if (!validSignature) {
    return failAllowlisting({
      reason: "invalid_signature",
      request
    });
  }

  return await succeedAllowlisting(domain);
}

async function setAuthorizedKeys(keys) {
  let newAuthorizedPublicKeys = [];
  for (let key of keys) {
    let abKey = (0,adblockpluscore_lib_rsa_js__WEBPACK_IMPORTED_MODULE_3__.base64ToArrayBuffer)(key);
    let importedKey = await crypto.subtle.importKey(
      "spki",
      abKey,
      algorithm,
      false,
      ["verify"]
    );
    newAuthorizedPublicKeys.push(importedKey);
  }
  authorizedPublicKeys = newAuthorizedPublicKeys;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * Updates the list of public keys used to verify allowlisting
   * requests. If there are any invalid keys, the list of authorized
   * keys keeps its previous value.
   *
   * Any allowlisting requests that come in while this function is in
   * progress will wait for it to finish before verifying any
   * signatures.
   *
   * @param {[string]} keys The new set of public keys. The keys
   *   should be base64 encoded strings, in SPKI format. The keys must
   *   additionally use the RSASSA-PKCS1-v1_5 algorithm, SHA512 hash
   *   and 4096 bit long modulus.
   * @return {Promise} Promise that resolves when the keys have been
   *   updated, or rejects if any of the keys are invalid.
   */
  async setAuthorizedKeys(keys) {
    let resultPromise = setAuthorizedKeys(keys);
    publicKeysUpdated = resultPromise.catch(() => {});
    return await resultPromise;
  },

  /**
   * @callback allowlistingCallback
   * @param {string} domain The domain to allowlist.
   */

  /**
   * Set the function called when allowlisting succeeds.
   *
   * If the callback is not set, it has a default implementation that
   * adds an allowlisting filter for the allowlisted domain.
   *
   * @param {allowlistingCallback} callback The user defined function
   *   that will be called. This function should return a promise that
   *   resolves after adding the appropriate allowlisting filters.
   */
  setAllowlistingCallback(callback) {
    allowlistingCallback = callback;
  },

  /**
   * @typedef {Object} AllowlistingAuthorizationError
   * @property {string} reason The reason a request to allowlist was
   *   rejected. Can be "invalid_frame", "already_allowlisted",
   *   "invalid_timestamp", or "invalid_signature".
   * @property {Object} request The rejected request.
   * @property {string} [request.domain] The domain of the page that
   *   the request came from. This is also the domain that the request
   *   would have allowlisted if it was valid. If this is null, it
   *   means that the frame's domain could not be determined.
   * @property {*} request.timestamp The timestamp in the
   *   request. For a valid request this is a number, but the request
   *   may have been invalid so it might not be a number.
   * @property {*} request.signature The signature in the
   *   request. For a valid request, this is string, but the request
   *   may have been invalid so it might not be a string.
   */

  /**
   * Emitted when an allowlisting request is rejected.
   * @event
   * @type {EventDispatcher<AllowlistingAuthorizationError>}
   */
  onUnauthorized: new _types_js__WEBPACK_IMPORTED_MODULE_7__.EventDispatcher(
    dispatch => {
      dispatchUnauthorized = dispatch;
    },
    () => {
      dispatchUnauthorized = () => {};
    }
  )
});


/***/ }),

/***/ "./sdk/api/browser-features.js":
/*!*************************************!*\
  !*** ./sdk/api/browser-features.js ***!
  \*************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_617711__) => {

"use strict";
__nested_webpack_require_617711__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_617711__.d(__webpack_exports__, {
/* harmony export */   "isRunningInServiceWorker": () => (/* binding */ isRunningInServiceWorker)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_617711__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



let manifest = _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getManifest();

function isRunningInServiceWorker() {
  return !!(manifest.background && manifest.background.service_worker);
}


/***/ }),

/***/ "./sdk/api/content-filter.js":
/*!***********************************!*\
  !*** ./sdk/api/content-filter.js ***!
  \***********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_619242__) => {

"use strict";
__nested_webpack_require_619242__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_619242__.d(__webpack_exports__, {
/* harmony export */   "setSnippetLibrary": () => (/* binding */ setSnippetLibrary),
/* harmony export */   "applyContentFilters": () => (/* binding */ applyContentFilters),
/* harmony export */   "injectCSS": () => (/* binding */ injectCSS)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_619242__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_elemHide_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_619242__(/*! adblockpluscore/lib/elemHide.js */ "./node_modules/adblockpluscore/lib/elemHide.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_619242__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var adblockpluscore_lib_snippets_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_619242__(/*! adblockpluscore/lib/snippets.js */ "./node_modules/adblockpluscore/lib/snippets.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_619242__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_619242__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_619242__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _debugging_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_619242__(/*! ./debugging.js */ "./sdk/api/debugging.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */












let isolatedLib;
let injectedLib;

function setSnippetLibrary({isolatedCode, injectedCode}) {
  isolatedLib = isolatedCode;
  injectedLib = injectedCode;
}

async function applyContentFilters(tabId, frameId) {
  let frame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_5__.getFrameInfo)(tabId, frameId);
  let details = {tabId, frameIds: [frameId]};
  let emulatedPatterns = [];
  let tracedSelectors;

  if (!(frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT)) {
    let filters = _core_js__WEBPACK_IMPORTED_MODULE_4__.filterEngine.snippets.getFilters(frame.hostname);

    if (filters.length > 0) {
      let scripts = filters.map(({script}) => script);
      let environment = {};
      if (_debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.elemHide)
        environment.debugCSSProperties = _debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.snippetsCssProperties;

      let isolatedDependencies = [];
      let isolated = [];
      let main = [];

      for (let script of scripts) {
        for (let [snippet, ...args] of (0,adblockpluscore_lib_snippets_js__WEBPACK_IMPORTED_MODULE_3__.parseScript)(script)) {
          if (isolatedLib.has(snippet)) {
            let dependency = isolatedLib.get(snippet);
            if (dependency)
              isolatedDependencies.push(dependency);
            isolated.push([snippet, ...args]);
          }
          if (injectedLib.has(snippet))
            main.push([snippet, ...args]);
        }
      }

      let execute = [];
      if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting && webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting.executeScript) {
        if (isolated.length > 0) {
          if (isolatedDependencies.length) {
            let isolatedDepsPromises = [];
            for (let dependency of isolatedDependencies) {
              isolatedDepsPromises.push(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting.executeScript({
                target: details,
                world: "ISOLATED",
                func: dependency
              }));
            }
            await Promise.all(isolatedDepsPromises);
          }

          execute.push(
            webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting.executeScript({
              target: details,
              world: "ISOLATED",
              func: isolatedLib,
              args: [environment, ...isolated]
            })
          );
        }

        if (main.length > 0) {
          execute.push(
            webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting.executeScript({
              target: details,
              world: "MAIN",
              func: injectedLib,
              args: [environment, ...main]
            })
          );
        }
      }
      else {
        if (isolated.length > 0) {
          const args = JSON.stringify([environment, ...isolated]);
          let code = "";
          // prepend all dependencies before the snippets
          if (isolatedDependencies.length) {
            for (const cb of isolatedDependencies)
              code += `(${cb})();`;
          }
          code += `(${isolatedLib}).apply(null,${args})`;
          execute.push(
            webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.executeScript(
              tabId,
              {
                frameId,
                code,
                matchAboutBlank: true,
                runAt: "document_start"
              }));
        }

        if (main.length > 0) {
          const args = JSON.stringify([environment, ...main]);
          // stringify injectedLib to escape backticks
          let code = JSON.stringify(injectedLib.toString());
          code = `"(${code.slice(1, -1)}).apply(null,${JSON.stringify(args).slice(1, -1)});"`;
          let executable =
          `function injectSnippetsInMainContext(executable)
          {
            // injecting phases
            let script = document.createElement("script");
            script.type = "application/javascript";
            script.async = false;

            // Firefox 58 only bypasses site CSPs when assigning to 'src',
            // while Chrome 67 and Microsoft Edge (tested on 44.17763.1.0)
            // only bypass site CSPs when using 'textContent'.
            if (typeof netscape != "undefined" && typeof browser != "undefined")
            {
              let url = URL.createObjectURL(new Blob([executable]));
              script.src = url;
              document.documentElement.appendChild(script);
              URL.revokeObjectURL(url);
            }
            else
            {
              script.textContent = executable;
              document.documentElement.appendChild(script);
            }

            document.documentElement.removeChild(script);
          };
          const executable = ${code};
          injectSnippetsInMainContext(executable);`;
          execute.push(
            webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.executeScript(
              tabId,
              {
                frameId,
                code: executable,
                matchAboutBlank: true,
                runAt: "document_start"
              }));
        }
      }

      let request = {tabId, frameId, url: frame.url};
      Promise.all(execute).then(() => filters.forEach(filter => {
        (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_6__.logItem)(request, filter, {
          docDomain: frame.hostname,
          method: "snippet"
        });
      }), () => {});
    }

    if (!(frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.ELEMHIDE)) {
      let specificOnly = (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICHIDE) != 0;
      let trace = (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_6__.tracingEnabled)(tabId);
      let styleSheet = _core_js__WEBPACK_IMPORTED_MODULE_4__.filterEngine.elemHide.getStyleSheet(
        frame.hostname,
        specificOnly, trace || _debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.elemHide,
        trace
      );

      if (_debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.elemHide) {
        let declarationBlock = "{";
        for (let [property, value] of _debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.cssProperties)
          declarationBlock += `${property}: ${value} !important;`;
        declarationBlock += "}";

        styleSheet.code = (0,adblockpluscore_lib_elemHide_js__WEBPACK_IMPORTED_MODULE_1__.createStyleSheet)(styleSheet.selectors,
                                           declarationBlock);
      }

      injectCSS(tabId, frameId, styleSheet.code);

      for (let {selector, text} of _core_js__WEBPACK_IMPORTED_MODULE_4__.filterEngine.elemHideEmulation.getFilters(
        frame.hostname))
        emulatedPatterns.push({selector, text});

      if (trace) {
        tracedSelectors = [];
        for (let selector of styleSheet.selectors)
          tracedSelectors.push([selector, null]);
        for (let exception of styleSheet.exceptions)
          tracedSelectors.push([exception.selector, exception.text]);
      }
    }
  }

  let cssProperties;
  if (_debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.elemHide)
    cssProperties = _debugging_js__WEBPACK_IMPORTED_MODULE_7__.debugOptions.cssProperties;
  return {emulatedPatterns, cssProperties, tracedSelectors};
}

function injectCSS(tabId, frameId, code) {
  let result;

  if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting && webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting.insertCSS) {
    result = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.scripting.insertCSS({
      target: {tabId, frameIds: [frameId]},
      css: code,
      origin: "USER"
    });
  }
  else {
    result = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.insertCSS(
      tabId,
      {
        code,
        cssOrigin: "user",
        frameId,
        matchAboutBlank: true,
        runAt: "document_start"
      }
    );
  }

  result.catch(() => {}); // Fails if tab or frame no longer exists
}


/***/ }),

/***/ "./sdk/api/core.js":
/*!*************************!*\
  !*** ./sdk/api/core.js ***!
  \*************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_630075__) => {

"use strict";
__nested_webpack_require_630075__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_630075__.d(__webpack_exports__, {
/* harmony export */   "filterEngine": () => (/* binding */ filterEngine)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_630075__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_630075__(/*! adblockpluscore */ "./node_modules/adblockpluscore/lib/index.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */





let filterEngine = new adblockpluscore__WEBPACK_IMPORTED_MODULE_1__.FilterEngine((function() {
  let features;

  if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest)
    features = adblockpluscore__WEBPACK_IMPORTED_MODULE_1__.Features.DNR;

  return {features};
})());


/***/ }),

/***/ "./sdk/api/debugging.js":
/*!******************************!*\
  !*** ./sdk/api/debugging.js ***!
  \******************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_631875__) => {

"use strict";
__nested_webpack_require_631875__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_631875__.d(__webpack_exports__, {
/* harmony export */   "debugOptions": () => (/* binding */ debugOptions),
/* harmony export */   "saveDebugOptions": () => (/* binding */ saveDebugOptions),
/* harmony export */   "loadDebugOptions": () => (/* binding */ loadDebugOptions),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_631875__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_filterStorage_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_631875__(/*! adblockpluscore/lib/filterStorage.js */ "./node_modules/adblockpluscore/lib/filterStorage.js");
/* harmony import */ var _io_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_631875__(/*! ./io.js */ "./sdk/api/io.js");
/* harmony import */ var _info_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_631875__(/*! ./info.js */ "./sdk/api/info.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_631875__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_631875__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/* harmony import */ var _subscriptions_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_631875__(/*! ./subscriptions.js */ "./sdk/api/subscriptions.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */











let defaultDebugOptions = {
  elemHide: false,
  cssProperties: [["background", "#e67370"], ["outline", "solid red"]],
  snippetsCssProperties: [
    ["background", "repeating-linear-gradient(to bottom, #e67370 0," +
     "#e67370 9px, white 9px, white 10px)"],
    ["outline", "solid red"]]
};

let debugOptions;

const STORAGE_KEY = "ewe:debugOptions";
let savingPromise = Promise.resolve(null);
let storage = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local;

async function saveDebugOptions() {
  await savingPromise;

  let obj = {};
  obj[STORAGE_KEY] = JSON.stringify(debugOptions);
  savingPromise = storage.set(obj);
  await savingPromise;
}

async function loadDebugOptions() {
  let obj = await storage.get(STORAGE_KEY);
  if (!obj || !obj[STORAGE_KEY]) {
    debugOptions = JSON.parse(JSON.stringify(defaultDebugOptions));
    return;
  }

  debugOptions = JSON.parse(obj[STORAGE_KEY]);
}

let initializationPromise;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * AddonInfo assigned during start.
   * @type {Object}
   * @property {string} name
   * @property {string} version
   */
  get addonInfo() {
    return {
      name: _info_js__WEBPACK_IMPORTED_MODULE_3__.addonName,
      version: _info_js__WEBPACK_IMPORTED_MODULE_3__.addonVersion,
      bundledSubscriptions: _info_js__WEBPACK_IMPORTED_MODULE_3__.addonBundledSubscriptions,
      bundledSubscriptionsPath: _info_js__WEBPACK_IMPORTED_MODULE_3__.addonBundledSubscriptionsPath,
      manifestVersion: _info_js__WEBPACK_IMPORTED_MODULE_3__.manifestVersion
    };
  },

  /**
   * Causes elements targeted by element hiding, element hiding emulation,
   * or snippets to be highlighted instead of hidden.
   * @param {boolean} enabled Enables or disables debug mode.
   * @returns {Promise} A promise that will resolve once the settings
   *    are saved.
   */
  async setElementHidingDebugMode(enabled) {
    await this.start();
    debugOptions.elemHide = enabled;
    await saveDebugOptions();
  },

  /**
   * Updates the element hiding debug style.
   * @param {Array} cssProperties The css properties for
   *                              the debug element.
   * @param {Array} snippetsCssProperties The css properties for
   *                                      the debug snippet element.
   * @returns {Promise} A promise that will resolve once the settings
   *    are saved.
   */
  async setElementHidingDebugStyle(cssProperties, snippetsCssProperties) {
    await this.start();

    if (cssProperties)
      debugOptions.cssProperties = cssProperties;

    if (snippetsCssProperties)
      debugOptions.snippetsCssProperties = snippetsCssProperties;

    await saveDebugOptions();
  },

  /**
   * Resets all of the debug options to their default state.
   * @returns {Promise}
   */
  async clearDebugOptions() {
    await this.start();
    debugOptions = JSON.parse(JSON.stringify(defaultDebugOptions));
    await saveDebugOptions();
  },

  /**
   * @ignore
   * @param {string} text
   */
  async isInFilterStorage(text) {
    let contents = [];
    await _io_js__WEBPACK_IMPORTED_MODULE_2__.IO.readFromFile(adblockpluscore_lib_filterStorage_js__WEBPACK_IMPORTED_MODULE_1__.FilterStorage.sourceFile,
                          line => contents.push(line));
    return contents.some(line => line.includes(text));
  },

  /**
   * @ignore
   * Used internally. Returns a list of warnings in the context of validating
   * that a user has provided the appropriate files to the extension.
   * @param {Array<Recommendation>} [addonInfo.bundledSubscriptions]
   *   A list of subscriptions provided by the integrator.
   * @param {string} [addonInfo.bundledSubscriptionsPath]
   *   A path to subscription files provided by the integrator.
   * @return {Array<String>}
   */
  validateSubscriptions: _subscriptions_js__WEBPACK_IMPORTED_MODULE_6__.validate,

  /**
   * @ignore
   * Used internally. Waits for any pending save actions to complete.
   * @return {Promise} The promise that is resolved once the filter storage
   *   module has saved all items.
   */
  async ensureEverythingHasSaved() {
    let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_4__.filterEngine;
    if (filterStorage) {
      // It would be better if filterStorage gave a promise to await for this.
      // https://gitlab.com/eyeo/adblockplus/abc/adblockpluscore/-/issues/464
      while (filterStorage._saving)
        await new Promise(r => setTimeout(r, 10));
    }

    await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_5__.awaitSavingComplete)();
  },

  /**
   * @ignore
   * Initialize debugging.
   */
  async start() {
    if (!initializationPromise)
      initializationPromise = loadDebugOptions();
    return initializationPromise;
  },

  /**
   * @ignore
   * Return the promise for saving the debugging options.
   * @return {Promise}
   */
  async ensureSaved() {
    await savingPromise;
  }
});


/***/ }),

/***/ "./sdk/api/diagnostics.js":
/*!********************************!*\
  !*** ./sdk/api/diagnostics.js ***!
  \********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_639248__) => {

"use strict";
__nested_webpack_require_639248__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_639248__.d(__webpack_exports__, {
/* harmony export */   "BlockableEventDispatcher": () => (/* binding */ BlockableEventDispatcher),
/* harmony export */   "getMatchedFilterEvents": () => (/* binding */ getMatchedFilterEvents),
/* harmony export */   "clearMatchedFilterEvents": () => (/* binding */ clearMatchedFilterEvents),
/* harmony export */   "logItem": () => (/* binding */ logItem),
/* harmony export */   "emitLogItem": () => (/* binding */ emitLogItem),
/* harmony export */   "logHiddenElements": () => (/* binding */ logHiddenElements),
/* harmony export */   "forceEnableTracing": () => (/* binding */ forceEnableTracing),
/* harmony export */   "setForceEnableTracing": () => (/* binding */ setForceEnableTracing),
/* harmony export */   "tracingEnabled": () => (/* binding */ tracingEnabled)
/* harmony export */ });
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_639248__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_639248__(/*! adblockpluscore/lib/url.js */ "./node_modules/adblockpluscore/lib/url.js");
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_639248__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_639248__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _filters_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_639248__(/*! ./filters.js */ "./sdk/api/filters.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_639248__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */








let listeners = [];
let filterTextToEvents = new Map();
let defaultOptions = {includeElementHiding: false,
                      includeUnmatched: false,
                      filterType: "blocking",
                      tabId: null};

/**
 * The BlockableEventDispatcher class allows users to listen to
 * filters and requests.
 * @hideconstructor
 */
class BlockableEventDispatcher {
  /**
  * @typedef {Object} BlockableEventOptions
  * @param {boolean} [includeElementHiding=false]
  *   Whether or not element hiding filters accounting for dynamic DOM changes
  *   should also be emitted. This event is emitted after the page has been
  *   fully loaded, and the element hiding filters have been applied. The
  *   expected delay between the filter being applied and the event being
  *   emitted is around two seconds.
  *   Note that this will enable element hiding tracing, which degrades
  *   performance and should only be used to enable ad-hoc diagnostics.
  * @param {boolean} [includeUnmatched=false] Whether or not unmatched requests
  *   should also be emitted. This event is generally emitted after a request is
  *   fully completed. Note that blockable item events may refer to either
  *   requests or documents. Unmatched events only refer to requests. This has
  *   the potentially confusing implication that there may be allowing document
  *   events (eg a $genericblock allowing filter being activated for a document)
  *   as well as an unmatched event for the request that actually loaded the
  *   HTML of the document.
  * @param {string} [filterType="blocking"]
  *   The type of filters to emit. Can be "blocking", "allowing", or "all".
  * @param {Number} [tabId=null]
  *   The tab to filter events for. Element hiding tracing will be limited to
  *   this tab (if `includeElementHiding` is set). If set to `null` events for
  *   all tabs will be considered, and are subject to element hiding tracing
  *   (if `includeElementHiding` is set) which will degrade performance.
  */

  /**
   * Attaches a listener function to an event. This listener will be called
   * when the Blockable event is emitted.
   * @param {function} listener The user defined function that will be called
   *                            once the specified event is emitted.
   * @param {BlockableEventOptions} options The filtering conditions to apply
   *                                        when the event is emitted.
   * @example
   * // Logs all blocked requests
   * EWE.reporting.onBlockableItem.addListener(console.log);
   * @example
   * // Log all blockable items of a specific tab for debugging purposes
   * EWE.reporting.onBlockableItem.addListener(
   *   console.log,
   *   {includeElementHiding: true,
   *    includeUnmatched: true,
   *    filterType: "all", tabId}
   * );
   */
  addListener(listener, options) {
    listeners.push({listener, options: {...defaultOptions, ...options}});
  }

  /**
   * Removes the added function. This means the listener will no
   * longer be called by the emitted event.
   * @param {function} listener The user defined function to be removed.
   * @param {Object} options The filtering conditions to apply when
   *                         the event is emitted.
   */
  removeListener(listener, options) {
    let {includeElementHiding, includeUnmatched,
         filterType, tabId} = {...defaultOptions, ...options};

    let index = listeners.findIndex(obj =>
      obj.listener == listener &&
      obj.options.includeElementHiding == includeElementHiding &&
      obj.options.includeUnmatched == includeUnmatched &&
      obj.options.filterType == filterType &&
      obj.options.tabId == tabId
    );

    if (index != -1)
      listeners.splice(index, 1);
  }
}

function getMatchedFilterEvents(filterText) {
  return filterTextToEvents.get(filterText);
}

function clearMatchedFilterEvents(tabId) {
  if (tabId) {
    for (let events of filterTextToEvents.values())
      events = events.filter(event => event.details.tabId != tabId);
  }
  else {
    filterTextToEvents.clear();
  }
}

function logFilterEvent(details, filter, matchInfo) {
  if (!filter)
    return;

  // DNR rule (filter text) can match multiple times,
  // so saving all the events to find the according one later.
  let events = filterTextToEvents.get(filter.text);
  if (!events)
    events = [];

  events.push({details, matchInfo});

  // Assuming the DNR matched rules order corresponds to
  // filter engine matched filters events order,
  // so let's keep it ready (sorted) for mapping.
  events.sort((a, b) => a.details.timeStamp - b.details.timeStamp);
  filterTextToEvents.set(filter.text, events);
}

function logItem(request, filter, matchInfo = {}) {
  // Even in MV3 we have to emit all the log events
  // that don't have an upcoming corresponding DNR rule match
  if (!_browser_js__WEBPACK_IMPORTED_MODULE_2__.default.declarativeNetRequest ||
      matchInfo.method == "elemhide" ||
      matchInfo.method == "snippet" ||
      matchInfo.method == "popup" ||
      matchInfo.method == "unmatched" ||
      matchInfo.allowingReason == "elemhide" ||
      matchInfo.allowingReason == "generichide" ||
      matchInfo.allowingReason == "extensionInitiated" ||
     (request.type == "main_frame" && matchInfo.method != "csp"))
    emitLogItem(request, filter, matchInfo);
  else
    logFilterEvent(request, filter, matchInfo);
}

function emitLogItem(request, filter, matchInfo = {}) {
  for (let {listener, options} of listeners) {
    let {includeElementHiding, includeUnmatched, filterType, tabId} = options;

    if (tabId != null && tabId != request.tabId)
      continue;

    if (filter) {
      if (!includeElementHiding && (filter.type == "elemhide" ||
                                    filter.type == "elemhideexception" ||
                                    filter.type == "elemhideemulation"))
        continue;

      if (filterType != "all" &&
          filterType == "allowing" != (filter.type == "allowing" ||
                                       filter.type == "elemhideexception"))
        continue;
    }

    if (!includeUnmatched && !filter)
      continue;

    listener({request, filter: filter && (0,_filters_js__WEBPACK_IMPORTED_MODULE_4__.convertFilter)(filter), matchInfo});
  }
}

function logHiddenElements(selectors, filters, sender) {
  let request = {
    tabId: sender.tab.id,
    frameId: sender.frameId,
    url: sender.url || _frame_state_js__WEBPACK_IMPORTED_MODULE_5__.BLANK_PAGE_URL
  };
  let {hostname} = (0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_1__.parseURL)(request.url);
  let matchInfo = {
    docDomain: hostname,
    method: "elemhide"
  };

  if (selectors.length > 0) {
    for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine.filterStorage.subscriptions()) {
      if (subscription.disabled)
        continue;

      for (let text of subscription.filterText()) {
        let filter = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_0__.Filter.fromText(text);

        if (filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_0__.ElemHideFilter &&
            selectors.includes(filter.selector) &&
            filter.isActiveOnDomain(hostname))
          logItem(request, filter, matchInfo);
      }
    }
  }

  for (let text of filters)
    logItem(request, adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_0__.Filter.fromText(text), matchInfo);
}

let forceEnableTracing = false;

// We might want to avoid racing between subscribing listener for element
// hiding events and "content-filter.js" `applyContentFilters()` that uses
// `tracingEnabled` here to detect whether we need to trace the selectors:
// if page loading is fast enough to happen before listener is subscribed,
// we don't track the selectors and don't emit elemhide log events,
// which makes the elemhiding log events-related tests flaky and
// failing time to time.

function setForceEnableTracing(enabled) {
  forceEnableTracing = enabled;
}

function tracingEnabled(tabId) {
  return forceEnableTracing ||
    listeners.some(({options}) =>
      options.includeElementHiding &&
      (options.tabId == null || options.tabId == tabId)
    );
}


/***/ }),

/***/ "./sdk/api/dnr-filters.js":
/*!********************************!*\
  !*** ./sdk/api/dnr-filters.js ***!
  \********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_650279__) => {

"use strict";
__nested_webpack_require_650279__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_650279__.d(__webpack_exports__, {
/* harmony export */   "getFilterTextByRuleId": () => (/* binding */ getFilterTextByRuleId),
/* harmony export */   "validateFilter": () => (/* binding */ validateFilter),
/* harmony export */   "removeDynamicFilters": () => (/* binding */ removeDynamicFilters),
/* harmony export */   "init": () => (/* binding */ init),
/* harmony export */   "addFilters": () => (/* binding */ addFilters),
/* harmony export */   "setMetadataForFilter": () => (/* binding */ setMetadataForFilter),
/* harmony export */   "getMetadataForFilter": () => (/* binding */ getMetadataForFilter),
/* harmony export */   "removeOrDisableFilters": () => (/* binding */ removeOrDisableFilters),
/* harmony export */   "enableFilters": () => (/* binding */ enableFilters),
/* harmony export */   "getDynamicFilters": () => (/* binding */ getDynamicFilters),
/* harmony export */   "getDynamicUserFilters": () => (/* binding */ getDynamicUserFilters),
/* harmony export */   "migrateCustomFilters": () => (/* binding */ migrateCustomFilters)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_650279__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_650279__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_650279__(/*! adblockpluscore/lib/subscriptionClasses.js */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
/* harmony import */ var adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_650279__(/*! adblockpluscore/lib/url.js */ "./node_modules/adblockpluscore/lib/url.js");
/* harmony import */ var adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_650279__(/*! adblockpluscore/lib/filterNotifier.js */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_650279__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var adblockpluscore_lib_dnr_index_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_650279__(/*! adblockpluscore/lib/dnr/index.js */ "./node_modules/adblockpluscore/lib/dnr/index.js");
/* harmony import */ var _errors_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_650279__(/*! ../errors.js */ "./sdk/errors.js");
/* harmony import */ var _types_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_650279__(/*! ./types.js */ "./sdk/api/types.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_9__ = __nested_webpack_require_650279__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */














let highestRuleId = 1;
let dynamicFilters = new Map();
let ruleIdToFilterText = new Map();
let initializationPromise;

function getFilterTextByRuleId(ruleId) {
  return ruleIdToFilterText.get(ruleId);
}

let getRulesFromFilter = () => {};
if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
  getRulesFromFilter = (0,adblockpluscore_lib_dnr_index_js__WEBPACK_IMPORTED_MODULE_6__.createConverter)({
    isRegexSupported: webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.isRegexSupported
  });
}

/**
 * Update a dynamic subscription.
 *
 * @param {Subscription} subscription The subscription updated.
 * @param {?object} updates The list of added and removed filter text. If
 *   falsey then nothing happens.
 *
 * @private
 */
async function dynamicSubscriptionUpdate(subscription, updates) {
  if (!webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest || !updates)
    return;

  // For now we only want to handle subscription that are in the
  // recommendations.
  if (!subscription.type)
    return;

  let {added, removed} = updates;

  let filters = await processFilterTexts(added, subscription.id);
  // Adding subscription.id into existing filter
  for (let text of filters.existOnOtherSubscription) {
    let filter = dynamicFilters.get(text);
    filter.subscriptionIds.push(subscription.id);
  }

  // Removing subscription.id from existing filter
  removed = removed.filter(text => {
    let detail = dynamicFilters.get(text);
    if (detail && detail.subscriptionIds) {
      let index = detail.subscriptionIds.indexOf(subscription.id);
      if (index !== -1)
        detail.subscriptionIds.splice(index, 1);
      return detail.subscriptionIds.length == 0;
    }
    return false;
  });

  let removeRuleIds = removed.flatMap(text => {
    let detail = dynamicFilters.get(text);
    return detail ? detail.ruleIds : [];
  });

  // Empty array cause exceptions. Make it `undefined`.
  if (removeRuleIds.length == 0)
    removeRuleIds = void 0;

  await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.updateDynamicRules(
    {addRules: filters.add, removeRuleIds}
  );

  removed.forEach(text => dynamicFilters.delete(text));
  removed.forEach(ruleId => ruleIdToFilterText.delete(ruleId));

  filters.details.forEach(details => {
    let {useFilterEngine, filter, ruleIds, enabled} = details;

    setHighestRuleId(ruleIds);
    dynamicFilters.set(filter.text,
                       {ruleIds, useFilterEngine, enabled, metadata: {},
                        subscriptionIds: [subscription.id]});
    for (let ruleId of ruleIds)
      ruleIdToFilterText.set(ruleId, filter.text);
  });

  storeDynamicFilters();
}

function validateFilter(filter) {
  if (filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.InvalidFilter)
    return new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError("invalid_filter", filter.reason, filter.option);

  if ((0,adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.isActiveFilter)(filter) && filter.domains) {
    for (let domain of filter.domains.keys()) {
      if (domain && !(0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_3__.isValidHostname)(domain))
        return new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError("invalid_domain", domain);
    }
  }

  return null;
}

async function removeDynamicFilters() {
  if (!webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest)
    return;

  dynamicFilters = new Map();
  _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.dynamic_filters = [];
  _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.rule_id_to_filter_text = [];

  let rules = await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.getDynamicRules();
  if (rules.length == 0)
    return;

  await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.updateDynamicRules({
    removeRuleIds: rules.map(r => r.id)
  });

  return rules;
}

function setHighestRuleId(ruleIds) {
  if (!ruleIds)
    return;

  for (let id of ruleIds) {
    if (highestRuleId < id)
      highestRuleId = id;
  }
}

function storeDynamicFilters() {
  let storageArray = [];
  storageArray.push(...dynamicFilters);
  _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.dynamic_filters = storageArray;

  let ruleIdToFilterTextArray = [];
  ruleIdToFilterTextArray.push(...ruleIdToFilterText);
  _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.rule_id_to_filter_text = ruleIdToFilterTextArray;
}

function init() {
  if (!initializationPromise) {
    initializationPromise = (async() => {
      if (!webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest)
        return;

      let dynamicFilterArray = _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.dynamic_filters;
      if (Array.isArray(dynamicFilterArray) &&
          dynamicFilterArray.length > 0)
        dynamicFilters = new Map(dynamicFilterArray);
      else
        // DNR rules persist after the extension is uninstalled. The same cannot
        // be said for storage. To be safe, if we have no record of dynamic
        // filters let's clear any DNR rules too.
        await removeDynamicFilters();

      let ruleIdToFilterTextArray = _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.rule_id_to_filter_text;
      if (Array.isArray(ruleIdToFilterTextArray) &&
          ruleIdToFilterTextArray.length > 0)
        ruleIdToFilterText = new Map(ruleIdToFilterTextArray);

      for (let {ruleIds} of dynamicFilters.values())
        setHighestRuleId(ruleIds);

      adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("subscription.updated", dynamicSubscriptionUpdate);
    })();
  }

  return initializationPromise;
}

async function getRules(filter) {
  let ruleIds = [];
  let filterRules = [];

  // "sitekey" option is not supported in DNR
  if (filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.URLFilter && !filter.sitekeys) {
    let result = await getRulesFromFilter(filter.text);
    if (result.name == "Error") {
      let {option} = result.detail;
      throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(result.message, result.detail.text, option);
    }

    for (let rule of result) {
      let id = ++highestRuleId;
      rule.id = id;
      ruleIds.push(id);
      filterRules.push(rule);
    }
  }

  return {filterRules, ruleIds};
}

async function processFilterTexts(texts, subscriptionId = null) {
  let details = [];
  let add = [];
  let exist = [];
  let existOnOtherSubscription = [];
  let seenFilterTexts = new Set();

  texts = texts.map(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize);
  for (let text of texts) {
    let dynamicFilterToAnalyze = dynamicFilters.get(text);
    if (dynamicFilterToAnalyze) {
      let subscriptionIds = dynamicFilterToAnalyze.subscriptionIds || [null];
      if (subscriptionIds.includes(subscriptionId))
        exist.push(text);
      else
        existOnOtherSubscription.push(text);
      continue;
    }

    if (seenFilterTexts.has(text))
      continue;

    let filter = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text);
    let error = validateFilter(filter);
    if (error)
      throw error;

    if (!_core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.filterState.isEnabled(text)) {
      details.push({filter, ruleIds: [], enabled: false});
    }
    else {
      let {filterRules, ruleIds} = await getRules(filter);
      add.push(...filterRules);
      details.push({filter, ruleIds, enabled: true});
    }

    seenFilterTexts.add(text);
  }

  return {add, exist, existOnOtherSubscription, details};
}

async function dynamicRulesAvailable() {
  let {declarativeNetRequest} = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__;
  if (!declarativeNetRequest)
    return Infinity;

  const {MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES} = declarativeNetRequest;
  let used = (await declarativeNetRequest.getDynamicRules()).length +
               (await declarativeNetRequest.getSessionRules()).length;
  return MAX_NUMBER_OF_DYNAMIC_AND_SESSION_RULES - used;
}

async function addFilters(texts, metadata) {
  await init();
  let filters = await processFilterTexts(texts);
  if (filters.exist.length > 0)
    throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(_errors_js__WEBPACK_IMPORTED_MODULE_7__.ERROR_DUPLICATE_FILTERS);

  let {length} = filters.add;
  if (length > 0) {
    // always false when !browser.declarativeNetRequest
    if (length >= await dynamicRulesAvailable())
      throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(_errors_js__WEBPACK_IMPORTED_MODULE_7__.ERROR_TOO_MANY_FILTERS);

    // so that this would throw the right error in case
    // browser.declarativeNetRequest doesn't exist or if
    // the API returned a different error instead
    await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.updateDynamicRules({
      addRules: filters.add
    });
  }

  for (let text of filters.existOnOtherSubscription) {
    let filter = dynamicFilters.get(text);
    if (!filter.subscriptionIds)
      filter.subscriptionIds = [];
    filter.subscriptionIds.push(null);
  }

  for (let filterDetails of filters.details) {
    let {filter, ruleIds, enabled} = filterDetails;
    _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.addFilter(filter);

    setHighestRuleId(ruleIds);
    dynamicFilters.set(filter.text, {ruleIds, enabled, metadata,
                                     subscriptionIds: [null]});
    for (let ruleId of ruleIds)
      ruleIdToFilterText.set(ruleId, filter.text);
  }

  storeDynamicFilters();
}

function setMetadataForFilter(text, metadata) {
  let details = dynamicFilters.get(text);
  if (!details)
    throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(_errors_js__WEBPACK_IMPORTED_MODULE_7__.ERROR_FILTER_NOT_FOUND);

  details.metadata = metadata;

  storeDynamicFilters();
}

function getMetadataForFilter(text) {
  let details = dynamicFilters.get(text);
  if (!details)
    return null;

  let metadata = details.metadata;
  return (typeof metadata != "undefined") ? metadata : null;
}

async function removeOrDisableFilters(texts, remove = true) {
  await init();

  let filtersToRemove = texts.map(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize);
  let ruleIdsToRemove = [];
  for (let text of filtersToRemove) {
    if (!dynamicFilters.has(text))
      continue;

    for (let ruleId of dynamicFilters.get(text).ruleIds)
      ruleIdsToRemove.push(ruleId);

    let details = dynamicFilters.get(text);

    if (remove) {
      // Removing existing filter
      if (details) {
        if (!details.subscriptionIds)
          details.subscriptionIds = [];

        let index = details.subscriptionIds.indexOf(null);
        if (index !== -1)
          details.subscriptionIds.splice(index, 1);
      }
      // Removing filter only if subscriptionIds array is empty
      if (details.subscriptionIds && details.subscriptionIds.length >= 0) {
        _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.removeFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text));

        dynamicFilters.delete(text);
        for (let ruleId of ruleIdsToRemove)
          ruleIdToFilterText.delete(ruleId);
      }
    }
    else {
      _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.filterState.setEnabled(text, false);

      details.enabled = false;
      details.ruleIds = [];
      dynamicFilters.set(text, details);
      ruleIdToFilterText.set(text, details);
    }
  }

  if (ruleIdsToRemove.length > 0) {
    await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.updateDynamicRules({
      removeRuleIds: ruleIdsToRemove
    });
  }

  storeDynamicFilters();
}

async function enableFilters(texts) {
  await init();

  let rules = [];

  for (let text of texts) {
    let normalized = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize(text);
    let details = dynamicFilters.get(normalized);

    if (!details || details.enabled)
      continue;

    let filter = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(normalized);
    _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.filterState.setEnabled(filter.text, true);

    let {filterRules, ruleIds} = await getRules(filter);
    rules.push(...filterRules);

    setHighestRuleId(ruleIds);
    dynamicFilters.set(filter.text, {ruleIds, enabled: true});
  }

  if (rules.length == 0)
    return;

  await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest.updateDynamicRules({
    addRules: rules
  });

  storeDynamicFilters();
}

async function getDynamicFilters() {
  await init();
  return dynamicFilters;
}

async function getDynamicUserFilters() {
  await init();
  let dynamicUserFilters = new Map();

  for (let [filterText, details] of dynamicFilters.entries()) {
    if (!details.subscriptionIds || details.subscriptionIds.includes(null))
      dynamicUserFilters.set(filterText, details);
  }
  return dynamicUserFilters;
}

async function migrateCustomFilters() {
  let filters = [];

  for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.subscriptions()) {
    if (!(subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_2__.SpecialSubscription))
      continue;

    for (let text of subscription.filterText())
      filters.push({text, metadata: subscription.metadata});
  }

  for (let filter of filters) {
    try {
      _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.filterStorage.removeFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(filter.text));
      await addFilters([filter.text], filter.metadata);
    }
    catch (e) {
      let errors = _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.migration_filter_errors;
      errors.push({error: e.message, filter});
      _prefs_js__WEBPACK_IMPORTED_MODULE_9__.Prefs.migration_filter_errors = errors;
    }
  }
}


/***/ }),

/***/ "./sdk/api/filters.js":
/*!****************************!*\
  !*** ./sdk/api/filters.js ***!
  \****************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_668380__) => {

"use strict";
__nested_webpack_require_668380__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_668380__.d(__webpack_exports__, {
/* harmony export */   "convertFilter": () => (/* binding */ convertFilter),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_668380__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_668380__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_668380__(/*! adblockpluscore/lib/subscriptionClasses.js */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
/* harmony import */ var adblockpluscore_lib_matcher_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_668380__(/*! adblockpluscore/lib/matcher.js */ "./node_modules/adblockpluscore/lib/matcher.js");
/* harmony import */ var adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_668380__(/*! adblockpluscore/lib/filterNotifier.js */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_668380__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var _initializer_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_668380__(/*! ./initializer.js */ "./sdk/api/initializer.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_668380__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _types_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_668380__(/*! ./types.js */ "./sdk/api/types.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_9__ = __nested_webpack_require_668380__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/* harmony import */ var _dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__ = __nested_webpack_require_668380__(/*! ./dnr-filters.js */ "./sdk/api/dnr-filters.js");
/* harmony import */ var _errors_js__WEBPACK_IMPORTED_MODULE_11__ = __nested_webpack_require_668380__(/*! ../errors.js */ "./sdk/errors.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_12__ = __nested_webpack_require_668380__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */

















function convertFilter(filter) {
  return {
    text: filter.text,
    enabled: typeof filter.disabled == "undefined" ? null : !filter.disabled,
    slow: filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.URLFilter && (0,adblockpluscore_lib_matcher_js__WEBPACK_IMPORTED_MODULE_3__.isSlowFilter)(filter),
    type: filter.type,
    thirdParty: filter.thirdParty || null,
    selector: filter.selector || null,
    csp: filter.csp || null
  };
}

function makeFilterListener(dispatch) {
  return filter => dispatch(convertFilter(filter));
}

function makeSubListener(dispatch) {
  return subscription => {
    if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_2__.SpecialSubscription) {
      for (let text of subscription.filterText())
        dispatch(convertFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text)));
    }
  };
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * Represents a single filter rule and its state.
   * @typedef {Object} Filter
   * @property {string} text A {@link https://help.eyeo.com/adblockplus/how-to-write-filters|filter}
   *                         rule that specifies what content
   *                         to block or to allow. Used to identify a filter.
   * @property {boolean|null} enabled Indicates whether this filter would
   *                                  be applied. Filters are enabled by
   *                                  default. For comment filters returned
   *                                  value is null.
   * @property {boolean} slow Indicates that this filter is not subject to an
   *                          internal optimization. Filters that are
   *                          considered slow should be avoided. Only URLFilters
   *                          can be slow.
   * @property {string} type The filter {@link https://gitlab.com/eyeo/adblockplus/abc/adblockpluscore/-/jobs/artifacts/0.6.0/file/build/docs/module-filterClasses.Filter.html?job=docs#type|type}
   * @property {boolean|null} thirdParty True when the filter applies to
   *                          third-party, false to first-party, null otherwise.
   * @property {string|null} selector CSS selector for the HTML elements that
   *                                  will be hidden.
   * @property {string|null} csp Content Security Policy to be injected.
   */

  /**
   * Adds multiple filters from texts.
   * @param {[string]} texts The filter rules to be added.
   * @param {?Object} metadata Extra data to associate with a filter.
   * @return {Promise}
   * @throws {FilterError|Error} The first filter to add that either failed
   *   validation (FilterError) or that is not supported by the DNR (Error).
   *   An error will be thrown for duplicated filters.
   */
  async add(texts, metadata) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
      await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.addFilters)(texts, metadata);
      return;
    }

    let filters = [];
    for (let text of texts) {
      let normalized = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize(text);
      let filter = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(normalized);
      let error = (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.validateFilter)(filter);

      if (error)
        throw error;

      filters.push(filter);
    }

    let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine;

    if (!metadata) {
      if (filterStorage.filtersExist(filters).length > 0)
        throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(_errors_js__WEBPACK_IMPORTED_MODULE_11__.ERROR_DUPLICATE_FILTERS);

      for (let filter of filters)
        await filterStorage.addFilter(filter);
    }
    else {
      try {
        await filterStorage.addFiltersWithMetadata(filters, metadata);
      }
      catch (e) {
        throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(e.message);
      }
    }
  },

  /**
   * Set an extra data associated with an added filter.
   * @param {string} text filter text to set metadata for.
   * @param {Object} metadata Extra data to associate with a filter.
   * @returns {Promise<void>} Nothing is done for not added filter.
   * @throws {FilterError} An error will be thrown for not added filter.
   */
  async setMetadata(text, metadata) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
      (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.setMetadataForFilter)(text, metadata);
      return;
    }

    let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine;

    try {
      await filterStorage.setMetadataForFilter(text, metadata);
    }
    catch (e) {
      if (e.message == _errors_js__WEBPACK_IMPORTED_MODULE_11__.ERROR_FILTER_NOT_FOUND) {
        // filter might be added without a metadata first,
        // so we're trying to make it working in a non-surprising way:
        // by removing the existing filter and readding it with a metadata.
        let filter = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize(text));
        if (filterStorage.filtersExist([filter]).length > 0) {
          await filterStorage.removeFilter(filter);
          await this.add([text], metadata);
          return;
        }
      }
      throw new _types_js__WEBPACK_IMPORTED_MODULE_8__.FilterError(e.message);
    }
  },

  /**
   * Returns an extra data associated with a filter.
   * @param {string} text The filter text to get metadata for.
   * @return {Promise<?Object>}
   */
  async getMetadata(text) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest)
      return (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.getMetadataForFilter)(text);

    return await _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.filterStorage.getMetadataForFilter(text);
  },

  /**
   * Returns an array of user filter objects.
   * @return {Promise<Array<Filter>>}
   */
  async getUserFilters() {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
    let result = [];

    for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.filterStorage.subscriptions()) {
      if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_2__.SpecialSubscription) {
        for (let text of subscription.filterText())
          result.push(convertFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text)));
      }
    }

    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
      for (let [text, details] of (await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.getDynamicUserFilters)()).entries()) {
        if (!result.find(filter => filter.text == text)) {
          let filter = convertFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text));
          filter.enabled = filter.type == "comment" ? null : details.enabled;

          result.push(filter);
        }
      }
    }

    return result;
  },

  /**
   * Returns the allowing filters that will be effective
   * when the given document will be reloaded.
   * @param {number} tabId The id of the tab to lookup.
   * @param {Object} [options]
   * @param {number} [options.frameId=0] The id of the frame to lookup.
   * @param {Array<string>} [options.types=["document"]] The types of filters
   *   to consider. These can be any of "document", "elemhide", "genericblock",
   *   and "generichide".
   * @return {Promise<Array<string>>}
   */
  async getAllowingFilters(tabId, options = {}) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();

    let {frameId, types} = {frameId: 0, types: ["document"], ...options};
    let filters = new Set();
    let mask = types.reduce((a, b) => a | adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_5__.contentTypes[b.toUpperCase()], 0);

    for (let frame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_9__.getFrameInfo)(tabId, frameId); frame;
         frame = frame.parent) {
      let parentHostname = frame.parent && frame.parent.hostname;
      let docDomain = parentHostname || frame.hostname;
      let matches = _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.defaultMatcher.search(
        frame.url, mask, docDomain, frame.sitekey, false, "allowing");

      for (let filter of matches.allowing)
        filters.add(filter.text);
    }

    return Array.from(filters);
  },

  /**
   * Returns whether a particular resource is allowlisted.
   * @param {string} url The resource's url.
   * @param {string} type The resource's content type. Can be one of
   *   "background", "csp", "document", "dtd", "elemhide", "font",
   *   "genericblock", "generichide", "header", "image", "media", "object",
   *   "other", "ping", "popup", "script", "stylesheet", "subdocument",
   *   "webrtc", "websocket", "xbl", "xmlhttprequest".
   * @param {number} tabId The id of resource's tab.
   * @param {number} frameId=0 The id of the resource's frame.
   * @return {Promise<bool>}
   */
  async isResourceAllowlisted(url, type, tabId, frameId = 0) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();

    let mask = adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_5__.contentTypes[type.toUpperCase()];
    let frame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_9__.getFrameInfo)(tabId, frameId) || {};
    let matcher = _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.defaultMatcher;

    if (matcher.isAllowlisted(url, mask, frame.hostname, frame.sitekey))
      return true;

    for (; frame; frame = frame.parent) {
      if (!frame.url)
        break;

      let parentHostname = frame.parent && frame.parent.hostname;
      if (matcher.isAllowlisted(frame.url, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_5__.contentTypes.DOCUMENT,
                                parentHostname, frame.sitekey))
        return true;
    }

    return false;
  },

  /**
   * Enables multiple filters. The filters effects will again be applied.
   * @param {[string]} texts The filter rules to be enabled.
   * @return {Promise}
   */
  async enable(texts) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();

    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
      await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.enableFilters)(texts);
      return;
    }

    for (let text of texts) {
      let normalized = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize(text);
      _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.filterStorage.filterState.setEnabled(normalized, true);
    }
  },

  /**
   * Disables multiple filters. The filters will no longer have any effect
   * but will be returned by `filters.getUserFilters()`.
   * @param {[string]} texts The filter rules to be disabled.
   * @return {Promise}
   */
  async disable(texts) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();

    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
      await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.removeOrDisableFilters)(texts, false);
      return;
    }

    for (let text of texts) {
      let normalized = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize(text);
      _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.filterStorage.filterState.setEnabled(normalized, false);
    }
  },

  /**
   * Removes multiple filters. The filters will no longer have any effect
   * and won't be returned by `filters.getUserFilters()`.
   * @param {[string]} texts The filter rules to be removed.
   * @return {Promise}
   */
  async remove(texts) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();

    if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
      await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.removeOrDisableFilters)(texts, true);
      return;
    }

    for (let text of texts) {
      let normalized = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.normalize(text);
      _core_js__WEBPACK_IMPORTED_MODULE_7__.filterEngine.filterStorage.removeFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(normalized));
    }
  },

  /**
   * Validates a list of filters.
   * @param {string} text Filter to be validated
   * @return {null|FilterError}
   */
  validate(text) {
    return (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_10__.validateFilter)(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text));
  },

  /**
   * Emitted when a new filter is added.
   * @event
   * @type {EventDispatcher<Filter>}
   */
  onAdded: new _types_js__WEBPACK_IMPORTED_MODULE_8__.EventDispatcher(dispatch => {
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("filter.added", makeFilterListener(dispatch));
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("subscription.added", makeSubListener(dispatch));
  }),

  /**
   * Emitted when a filter is either enabled or disabled.
   * The property name "enabled" is provided.
   * @event
   * @type {EventDispatcher<Filter, string>}
   */
  onChanged: new _types_js__WEBPACK_IMPORTED_MODULE_8__.EventDispatcher(dispatch => {
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("filterState.enabled", (text, enabled) => {
      dispatch({...convertFilter(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.Filter.fromText(text)), enabled}, "enabled");
    });
  }),

  /**
   * Emitted when a filter is removed.
   * @event
   * @type {EventDispatcher<Filter>}
   */
  onRemoved: new _types_js__WEBPACK_IMPORTED_MODULE_8__.EventDispatcher(dispatch => {
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("filter.removed", makeFilterListener(dispatch));
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("subscription.removed", makeSubListener(dispatch));
  }),

  /**
   * Returns an array of MV2 to MV3 migration errors and the related filters.
   * @return {Promise<array<Filter, string>>} The migration errors.
   */
  async getMigrationErrors() {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
    return _prefs_js__WEBPACK_IMPORTED_MODULE_12__.Prefs.migration_filter_errors;
  },

  /**
   * Clears the migration errors.
   * @return {Promise}
   */
  async clearMigrationErrors() {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
    _prefs_js__WEBPACK_IMPORTED_MODULE_12__.Prefs.migration_filter_errors = [];
  }
});


/***/ }),

/***/ "./sdk/api/frame-state.js":
/*!********************************!*\
  !*** ./sdk/api/frame-state.js ***!
  \********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_687145__) => {

"use strict";
__nested_webpack_require_687145__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_687145__.d(__webpack_exports__, {
/* harmony export */   "BLANK_PAGE_URL": () => (/* binding */ BLANK_PAGE_URL),
/* harmony export */   "TOP_LEVEL_FRAME_ID": () => (/* binding */ TOP_LEVEL_FRAME_ID),
/* harmony export */   "isTopLevelFrameId": () => (/* binding */ isTopLevelFrameId),
/* harmony export */   "isValidFrameId": () => (/* binding */ isValidFrameId),
/* harmony export */   "isValidChildFrameId": () => (/* binding */ isValidChildFrameId),
/* harmony export */   "addOnFrameInfoListener": () => (/* binding */ addOnFrameInfoListener),
/* harmony export */   "addOnTabRemovedListener": () => (/* binding */ addOnTabRemovedListener),
/* harmony export */   "getFrameInfo": () => (/* binding */ getFrameInfo),
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_687145__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_687145__(/*! adblockpluscore/lib/url.js */ "./node_modules/adblockpluscore/lib/url.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_687145__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_687145__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_687145__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _sitekey_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_687145__(/*! ./sitekey.js */ "./sdk/api/sitekey.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */










/**
 * The URL that browsers use to represent an empty page, about:blank.
 */
const BLANK_PAGE_URL = "about:blank";

/**
 * The frameId of the top level frame on each tab.
 */
const TOP_LEVEL_FRAME_ID = 0;

/**
 * Checks if a frameId corresponds to the top level frame on a tab.
 * @param {number} frameId
 * @return {boolean}
 */
function isTopLevelFrameId(frameId) {
  return frameId == TOP_LEVEL_FRAME_ID;
}

/**
 * Checks if a frameId corresponds to a frame on a tab.
 * @param {number} frameId
 * @return {boolean}
 */
function isValidFrameId(frameId) {
  return frameId >= TOP_LEVEL_FRAME_ID;
}

/**
 * Checks if a frameId corresponds to an iframe.
 * @param {number} frameId
 * @return {boolean}
 */
function isValidChildFrameId(frameId) {
  return frameId > TOP_LEVEL_FRAME_ID;
}

/**
 * All known currently active frames, that can be looked up by
 * `tabId`, and then by `frameId` (`[tabId, [frameId, FrameInfo]]`).
 *
 * Maintaining this state is the central reason for the code in this
 * file. When we start up EWE, we scan all existing tabs for their
 * frames. After that, we hook into various browser events to try to
 * keep it up to date as things change.
 *
 * @type {Map<number, Map<number, FrameInfo>>}
 */
let state = new Map();
let startupPromise;

let onFrameInfoListeners = [];
let onTabRemovedListeners = [];

function addOnFrameInfoListener(listener) {
  onFrameInfoListeners.push(listener);
}

function addOnTabRemovedListener(listener) {
  onTabRemovedListeners.push(listener);
}

function notifyOnFrameInfo(tabId, frameId) {
  for (let listener of onFrameInfoListeners)
    listener(tabId, frameId);
}

function notifyOnTabRemoved(tabId) {
  for (let listener of onTabRemovedListeners)
    listener(tabId);
}

/**
 * Manages tracking state that is tied to a single specific frame.
 *
 * A simple webpage will have a single frame in a tab. However, when
 * we look at sites with advertising and embedded trackers, they often
 * have many <iframe> elements. Each iframe may have slightly
 * different state, but generally a frame will inherit settings from
 * the frame that it's on (its parent frame).
 *
 * This state is mostly used in applying frame-level allowing filters
 * (eg `$document` filters), but is also used to hold parameters like
 * what hostname to use when checking if filters match a request, and
 * whether or not a sitekey is involved. This needs to be done
 * statefully because we inherit some state from parent frames.
 *
 * We sometimes need access to this data synchronously (for example to
 * do request filtering), but the functions to fetch this data from
 * the browser on demand are asynchronous. The events where we need to
 * make decisions based on the frame usually have some of the frame's
 * state, like the URL of the frame, but don't have the sitekey and
 * don't have all of the information about the parents of the frame.
 *
 * @property {number} tabId The id of the tab.
 * @property {string} url The url of the frame.
 * @property {string} hostname The hostname part of the frame's
 *   URL. If the URL isn't a normal HTTP URL (for example if it's
 *   about:blank) then this will be the parent frame's hostname. If
 *   that also doesn't have a normal HTTP hostname, then this will
 *   default to an empty string.
 * @property {?string} sitekey The sitekey associated with a frame, if
 *   there is one. These sitekeys are read from the
 *   `onHeadersReceived` event. This is inherited from the parent
 *   frame if this frame doesn't have a sitekey of its own.
 * @property {boolean} headersReceived True if we've received an
 *   `onHeadersReceived` event for this frame and have checked it for
 *   sitekeys. If this is false, it could mean that we don't have
 *   enough information yet to make blocking decisions, because a
 *   sitekey might still arrive with the headers.
 * @property {?FrameInfo} parent The frame that this from is on. Null
 *   if this is the top-level frame on a tab.
 * @property {number} allowlisted Bitfield where each set bit is the
 *   content type of an allowlisting filter applied to the frame. This
 *   includes filters that turn of ad filtering entirely, like
 *   `$document` filters, but also includes filters that modify how we
 *   look up request filters like `$genericblock`.
 * @property {?Filter} allowingDocumentFilter The `$document` filter
 *   that is being applied to this frame, if any. This is useful for
 *   logging, for example if a request is allowed because of this
 *   filter. If you just need to check if there is a `$document` filter
 *   applied to the frame or not, you can also check
 *   `frame.allowlisted`.
 *
 * @param {number} tabId The tabId of the tab that the this frame is on.
 * @param {number} frameId The frameId of this frame.
 * @param {?FrameInfo} parent The frame that this from is on. Null
 *   if this is the top-level frame on a tab.
 * @param {string} url The url of the frame.
 * @hideconstructor
 */
class FrameInfo {
  constructor(tabId, frameId, parent, url) {
    let {
      allowlisted: parentAllowlisted,
      sitekey: parentSitekey,
      allowingDocumentFilter: parentAllowingDocumentFilter
    } = parent || {};

    let urlInfo = (0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_1__.parseURL)(url);

    this.tabId = tabId;
    this.url = url;
    this.hostname = urlInfo.hostname || (parent ? parent.hostname : "");
    let sitekey = (0,_sitekey_js__WEBPACK_IMPORTED_MODULE_5__.getSitekey)(tabId, frameId, url);
    this.sitekey = sitekey || parentSitekey;
    this.headersReceived = (!!sitekey) || sitekey === null;
    this.parent = parent;

    // allowlisted and allowingDocumentFilter start with their parent
    // value, but may have extra allowing filters added when we call
    // findAllowlistingFilters
    this.allowlisted = parentAllowlisted || 0;
    this.allowingDocumentFilter = parentAllowingDocumentFilter;

    findAllowlistingFilters(this, tabId, frameId);
  }
}

/**
 * Get a text description of the allowing filter added.
 * @param {number} typeMask Bitset to filter types you want to name.
 * @param {Filter} filter The filter with the allowing reason you want
 *   to name.
 * @return {string} Content type name of the allowing filter just
 *   added.
 */
function getAllowingReason(typeMask, filter) {
  for (let type in adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes) {
    if (typeMask & filter.contentType & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes[type])
      return type.toLowerCase();
  }
}

/**
 * Checks if the matcher has any allowing filters that should be
 * applied to this frame, and updates `frame.allowlisted` and
 * `frame.allowingDocumentFilter` accordingly.
 *
 * This can only ever add extra allowing filters. It's also safe to
 * call multiple times on the same frame. This would normally be
 * called on a new frame to find its allowing filters, but should also
 * be called whenever a frame is updated in such a way that there
 * could be new allowing filters, for example when a sitekey is added
 * to an existing frame.
 *
 * @param {FrameInfo} frame The frame that will be checked for new
 *   filters, and will be updated.
 * @param {number} tabId The tabId of the tab the frame is on. Used for
 *   logging.
 * @param {number} frameId The frameId of the frame. Used for logging.
 */
function findAllowlistingFilters(frame, tabId, frameId) {
  let details = {tabId, frameId, url: frame.url};
  // The docDomain for a frame is the hostname of the parent frame
  // (the loader). For top-level frames we use the current URL's hostname.
  let parentHostname = frame.parent && frame.parent.hostname;
  let matchInfo = {docDomain: parentHostname || frame.hostname,
                   method: "allowing"};

  // This loop will keep trying to find new types of allowing filters
  // for the frame until the matcher doesn't return any more.
  while (true) {
    let typeMask = ~frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.ALLOWING_TYPES;
    let filter = _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine.defaultMatcher.match(
      frame.url, typeMask, matchInfo.docDomain, frame.sitekey
    );

    if (!filter)
      break;

    frame.allowlisted |= filter.contentType & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.ALLOWING_TYPES;
    // We need to hold onto document allowing filters because we might
    // need it for logging blockable requests later.
    if (filter.contentType & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT)
      frame.allowingDocumentFilter = filter;

    let allowingReason = getAllowingReason(typeMask, filter);
    (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_4__.logItem)(details, filter, {...matchInfo, allowingReason});
  }
}

/**
 * Builds the frame state from scratch using the tabs API.
 *
 * This is called on startup, and in MV3 whenever the service worker
 * starts up. The only shortcoming is that this can't find sitekeys
 * for existing frames, since those are read from headers.
 * @async
 * @return {Promise} Resolves when all frames have been scanned.
 */
async function discoverExistingFrames() {
  let tabs = await _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.tabs.query({});
  await Promise.all(tabs.map(({id: tabId}) =>
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.webNavigation.getAllFrames({tabId}).then(rawFrames => {
      if (!rawFrames)
        return;

      // Sort the frames so that we'll add parent frames before the
      // child frames.
      rawFrames.sort((a, b) => a.frameId - b.frameId);

      let frames = new Map();
      state.set(tabId, frames);

      for (let {frameId, parentFrameId, url} of rawFrames) {
        let parent = isValidFrameId(parentFrameId) ?
            frames.get(parentFrameId) :
            null;

        // Chrome unfortunately has a bug where getAllFrames doesn't
        // always return all parent frames
        // (https://bugs.chromium.org/p/chromium/issues/detail?id=725917).
        // Not much we can do about it, but if we can't see the
        // required parent frame we can fall back to the root frame.
        if (isValidChildFrameId(parentFrameId) && !parent)
          parent = frames.get(TOP_LEVEL_FRAME_ID);

        // Yandex gives undefined or an empty string here sometimes,
        // for example when browsing to pages that Yandex treats
        // specially like their own website.
        if (!url)
          url = BLANK_PAGE_URL;

        frames.set(frameId, new FrameInfo(tabId, frameId, parent, url));
      }
    })
  ));
}

function onSitekeyReceived(tabId, frameId, url, sitekey) {
  let frame = getFrameInfo(tabId, frameId);
  let isSameFrame = frame && frame.url == url;
  if (isSameFrame)
    frame.headersReceived = true;

  if (sitekey) {
    // Sometimes the onHeadersReceived event comes after the
    // onCommitted event. This seems to be common when loading
    // iframes: the browser will show the iframe and then start
    // loading its contents. When this happens, we may get a sitekey
    // for a frame that's already being shown, and that may mean we
    // need to add some new allowlisting filters based on that
    // sitekey.
    if (isSameFrame && frame.sitekey != sitekey) {
      frame.sitekey = sitekey;
      findAllowlistingFilters(frame, tabId, frameId);
    }
  }
}


/**
 * Updates the frame state to reflect that a new frame is being shown.
 *
 * This can broadly be thought of in two categories:
 *
 * 1. The browser has navigated to the new page. Specifically, this is
 *    on the `webNavigation.onCommitted` event, which fires when the
 *    browser has decided to switch to the new document. We will
 *    usually have received headers for the document already by this
 *    point, but not always.
 * 2. The site is a single page application, and has updated its
 *    contents using Javascript and updated its URL with the history
 *    API.
 *
 * @param {Object} details Details object as provided by the
 *   webNavigation API events.
 * @param {number} details.tabId The tabId of the tab that the updated
 *   frame is on.
 * @param {number} details.frameId The frameId of the updated frame.
 * @param {number} [details.parentFrameId=-1] The frameId of the frame
 *   that the updated frame is on. -1 if the updated frame is the
 *   top-level frame.
 * @param {string} details.url The new url of the frame.
 * @param {Object} [options={}]
 * @param {boolean} [options.historyStateUpdated=false] True if this
 *   was triggered by a history state update, rather than by a full
 *   page navigation.
 * @param {boolean} [options.errorOccurred=false] True if this was
 *   triggered by a `webNavigation.onErrorOccurred` event rather than
 *   a `webNavigation.onCommitted` event.
 * @return {FrameInfo} The newly created frame state.
 */
function recordFrameFromNavigationEvent(
  {tabId, frameId, parentFrameId = -1, url},
  {historyStateUpdated = false, errorOccurred = false} = {}) {
  // Yandex gives undefined or an empty string here sometimes,
  // for example when browsing to pages that Yandex treats
  // specially like their own website.
  if (!url)
    url = BLANK_PAGE_URL;

  let frames = state.get(tabId);

  // We generally need to throw away any existing frame state for the
  // whole tab when a new top-level frame is committed to the
  // tab. This is because all previous frame state was on the old
  // top-level frame. However, if this was a history API update, those
  // frames could still be there on the page so we can't clear them out.
  if (!frames || (isTopLevelFrameId(frameId) && !historyStateUpdated)) {
    frames = new Map();
    state.set(tabId, frames);
  }
  let frame = frames.get(frameId);
  let parent = isValidFrameId(parentFrameId) ? frames.get(parentFrameId) : null;

  // Same as discoverExistingFrames, if we expect a parent but our
  // frame state doesn't seem to have that parent, falling back to the
  // root frame is better than nothing. This might happen due to this
  // bug: https://bugs.chromium.org/p/chromium/issues/detail?id=725917.
  if (isValidChildFrameId(parentFrameId) && !parent)
    parent = frames.get(TOP_LEVEL_FRAME_ID);

  // If the frame had an error instead of loading, we don't want to
  // use the URL from the error. Otherwise unscrupulous websites could
  // embed their advert in an iframe that has an allowlisted URL, but
  // doesn't actually contain the contents of that URL.
  if (errorOccurred) {
    if (frame)
      url = frame.url;
    else if (parent)
      url = parent.url;
  }

  // We might get multiple calls to `recordFrameFromNavigationEvent`
  // for iframes. This is because we need to listen to several
  // different events to hear about all frames, including onCommitted
  // and onBeforeNavigate and onErrorOccurred. To avoid duplicate
  // onBlockableItem events, we check if the frame we already have is
  // the same.
  if (!frame || isTopLevelFrameId(frameId) ||
      frame.url != url || frame.parent != parent) {
    frame = new FrameInfo(tabId, frameId, parent, url);
    frames.set(frameId, frame);
  }
  return frame;
}

function onBeforeNavigate(details) {
  // If an iframe's URL is "about:srcdoc", that means its contents is
  // actually specified using the srcdoc attribute. Some browsers
  // don't actually emit the webNavigation.onCommitted event for these
  // frames, so we need to use a different event to get them into our
  // frame state.
  if (details.url == "about:srcdoc")
    recordFrameFromNavigationEvent(details);
}

function onCommitted(details) {
  recordFrameFromNavigationEvent(details);
  notifyOnFrameInfo(details.tabId, details.frameId);
}

function onErrorOccurred(details) {
  // On Chrome, errored iframes are never committed, but they are
  // still on the page and their contents can still be manipulated
  // with Javascript so we need them in our frame state.
  // See https://bugs.chromium.org/p/chromium/issues/detail?id=725917
  //
  // Firefox's docs don't mention parentFrameId on this event, but
  // Chrome's do, and it does appear to be there in practice. Check
  // for it before proceeding in case some browsers don't, since it's
  // very important to have the parent frame to record frame state
  // changes.
  if (isValidChildFrameId(details.frameId) &&
      typeof details.parentFrameId == "number")
    recordFrameFromNavigationEvent(details, {errorOccurred: true});
}

function onHistoryStateUpdated(details) {
  recordFrameFromNavigationEvent(details, {historyStateUpdated: true});
}

function handleOnRemoved(tabId) {
  state.delete(tabId);
  (0,_sitekey_js__WEBPACK_IMPORTED_MODULE_5__.clearTabSitekeys)(tabId);
  notifyOnTabRemoved(tabId);
}

function onRemoved(tabId) {
  handleOnRemoved(tabId);
}

function onReplaced(addedTabId, removedTabId) {
  handleOnRemoved(removedTabId);
}

/**
 * Gets the state for a frame if we have it. If parentFrameId and
 * initiator are also provided, this function may also construct the
 * frame and add it to the frame state.
 *
 * @param {number} tabId The tabId of the tab the frame is on.
 * @param {number} frameId The frameId of the frame.
 * @param {?Object} [metadata] Additional metadata about the web
 *   request context that lead to asking for frame info, which might
 *   be used to create a FrameInfo if one doesn't exist already.
 * @param {?number} metadata.parentFrameId The frameId of the parent of the
 *   frame being requested. If this is set, it could be used to
 *   create the frame if it isn't already in the frame state.
 * @param {?string} metadata.initiator If getting the frame info is
 *   triggered by a web request, this should be the URL that initiated
 *   the request. If this is set, it can be used to provide a
 *   temporary frame state for use with service workers. In Firefox
 *   APIs, there is not an initiator but there is a documentUrl which
 *   can fulfil the same purpose.
 * @param {?string} metadata.documentUrl If getting the frame info is
 *   triggered by a web request, this should be the URL of the frame
 *   that initiated the request. If this is set, it could be used to
 *   create the frame if it isn't already in the frame state. This may
 *   not be available in Chrome. In Chrome, if initiator is provided,
 *   it can also be used to construct a FrameInfo, but this is not
 *   ideal since the initiator only contains the domain part of the
 *   URL.
 * @returns {?FrameInfo}
 */
function getFrameInfo(tabId, frameId,
                             {parentFrameId, initiator, documentUrl} = {}) {
  // tabId is -1 if the request came from a service worker, so we
  // construct a temporary frame state for it to use. We don't store
  // a tabId of -1 in our frame state, so we don't even need to check
  // it before returning.
  if (initiator && tabId == -1)
    return new FrameInfo(tabId, frameId, null, initiator);

  let frames = state.get(tabId);
  if (frames) {
    let frame = frames.get(frameId);
    if (frame)
      return frame;
  }

  // Sometimes the webRequest API can trigger for resources in a frame
  // before the onCommitted event for the frame. In this case, it
  // should be safe to construct the frame state early.
  if (documentUrl && typeof parentFrameId == "number") {
    return recordFrameFromNavigationEvent({
      tabId,
      frameId,
      parentFrameId,
      url: documentUrl
    });
  }
}

async function start() {
  if (!startupPromise) {
    (0,_sitekey_js__WEBPACK_IMPORTED_MODULE_5__.addListener)(onSitekeyReceived);

    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.webNavigation.onCommitted.addListener(onCommitted);
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.webNavigation.onErrorOccurred.addListener(onErrorOccurred);
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.webNavigation.onHistoryStateUpdated.addListener(
      onHistoryStateUpdated);
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.tabs.onRemoved.addListener(onRemoved);
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.tabs.onReplaced.addListener(onReplaced);

    startupPromise = discoverExistingFrames();
  }

  await startupPromise;
}


/***/ }),

/***/ "./sdk/api/id-utils.js":
/*!*****************************!*\
  !*** ./sdk/api/id-utils.js ***!
  \*****************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_710223__) => {

"use strict";
__nested_webpack_require_710223__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_710223__.d(__webpack_exports__, {
/* harmony export */   "INDEX_MAX": () => (/* binding */ INDEX_MAX),
/* harmony export */   "encode": () => (/* binding */ encode),
/* harmony export */   "decode": () => (/* binding */ decode)
/* harmony export */ });
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */

// Chromium supports 31 bits per rule id

// max value for DNR rule index
const INDEX_MAX = 2000;

function encode(
  index,  /* Can be in range of 0-`INDEX_MAX`
             Also we add 1, the higher range value is `INDEX_MAX`-1 */
  line) { // Can be in range of 0-Math.floor((2^31 - 1)/INDEX_MAX)-1 only
  // add 1 as Chromium requires rule id to start from 1
  return 1 + index + line * INDEX_MAX;
}

function decode(ruleId) {
  // Reduce 1 as Chromium requires rule id to start from 1
  // and we've added 1 while encoding
  ruleId -= 1;
  let index = ruleId % INDEX_MAX;
  let line = Math.floor(ruleId / INDEX_MAX);
  return {index, line};
}


/***/ }),

/***/ "./sdk/api/idb.js":
/*!************************!*\
  !*** ./sdk/api/idb.js ***!
  \************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_712112__) => {

"use strict";
__nested_webpack_require_712112__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_712112__.d(__webpack_exports__, {
/* harmony export */   "openDatabase": () => (/* binding */ openDatabase)
/* harmony export */ });
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */

const DB_NAME = "EWE";
const DB_VERSION = 1;

function openDatabase() {
  return new Promise((resolve, reject) => {
    let request = indexedDB.open(DB_NAME, DB_VERSION);

    request.onupgradeneeded = event => {
      let db = event.target.result;
      db.createObjectStore("file-entries");
      db.createObjectStore("file-contents", {autoIncrement: true});
    };

    request.onsuccess = event => resolve(event.target.result);
    request.onerror = event => reject(event.target.error);
  });
}


/***/ }),

/***/ "./sdk/api/info.js":
/*!*************************!*\
  !*** ./sdk/api/info.js ***!
  \*************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_713736__) => {

"use strict";
__nested_webpack_require_713736__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_713736__.d(__webpack_exports__, {
/* harmony export */   "addonName": () => (/* binding */ addonName),
/* harmony export */   "addonVersion": () => (/* binding */ addonVersion),
/* harmony export */   "addonBundledSubscriptions": () => (/* binding */ addonBundledSubscriptions),
/* harmony export */   "addonBundledSubscriptionsPath": () => (/* binding */ addonBundledSubscriptionsPath),
/* harmony export */   "application": () => (/* binding */ application),
/* harmony export */   "applicationVersion": () => (/* binding */ applicationVersion),
/* harmony export */   "platform": () => (/* binding */ platform),
/* harmony export */   "platformVersion": () => (/* binding */ platformVersion),
/* harmony export */   "manifestVersion": () => (/* binding */ manifestVersion),
/* harmony export */   "setAddonInfo": () => (/* binding */ setAddonInfo)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_713736__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_713736__(/*! adblockpluscore/lib/recommendations.js */ "./node_modules/adblockpluscore/lib/recommendations.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */





let manifest = _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getManifest();

let addonName = manifest.short_name || manifest.name;
let addonVersion = manifest.version;
let addonBundledSubscriptions;
let addonBundledSubscriptionsPath;
let application = "unknown";
let applicationVersion = "0";
let platform;
let platformVersion = "0";
let manifestVersion = String(manifest.manifest_version);

function parseChromiumUserAgent() {
  let regexp = /(\S+)\/(\S+)(?:\s*\(.*?\))?/g;
  let match;

  while (match = regexp.exec(navigator.userAgent)) {
    let [, app, version] = match;

    // For compatibility with legacy websites, Chrome's UA
    // also includes a Mozilla, AppleWebKit and Safari tokens.
    // Any further name/version pair indicates a fork.
    if (app == "Mozilla" || app == "AppleWebKit" || app == "Safari")
      continue;

    if (app == "Chrome") {
      platformVersion = version;
      if (application != "unknown")
        continue;
    }

    application = app == "OPR" ? "opera" : app.toLowerCase();
    applicationVersion = version;
  }
}

if (typeof netscape != "undefined") {
  platform = "gecko";

  let match = /\brv:([^;)]+)/.exec(navigator.userAgent);
  if (match)
    platformVersion = match[1];

  _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getBrowserInfo().then(browserInfo => {
    application = browserInfo.name.toLowerCase();
    applicationVersion = browserInfo.version;
  });
}
else {
  platform = "chromium";
  parseChromiumUserAgent();
}

function setAddonInfo(addonInfo) {
  if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest) {
    if (!addonInfo)
      throw new Error("No addonInfo provided to EWE.start");

    if (!addonInfo.bundledSubscriptions)
      throw new Error("No `bundledSubscriptions` provided");

    if (!addonInfo.bundledSubscriptionsPath)
      throw new Error("No `bundledSubscriptionsPath` provided");
  }

  if (!addonInfo)
    return;

  if (addonInfo.name)
    addonName = addonInfo.name;
  if (addonInfo.version)
    addonVersion = addonInfo.version;
  if (addonInfo.manifestVersion)
    manifestVersion = addonInfo.manifestVersion;

  addonBundledSubscriptions = addonInfo.bundledSubscriptions;
  addonBundledSubscriptionsPath = addonInfo.bundledSubscriptionsPath;

  if (addonBundledSubscriptions &&
      addonBundledSubscriptions.length > 0)
    (0,adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_1__.setRecommendations)(addonBundledSubscriptions);
}


/***/ }),

/***/ "./sdk/api/initializer.js":
/*!********************************!*\
  !*** ./sdk/api/initializer.js ***!
  \********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_718482__) => {

"use strict";
__nested_webpack_require_718482__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_718482__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_718482__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_718482__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/* harmony import */ var _io_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_718482__(/*! ./io.js */ "./sdk/api/io.js");
/* harmony import */ var _dnr_filters_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_718482__(/*! ./dnr-filters.js */ "./sdk/api/dnr-filters.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_718482__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/* harmony import */ var _debugging_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_718482__(/*! ./debugging.js */ "./sdk/api/debugging.js");
/* harmony import */ var _reporting_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_718482__(/*! ./reporting.js */ "./sdk/api/reporting.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */









let startupPromise;

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * Initializes stateful modules that may be used in filtering requests.
   *
   * This function is idempotent. If you call it after initialization
   * has already been launched elsewhere, then it will return the same
   * promise as the original initialization. This allows this function
   * to be called anywhere that you need to ensure that initialization
   * has completed before continuing.
   *
   * Calling this function is required for the other API calls to
   * work, except for API event listener calls, which could also be
   * done before `start()`.
   * @return {Promise} Resolves when initialization is complete
   */
  start() {
    if (!startupPromise) {
      startupPromise = (async() => {
        await _io_js__WEBPACK_IMPORTED_MODULE_2__.IO.initialize();
        await _debugging_js__WEBPACK_IMPORTED_MODULE_5__.default.start();
        await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_4__.init)();
        await _core_js__WEBPACK_IMPORTED_MODULE_0__.filterEngine.initialize();
        await _frame_state_js__WEBPACK_IMPORTED_MODULE_1__.start();
        await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_3__.init)();
        await _reporting_js__WEBPACK_IMPORTED_MODULE_6__.default.start();
      })();
    }
    return startupPromise;
  }
});


/***/ }),

/***/ "./sdk/api/io-bsl.js":
/*!***************************!*\
  !*** ./sdk/api/io-bsl.js ***!
  \***************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_721913__) => {

"use strict";
__nested_webpack_require_721913__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_721913__.d(__webpack_exports__, {
/* harmony export */   "IO": () => (/* binding */ IO)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_721913__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



const KEY_PREFIX = "ewe:file:";

function fileToKey(fileName) {
  return KEY_PREFIX + fileName;
}

async function loadFile(fileName) {
  let key = fileToKey(fileName);
  let items = await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.get(key);
  let entry = items[key];
  if (entry)
    return entry;
  throw {type: "NoSuchFile"};
}

function saveFile(fileName, data) {
  return webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.set({
    [fileToKey(fileName)]: {
      content: Array.from(data),
      lastModified: Date.now()
    }
  });
}

// IO implementation that is using `browser.storage.local` API
let IO = {
  /**
   * Reads text lines from a file.
   * @param {string} filename
   *    Name of the file to be read
   * @param {TextSink} listener
   *    Function that will be called for each line in the file
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  async readFromFile(filename, listener) {
    let entry = await loadFile(filename);
    for (let line of entry.content)
      listener(line);
  },

  /**
   * Writes text lines to a file.
   * @param {string} filename
   *    Name of the file to be written
   * @param {Iterable.<string>} data
   *    An array-like or iterable object containing the lines (without line
   *    endings)
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  writeToFile(filename, data) {
    return saveFile(filename, data);
  },

  /**
   * Renames a file.
   * @param {string} fromFile
   *    Name of the file to be renamed
   * @param {string} newName
   *    New file name, will be overwritten if exists
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  async renameFile(fromFile, newName) {
    let entry = await loadFile(fromFile);
    await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.set({[fileToKey(newName)]: entry});
    await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.remove(fileToKey(fromFile));
  },

  /**
   * Retrieves file metadata.
   * @param {string} filename
   *    Name of the file to be looked up
   * @return {Promise.<StatData>}
   *    Promise to be resolved with file metadata once the operation is
   *    completed
   */
  async statFile(filename) {
    try {
      let entry = await loadFile(filename);
      return {
        exists: true,
        lastModified: entry.lastModified
      };
    }
    catch (error) {
      if (error.type == "NoSuchFile")
        return Promise.resolve({exists: false});
      throw error;
    }
  },

  async fixPrefixes() {
    let data = await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.get();
    for (let key in data) {
      let value = data[key];

      // The order of prefixes matters:
      // the most important should be the last
      // to override the existing values jic.
      for (let eachPrefix of ["abp:file:", "file:"]) {
        if (key.startsWith(eachPrefix)) {
          let obj = {};
          obj[KEY_PREFIX + key.substring(eachPrefix.length)] = value;
          await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.set(obj);
          await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.remove(key);
        }
      }
    }
  },

  /**
   * Initialize the storage
   * @return {Promise} initialization promise
   */
  async initialize() {
    // Migrating the files with 'file:' and `abp:file:` prefixes
    // to 'ewe:file:' stored in `browser.storage.local` in Firefox private mode.
    // See https://gitlab.com/eyeo/adblockplus/abc/webext-sdk/-/issues/369
    await this.fixPrefixes();
  }
};



/***/ }),

/***/ "./sdk/api/io-idb.js":
/*!***************************!*\
  !*** ./sdk/api/io-idb.js ***!
  \***************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_726963__) => {

"use strict";
__nested_webpack_require_726963__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_726963__.d(__webpack_exports__, {
/* harmony export */   "getDatabase": () => (/* binding */ getDatabase),
/* harmony export */   "IO": () => (/* binding */ IO)
/* harmony export */ });
/* harmony import */ var _idb_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_726963__(/*! ./idb.js */ "./sdk/api/idb.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



let database;

function clearContent(filename, entryStore, contentStore) {
  entryStore.get(filename).onsuccess = event => {
    let entry = event.target.result;
    if (entry)
      contentStore.delete(entry.content);
  };
}

function saveFile(db, filename, lines, lastModified) {
  return new Promise((resolve, reject) => {
    let data = new TextEncoder().encode(Array.from(lines).join("\n"));
    let tx = db.transaction(["file-entries", "file-contents"], "readwrite");
    let entryStore = tx.objectStore("file-entries");
    let contentStore = tx.objectStore("file-contents");

    clearContent(filename, entryStore, contentStore);
    contentStore.add(data).onsuccess = event => {
      let content = event.target.result;
      entryStore.put({lastModified, content}, filename);
    };

    tx.oncomplete = () => resolve();
    tx.onerror = tx.onabort = event => reject(event.target.error);
  });
}

async function initIO(db) {
  database = db;
}

function getDatabase() {
  if (!database)
    throw new Error("Database hasn't been opened. Did you call start()?");
  return database;
}

// IO implementation that is using `IndexedDB`
let IO = {
  /**
   * Reads text lines from a file.
   * @param {string} filename
   *    Name of the file to be read
   * @param {TextSink} listener
   *    Function that will be called for each line in the file
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  async readFromFile(filename, listener) {
    let data = await new Promise((resolve, reject) => {
      let db = getDatabase();
      let tx = db.transaction(["file-entries", "file-contents"], "readonly");
      let entryStore = tx.objectStore("file-entries");
      let contentStore = tx.objectStore("file-contents");

      entryStore.get(filename).onsuccess = entryEvent => {
        let entry = entryEvent.target.result;
        if (!entry) {
          reject(new Error("File does not exist"));
          return;
        }

        contentStore.get(entry.content).onsuccess = contentEvent => {
          resolve(contentEvent.target.result);
        };
      };

      tx.onerror = tx.onabort = event => reject(event.target.error);
    });

    let decoder = new TextDecoder();
    let start = 0;

    while (true) {
      let index = data.indexOf(10 /* newline character */, start + 1000);
      let end = index != -1 ? index : data.length;
      let text = decoder.decode(data.subarray(start, end));

      for (let line of text.split("\n"))
        listener(line);

      if (index == -1)
        break;

      start = index + 1;
    }
  },

  /**
   * Writes text lines to a file.
   * @param {string} filename
   *    Name of the file to be written
   * @param {Iterable<string>} lines
   *    An array-like or iterable object containing the lines (without line
   *    endings)
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  async writeToFile(filename, lines) {
    await saveFile(getDatabase(), filename, lines, Date.now());
  },

  /**
   * Renames a file.
   * @param {string} oldName
   *    Name of the file to be renamed
   * @param {string} newName
   *    New file name, will be overwritten if exists
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  renameFile(oldName, newName) {
    return new Promise((resolve, reject) => {
      let db = getDatabase();
      let tx = db.transaction(["file-entries", "file-contents"], "readwrite");
      let entryStore = tx.objectStore("file-entries");
      let contentStore = tx.objectStore("file-contents");

      entryStore.get(oldName).onsuccess = event => {
        let entry = event.target.result;
        if (!entry) {
          reject(new Error("File does not exist"));
          return;
        }

        clearContent(newName, entryStore, contentStore);
        entryStore.put(entry, newName);
        entryStore.delete(oldName);
      };

      tx.oncomplete = () => resolve();
      tx.onerror = tx.onabort = event => reject(event.target.error);
    });
  },

  /**
   * Retrieves file metadata.
   * @param {string} filename
   *    Name of the file to be looked up
   * @return {Promise<StatData>}
   *    Promise to be resolved with file metadata once the operation is
   *    completed
   */
  statFile(filename) {
    return new Promise((resolve, reject) => {
      let db = getDatabase();
      let tx = db.transaction(["file-entries"], "readonly");
      let store = tx.objectStore("file-entries");

      store.get(filename).onsuccess = event => {
        let entry = event.target.result;
        let exists = false;
        let lastModified;

        if (entry) {
          exists = true;
          lastModified = entry.lastModified;
        }

        resolve({exists, lastModified});
      };

      tx.onerror = tx.onabort = event => reject(event.target.error);
    });
  },

  /**
   * Initialize the storage
   * @return {Promise} initialization promise
   */
  async initialize() {
    let db = await (0,_idb_js__WEBPACK_IMPORTED_MODULE_0__.openDatabase)();
    await initIO(db);
  }
};


/***/ }),

/***/ "./sdk/api/io.js":
/*!***********************!*\
  !*** ./sdk/api/io.js ***!
  \***********************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_733402__) => {

"use strict";
__nested_webpack_require_733402__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_733402__.d(__webpack_exports__, {
/* harmony export */   "readFileContent": () => (/* binding */ readFileContent),
/* harmony export */   "IO": () => (/* binding */ IO)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_733402__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var _io_idb_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_733402__(/*! ./io-idb.js */ "./sdk/api/io-idb.js");
/* harmony import */ var _io_bsl_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_733402__(/*! ./io-bsl.js */ "./sdk/api/io-bsl.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */






let io;
let initializationPromise;

function readFileContent(path) {
  const url = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.runtime.getURL(path);
  return fetch(url).then(content => content.text());
}

// This is a facade implementation that forwards to the current concrete
// implementation of IO. By default IndexedDB is used but if it's unavailable
// a fallback to `browser.storage.local` is used.
let IO = {
  /**
   * Reads text lines from a file.
   * @param {string} filename
   *    Name of the file to be read
   * @param {TextSink} listener
   *    Function that will be called for each line in the file
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  async readFromFile(filename, listener) {
    return io.readFromFile(filename, listener);
  },

  /**
   * Writes text lines to a file.
   * @param {string} filename
   *    Name of the file to be written
   * @param {Iterable<string>} lines
   *    An array-like or iterable object containing the lines (without line
   *    endings)
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  async writeToFile(filename, lines) {
    return io.writeToFile(filename, lines);
  },

  /**
   * Renames a file.
   * @param {string} oldName
   *    Name of the file to be renamed
   * @param {string} newName
   *    New file name, will be overwritten if exists
   * @return {Promise}
   *    Promise to be resolved or rejected once the operation is completed
   */
  renameFile(oldName, newName) {
    return io.renameFile(oldName, newName);
  },

  /**
   * Retrieves file metadata.
   * @param {string} filename
   *    Name of the file to be looked up
   * @return {Promise<StatData>}
   *    Promise to be resolved with file metadata once the operation is
   *    completed
   */
  statFile(filename) {
    return io.statFile(filename);
  },

  /**
   * Initialize the storage
   * @return {Promise} initialization promise
   */
  initialize() {
    if (!initializationPromise) {
      initializationPromise = (async() => {
        io = _io_idb_js__WEBPACK_IMPORTED_MODULE_1__.IO;
        try {
          await io.initialize();
        }
        catch (e) {
          if (e instanceof DOMException &&
              e.name == "InvalidStateError") {
            // fall back to `browser.storage.local` API if IndexedDb
            // is unavailable, eg. in Firefox in private mode. See
            // https://gitlab.com/eyeo/adblockplus/abc/webext-sdk/-/issues/231
            io = _io_bsl_js__WEBPACK_IMPORTED_MODULE_2__.IO;
            try {
              await io.initialize();
            }
            catch {
              initializationPromise = null;
              throw e;
            }
          }
          else {
            initializationPromise = null;
            throw e;
          }
        }
      })();
    }

    return initializationPromise;
  }
};


/***/ }),

/***/ "./sdk/api/message-responder.js":
/*!**************************************!*\
  !*** ./sdk/api/message-responder.js ***!
  \**************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_738045__) => {

"use strict";
__nested_webpack_require_738045__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_738045__.d(__webpack_exports__, {
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_738045__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var _initializer_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_738045__(/*! ./initializer.js */ "./sdk/api/initializer.js");
/* harmony import */ var _content_filter_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_738045__(/*! ./content-filter.js */ "./sdk/api/content-filter.js");
/* harmony import */ var adblockpluscore_lib_elemHide_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_738045__(/*! adblockpluscore/lib/elemHide.js */ "./node_modules/adblockpluscore/lib/elemHide.js");
/* harmony import */ var _subscribe_links_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_738045__(/*! ./subscribe-links.js */ "./sdk/api/subscribe-links.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_738045__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _allowlisting_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_738045__(/*! ./allowlisting.js */ "./sdk/api/allowlisting.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */










async function handleMessage(message, sender) {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_1__.default.start();
  switch (message.type) {
    case "ewe:content-hello":
      // Firefox mistakenly runs content scripts in non-web page context,
      // it does not happen in Chrome.
      // https://gitlab.com/eyeo/adblockplus/abc/webext-sdk/-/issues/174.
      // Messages sent from a non-web page context do not have an
      // associated tab and can be ignored.
      if (!sender.tab)
        return;

      let filterData = await (0,_content_filter_js__WEBPACK_IMPORTED_MODULE_2__.applyContentFilters)(sender.tab.id, sender.frameId);
      return {...filterData};
    case "ewe:subscribe-link-clicked":
      (0,_subscribe_links_js__WEBPACK_IMPORTED_MODULE_4__.subscribeLinkClicked)(message.url, message.title);
      break;
    case "ewe:trace-elem-hide":
      (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_5__.logHiddenElements)(message.selectors, message.filters, sender);
      break;
    case "ewe:inject-css":
      let styleSheet = (0,adblockpluscore_lib_elemHide_js__WEBPACK_IMPORTED_MODULE_3__.createStyleSheet)([message.selector]);
      (0,_content_filter_js__WEBPACK_IMPORTED_MODULE_2__.injectCSS)(sender.tab.id, sender.frameId, styleSheet);
      break;
    case "ewe:allowlist-page":
      return (0,_allowlisting_js__WEBPACK_IMPORTED_MODULE_6__.allowlistPage)(
        sender.tab.id, sender.frameId, message.timestamp, message.signature
      );
  }
}

function onMessage(message, sender) {
  if (typeof message == "object" && message != null &&
      message.type && message.type.startsWith("ewe:"))
    return handleMessage(message, sender);
  return false;
}

/**
 * Start the message responder module. In MV3, this must be called in
 * the first turn of the event loop.
 */
function start() {
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.runtime.onMessage.addListener(onMessage);
}


/***/ }),

/***/ "./sdk/api/notifications.js":
/*!**********************************!*\
  !*** ./sdk/api/notifications.js ***!
  \**********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_742259__) => {

"use strict";
__nested_webpack_require_742259__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_742259__.d(__webpack_exports__, {
/* harmony export */   "notifications": () => (/* binding */ notifications)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_742259__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_742259__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/* harmony import */ var adblockpluscore_lib_notifications_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_742259__(/*! adblockpluscore/lib/notifications.js */ "./node_modules/adblockpluscore/lib/notifications.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */







const NOTIFICATION_KEY = "ewe:notifications";
class NotificationSessionStorageBackend {
  constructor() {
    this.local = new Set();
    this.loaded = this.load();
  }

  add(notification) {
    this.local.add(notification);
    this.save();
  }

  delete(notification) {
    let removed = this.local.delete(notification);
    if (removed)
      this.save();

    return removed;
  }

  [Symbol.iterator]() {
    return this.local[Symbol.iterator]();
  }

  async load() {
    let result = await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.session.get([NOTIFICATION_KEY]);
    let loadedNotifications = result[NOTIFICATION_KEY] || [];
    for (let notification of loadedNotifications)
      this.local.add(notification);
  }

  async save() {
    await this.loaded;
    if (!this.debounceTimer) {
      this.debounceTimer = setTimeout(() => {
        this.debounceTimer = null;
        this.saveImmediate();
      }, 0);
    }
  }

  async saveImmediate() {
    await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.session.set({
      [NOTIFICATION_KEY]: [...this.local]
    });
  }
}

if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.session) {
  adblockpluscore_lib_notifications_js__WEBPACK_IMPORTED_MODULE_2__.notifications.setLocalNotificationStorage(
    new NotificationSessionStorageBackend()
  );
}

let funcsThatRequirePrefs = [
  "start",
  "shouldIgnoreNotifications",
  "showNotification",
  "showNext",
  "markAsShown",
  "toggleIgnoreCategory",
  "getDownloadCount",
  "getIgnoredCategories"
];

/**
 * The notifications API (optional usage).
 *
 * Call `notifications.start()` to start downloading remote
 * notifications. Local notifications functions such as
 * `notifications.addNotification(notification)` and
 * `notifications.showNotification(notification)` can be used even if
 * `notifications.start()` has not been called.
 *
 *  Please also notice that notification events are **not** using the
 * {@link #eventdispatcher|EventDispatcher} interface.
 *
 * Note that, when used through EWE, the following notifications
 * functions are asynchronous and return the values specified in the
 * Core documentation wrapped in promises:
 * - start
 * - shouldIgnoreNotifications
 * - showNotification
 * - showNext
 * - markAsShown
 * - toggleIgnoreCategory
 * - getDownloadCount
 * - getIgnoredCategories
 *
 * @see {@link https://eyeo.gitlab.io/adblockplus/abc/adblockpluscore/master/docs/module-notifications.html?job=docs|Adblock Plus core notifications documentation}
 */
let notifications = new Proxy(adblockpluscore_lib_notifications_js__WEBPACK_IMPORTED_MODULE_2__.notifications, {
  get(target, prop, receiver) {
    if (funcsThatRequirePrefs.includes(prop)) {
      return async function(...args) {
        await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_1__.init)();
        return target[prop](...args);
      };
    }
    return target[prop];
  }
});


/***/ }),

/***/ "./sdk/api/popup-blocker-background-page.js":
/*!**************************************************!*\
  !*** ./sdk/api/popup-blocker-background-page.js ***!
  \**************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_746946__) => {

"use strict";
__nested_webpack_require_746946__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_746946__.d(__webpack_exports__, {
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_746946__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_746946__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_746946__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_746946__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_746946__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_746946__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */










let loadingPopups = new Map();

function forgetPopup(tabId) {
  loadingPopups.delete(tabId);

  if (loadingPopups.size == 0) {
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onBeforeRequest.removeListener(onPopupURLChanged);
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onBeforeNavigate.removeListener(onPopupURLChanged);
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onCompleted.removeListener(onCompleted);
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.onRemoved.removeListener(onTabRemoved);
  }
}

function checkPotentialPopup(sourceTabId, popupTabId, url, frame) {
  let specificOnly = (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICBLOCK) != 0;
  let filter = _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine.defaultMatcher.match(
    url || _frame_state_js__WEBPACK_IMPORTED_MODULE_5__.BLANK_PAGE_URL, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.POPUP,
    frame.hostname, frame.sitekey, specificOnly
  );

  if (filter) {
    (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_4__.logItem)({tabId: sourceTabId, frameId: 0, url}, filter,
            {docDomain: frame.hostname, specificOnly, method: "popup"});

    if (filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.BlockingFilter)
      webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.remove(popupTabId).catch(() => {});

    forgetPopup(popupTabId);
  }
}

function onPopupURLChanged({frameId, tabId, url}) {
  if (!(0,_frame_state_js__WEBPACK_IMPORTED_MODULE_5__.isTopLevelFrameId)(frameId))
    return;

  let frame = loadingPopups.get(tabId);
  if (frame)
    checkPotentialPopup(frame.tabId, tabId, url, frame);
}

function onCompleted({frameId, url, tabId}) {
  if ((0,_frame_state_js__WEBPACK_IMPORTED_MODULE_5__.isTopLevelFrameId)(frameId) && url != _frame_state_js__WEBPACK_IMPORTED_MODULE_5__.BLANK_PAGE_URL)
    forgetPopup(tabId);
}

function onTabRemoved({tabId}) {
  forgetPopup(tabId);
}

function onPopup({tabId, url, sourceTabId, sourceFrameId}) {
  let frame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_5__.getFrameInfo)(sourceTabId, sourceFrameId);

  if (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT)
    return;

  if (loadingPopups.size == 0) {
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onBeforeRequest.addListener(
      onPopupURLChanged,
      {
        urls: ["http://*/*", "https://*/*"],
        types: ["main_frame"]
      }
    );
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onBeforeNavigate.addListener(onPopupURLChanged);
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onCompleted.addListener(onCompleted);
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.onRemoved.addListener(onTabRemoved);
  }

  loadingPopups.set(tabId, frame);
  checkPotentialPopup(sourceTabId, tabId, url, frame);
}

function onTabCreated({id, url, openerTabId}) {
  if (openerTabId)
    onPopup({tabId: id, url, sourceTabId: openerTabId, sourceFrameId: 0});
}

/**
 * Starts blocking popups. Must only be called after filter engine and
 * frame state are initialized.
 */
function start() {
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onCreatedNavigationTarget.addListener(onPopup);

  // On Firefox, clicking on a <a target="_blank" rel="noopener"> link doesn't
  // emit the webNavigation.onCreatedNavigationTarget event (and Firefox >=79,
  // implies "noopener" by default). But on Chrome, opening a new empty tab
  // emits the tabs.onCreated event with openerTabId set. So this would
  // cause new tabs created by the user to be considered popups too, on Chrome.
  if (typeof netscape != "undefined")
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.onCreated.addListener(onTabCreated);
}


/***/ }),

/***/ "./sdk/api/popup-blocker-service-worker.js":
/*!*************************************************!*\
  !*** ./sdk/api/popup-blocker-service-worker.js ***!
  \*************************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_753147__) => {

"use strict";
__nested_webpack_require_753147__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_753147__.d(__webpack_exports__, {
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_753147__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_753147__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_753147__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_753147__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _initializer_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_753147__(/*! ./initializer.js */ "./sdk/api/initializer.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_753147__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_753147__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */











const SESSION_STORAGE_KEY = "ewe:popupBlocker:loadingPopups";

class PotentialPopupMap {
  constructor() {
    this.openerPromiseMap = {};
    this.loaded = (async() => {
      let result = await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.session.get([SESSION_STORAGE_KEY]);
      this.openerMap = result[SESSION_STORAGE_KEY] || {};
    })();
  }

  async saveMap() {
    await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.session.set({
      [SESSION_STORAGE_KEY]: this.openerMap
    });
  }

  set(tabId, openerPromise) {
    if (this.openerPromiseMap[tabId] || this.openerMap[tabId])
      return;

    this.openerPromiseMap[tabId] = openerPromise;
    openerPromise.then(async opener => {
      await this.loaded;

      delete this.openerPromiseMap[tabId];
      if (opener) {
        this.openerMap[tabId] = opener;
        await this.saveMap();
      }
    });
  }

  async get(tabId) {
    let openerPromise = this.openerPromiseMap[tabId];
    if (openerPromise)
      return await openerPromise;

    await this.loaded;
    let opener = this.openerMap[tabId];
    return opener;
  }

  has(tabId) {
    return Object.hasOwnProperty.call(this.openerPromiseMap, tabId) ||
      Object.hasOwnProperty.call(this.openerMap, tabId);
  }

  async remove(tabId) {
    if (this.openerPromiseMap[tabId])
      delete this.openerPromiseMap[tabId];

    if (this.openerMap[tabId]) {
      delete this.openerMap[tabId];
      await this.saveMap();
    }
  }
}

let potentialPopups;

async function checkPotentialPopup(popupTabId, url, opener) {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_4__.default.start();
  let {docDomain, sitekey, specificOnly} = opener;

  // because of the async nature of getting to this point, it might
  // have been handled before we get here.
  if (!potentialPopups.has(popupTabId))
    return;


  let filter = _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine.defaultMatcher.match(
    url || _frame_state_js__WEBPACK_IMPORTED_MODULE_6__.BLANK_PAGE_URL, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.POPUP, docDomain, sitekey, specificOnly
  );

  if (filter) {
    (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_5__.logItem)({tabId: opener.tabId, frameId: 0, url}, filter,
            {docDomain, specificOnly, method: "popup"});

    if (filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.BlockingFilter)
      webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.remove(popupTabId).catch(() => {});

    await potentialPopups.remove(popupTabId);
  }
}

async function onPopupURLChanged({frameId, tabId, url}) {
  if (!(0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.isTopLevelFrameId)(frameId))
    return;

  let opener = await potentialPopups.get(tabId);
  if (opener)
    await checkPotentialPopup(tabId, url, opener);
}

async function onCompleted({frameId, tabId, url}) {
  if (!(0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.isTopLevelFrameId)(frameId) || url == _frame_state_js__WEBPACK_IMPORTED_MODULE_6__.BLANK_PAGE_URL)
    return;

  let opener = await potentialPopups.get(tabId);
  if (opener) {
    await checkPotentialPopup(tabId, url, opener);
    await potentialPopups.remove(tabId);
  }
}

async function onTabRemoved({tabId}) {
  await potentialPopups.remove(tabId);
}

async function onPopup({tabId, url, sourceTabId, sourceFrameId}) {
  let openerPromise = (async() => {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_4__.default.start();
    let frame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.getFrameInfo)(sourceTabId, sourceFrameId);

    if (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT)
      return;

    let opener = {
      tabId: sourceTabId,
      specificOnly: Boolean(frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICBLOCK),
      docDomain: frame.hostname,
      sitekey: frame.sitekey
    };
    return opener;
  })();

  potentialPopups.set(tabId, openerPromise);

  let opener = await openerPromise;
  if (opener)
    await checkPotentialPopup(tabId, url, opener);
}

/**
 * Starts blocking popups. Must be called in the first turn of the
 * event loop.
 */
function start() {
  potentialPopups = new PotentialPopupMap();

  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onCreatedNavigationTarget.addListener(onPopup);
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onBeforeRequest.addListener(
    onPopupURLChanged,
    {
      urls: ["http://*/*", "https://*/*"],
      types: ["main_frame"]
    }
  );
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onBeforeNavigate.addListener(onPopupURLChanged);
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onCommitted.addListener(onPopupURLChanged);
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onCompleted.addListener(onCompleted);
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.onRemoved.addListener(onTabRemoved);
}


/***/ }),

/***/ "./sdk/api/prefs.js":
/*!**************************!*\
  !*** ./sdk/api/prefs.js ***!
  \**************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_760518__) => {

"use strict";
__nested_webpack_require_760518__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_760518__.d(__webpack_exports__, {
/* harmony export */   "MIGRATED_TO_MV2": () => (/* binding */ MIGRATED_TO_MV2),
/* harmony export */   "MIGRATED_TO_MV3": () => (/* binding */ MIGRATED_TO_MV3),
/* harmony export */   "defaults": () => (/* binding */ defaults),
/* harmony export */   "Prefs": () => (/* binding */ Prefs),
/* harmony export */   "awaitSavingComplete": () => (/* binding */ awaitSavingComplete),
/* harmony export */   "migratePrefs": () => (/* binding */ migratePrefs),
/* harmony export */   "init": () => (/* binding */ init)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_760518__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_events_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_760518__(/*! adblockpluscore/lib/events.js */ "./node_modules/adblockpluscore/lib/events.js");
/* harmony import */ var _io_idb_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_760518__(/*! ./io-idb.js */ "./sdk/api/io-idb.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */





const MIGRATED_TO_MV2 = 0;
const MIGRATED_TO_MV3 = 1;

const defaults = Object.create({
  analytics: {trustedHosts: ["adblockplus.org",
                             "notification.adblockplus.org",
                             "easylist-downloads.adblockplus.org"]},
  rule_id_to_filter_text: [],
  dynamic_filters: [],
  notificationdata: {},
  notifications_ignoredcategories: [],
  notificationurl: "https://notification.adblockplus.org/notification.json",
  notifications_initial_delay: 1000, // 1 s
  patternsbackupinterval: 24,
  patternsbackups: 0,
  savestats: false,
  show_statsinpopup: true,
  subscriptions_autoupdate: true,
  subscriptions_fallbackerrors: 5,
  subscriptions_fallbackurl: "https://adblockplus.org/getSubscription?version=%VERSION%&url=%SUBSCRIPTION%&downloadURL=%URL%&error=%ERROR%&responseStatus=%RESPONSESTATUS%",
  subscriptions_initial_delay: 1000, // 1 s
  migration_filter_errors: [],
  migration_subscription_errors: [],
  migration_state: MIGRATED_TO_MV2,
  last_reporting_check_timestamp: 0
});

let Prefs = {
  on(preference, callback) {
    eventEmitter.on(preference, callback);
  },
  off(preference, callback) {
    eventEmitter.off(preference, callback);
  }
};

const KEY_PREFIX = "abp:pref:";

let eventEmitter = new adblockpluscore_lib_events_js__WEBPACK_IMPORTED_MODULE_1__.EventEmitter();
let overrides = new Map();
let initializationPromise;

function keyToPref(key) {
  return key.startsWith(KEY_PREFIX) ? key.substr(KEY_PREFIX.length) : null;
}

function prefToKey(pref) {
  return `${KEY_PREFIX}${pref}`;
}

let activeSaveActions = new Set();

function trackSaving(savePromise) {
  activeSaveActions.add(savePromise);
  savePromise.finally(() => activeSaveActions.delete(savePromise));
  return savePromise;
}

async function awaitSavingComplete() {
  if (Promise.allSettled) {
    await Promise.allSettled(activeSaveActions);
    return;
  }

  // Promise.allSettled isn't supported in oldest Firefox.
  // It was added in Firefox 71.
  for (let saveAction of activeSaveActions) {
    try {
      await saveAction;
    }
    catch (e) {
    }
  }
}

function addPreference(preference) {
  Object.defineProperty(Prefs, preference, {
    get() {
      if (overrides.has(preference))
        return overrides.get(preference);

      let defaultValue = defaults[preference];
      // Arrays and Objects are deeply copied
      // to avoid modifications of `defaults`
      return Array.isArray(defaultValue) ||
        (typeof defaultValue === "object" && defaultValue !== null) ?
          JSON.parse(JSON.stringify(defaultValue)) :
          defaultValue;
    },
    set(value) {
      let key = prefToKey(preference);
      if (value === defaults[preference]) {
        overrides.delete(preference);
        trackSaving(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.remove(key));
        return;
      }

      overrides.set(preference, value);
      trackSaving(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.set({[key]: value}));
    },
    enumerable: true
  });
}

async function migratePrefs(db) {
  return new Promise((resolve, reject) => {
    let tx = db.transaction(["prefs"], "readwrite");
    tx.oncomplete = () => resolve();
    tx.onerror = tx.onabort = event => reject(event.target.error);

    let prefsStore;
    try {
      prefsStore = tx.objectStore("prefs");
    }
    catch (e) {
      // no "prefs" object store
      return;
    }
    prefsStore.getAll().onsuccess = event => {
      for (let {name, value} of event.target.result)
        savePreference(name, value);
      prefsStore.clear();
    };
  });
}

function savePreference(name, value) {
  let key = prefToKey(name);
  overrides.set(name, value);
  trackSaving(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.set({[key]: value}));
}

async function loadPreferences() {
  let prefs = Object.keys(Object.getPrototypeOf(defaults));
  prefs.forEach(addPreference);

  let items = await webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.storage.local.get(prefs.map(prefToKey));
  for (let key in items)
    overrides.set(keyToPref(key), items[key]);
}

async function init() {
  if (!initializationPromise) {
    initializationPromise = (async() => {
      try {
        let db = (0,_io_idb_js__WEBPACK_IMPORTED_MODULE_2__.getDatabase)();
        await migratePrefs(db);
      }
      catch (e) {
        // db might be unavailable
      }

      await loadPreferences();
    })();
  }

  return initializationPromise;
}


/***/ }),

/***/ "./sdk/api/reporting-requester.js":
/*!****************************************!*\
  !*** ./sdk/api/reporting-requester.js ***!
  \****************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_767167__) => {

"use strict";
__nested_webpack_require_767167__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_767167__.d(__webpack_exports__, {
/* harmony export */   "getMatchedFilters": () => (/* binding */ getMatchedFilters)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_767167__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_767167__(/*! adblockpluscore/lib/recommendations.js */ "./node_modules/adblockpluscore/lib/recommendations.js");
/* harmony import */ var _id_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_767167__(/*! ./id-utils.js */ "./sdk/api/id-utils.js");
/* harmony import */ var _dnr_filters_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_767167__(/*! ./dnr-filters.js */ "./sdk/api/dnr-filters.js");
/* harmony import */ var adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_767167__(/*! adblockpluscore/lib/subscriptionClasses.js */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */







async function getMatchedFilters(tabId, minTimeStamp) {
  let filter = {};
  if (tabId)
    filter.tabId = tabId;
  if (minTimeStamp)
    filter.minTimeStamp = minTimeStamp;
  let rules = await _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.getMatchedRules(tabId || minTimeStamp ? filter : null);

  let filters = [];
  for (let ruleInfo of rules.rulesMatchedInfo) {
    if (ruleInfo.rule.rulesetId ==
        _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.DYNAMIC_RULESET_ID) {
      // dynamic rule
      ruleInfo.text = (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_3__.getFilterTextByRuleId)(ruleInfo.rule.ruleId);
      filters.push(ruleInfo);
    }
    else {
      // static rule
      let subscriptionId = ruleInfo.rule.rulesetId;
      let subscriptionInfo = Array.from((0,adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_1__.recommendations)())
        .find(x => x.id == subscriptionId);
      if (!subscriptionInfo)
        throw new Error(`Failed to find the subscription with id=${subscriptionId}`);

      let subscription = adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_4__.Subscription.fromURL(subscriptionInfo.url);
      let line = (0,_id_utils_js__WEBPACK_IMPORTED_MODULE_2__.decode)(ruleInfo.rule.ruleId).line - 1;
      // `-1` as we remove ABP header
      ruleInfo.text = subscription._filterText[line];
      filters.push(ruleInfo);
    }
  }

  return filters;
}


/***/ }),

/***/ "./sdk/api/reporting-scheduler.js":
/*!****************************************!*\
  !*** ./sdk/api/reporting-scheduler.js ***!
  \****************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_770711__) => {

"use strict";
__nested_webpack_require_770711__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_770711__.d(__webpack_exports__, {
/* harmony export */   "BUFFER": () => (/* binding */ BUFFER),
/* harmony export */   "getCheckInterval": () => (/* binding */ getCheckInterval),
/* harmony export */   "stop": () => (/* binding */ stop),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_770711__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_770711__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */




let callback;
let timer;
const BUFFER = 10000; // This is to protect against timing inaccuracies.

function getCheckInterval() {
  return (1000 *
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.GETMATCHEDRULES_QUOTA_INTERVAL * 60 /
    _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.MAX_GETMATCHEDRULES_CALLS_PER_INTERVAL) +
    BUFFER;
}

function schedule(intervalMillis) {
  // protection from the wallclock being updated
  let safeInterval = Math.min(Math.max(0, intervalMillis), 60000);
  timer = setTimeout(check, safeInterval);
}

async function check() {
  if (!timer)
    return;

  let lastCheckTimestamp = _prefs_js__WEBPACK_IMPORTED_MODULE_1__.Prefs.last_reporting_check_timestamp;
  let thisCheckTimestamp = Date.now();
  try {
    await callback(lastCheckTimestamp);
  }
  finally {
    _prefs_js__WEBPACK_IMPORTED_MODULE_1__.Prefs.last_reporting_check_timestamp = thisCheckTimestamp;
    schedule(getCheckInterval());
  }
}

async function start(checkCallback) {
  if (timer)
    return;

  callback = checkCallback;

  await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_1__.init)();

  // Due to service worker restarting behaviour it can happen
  // that we start requesting earlier than it is allowed by Chromium.
  // So we might need to delay the first check.
  let nextCheckTimestamp =
    _prefs_js__WEBPACK_IMPORTED_MODULE_1__.Prefs.last_reporting_check_timestamp + getCheckInterval();
  schedule(nextCheckTimestamp - Date.now());
}

function stop() {
  if (!timer)
    return;

  clearTimeout(timer);
  timer = null;
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * Start checking with predefined interval
   * @param {function} callback A function to be called for the check.
   * @returns {Promise} starting promise.
   */
  start
});


/***/ }),

/***/ "./sdk/api/reporting.js":
/*!******************************!*\
  !*** ./sdk/api/reporting.js ***!
  \******************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_774163__) => {

"use strict";
__nested_webpack_require_774163__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_774163__.d(__webpack_exports__, {
/* harmony export */   "resetClearCounter": () => (/* binding */ resetClearCounter),
/* harmony export */   "setLastCheckTimestamp": () => (/* binding */ setLastCheckTimestamp),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_774163__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var adblockpluscore_lib_analytics_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_774163__(/*! adblockpluscore/lib/analytics.js */ "./node_modules/adblockpluscore/lib/analytics.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_774163__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_774163__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_774163__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _request_filter_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_774163__(/*! ./request-filter.js */ "./sdk/api/request-filter.js");
/* harmony import */ var _subscribe_links_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_774163__(/*! ./subscribe-links.js */ "./sdk/api/subscribe-links.js");
/* harmony import */ var _reporting_scheduler_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_774163__(/*! ./reporting-scheduler.js */ "./sdk/api/reporting-scheduler.js");
/* harmony import */ var _reporting_requester_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_774163__(/*! ./reporting-requester.js */ "./sdk/api/reporting-requester.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */















let contentTypesMap = new Map();

for (let item of _request_filter_js__WEBPACK_IMPORTED_MODULE_5__.resourceTypes) {
  let contentTypeObject = Object.keys(adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes).find(key =>
    adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes[key] === item[1]
  );

  contentTypesMap.set(item[0].toLowerCase(), contentTypeObject.toLowerCase());
}

let clearCounter;
resetClearCounter();

function resetClearCounter() {
  clearCounter = 0;
}

let debugLastCheckTimestamp;

function setLastCheckTimestamp(timeStamp) {
  debugLastCheckTimestamp = timeStamp;
}

async function onCheck(lastCheckTimestamp) {
  try {
    let filterTextEventIndexMap = new Map();

    // Can't request per tabId due to request frequency limitation,
    // so passing `null` for `tabId` to have as much information as we can.
    // Filtering happens when each `onBlockableItem` listener is triggered.
    let usedLastCheckTimestamp;
    if (debugLastCheckTimestamp) {
      usedLastCheckTimestamp = debugLastCheckTimestamp;
      debugLastCheckTimestamp = null;
    }
    else {
      usedLastCheckTimestamp = lastCheckTimestamp;
    }

    let ruleInfoList = await (0,_reporting_requester_js__WEBPACK_IMPORTED_MODULE_8__.getMatchedFilters)(null, usedLastCheckTimestamp);
    ruleInfoList.sort((a, b) => a.timeStamp - b.timeStamp);
    // Assuming the DNR matched rules order corresponds to
    // filter engine matched filters events order.
    for (let ruleInfo of ruleInfoList) {
      let filter = adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_3__.Filter.fromText(ruleInfo.text);
      let events = (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_4__.getMatchedFilterEvents)(filter.text);
      // `ruleInfo.tabId = -1 is in some cases
      // ("tab is inactive" according to the documentation),
      // so we can't search/filter for tabId
      let event;
      if (events) {
        // The events are already sorted by time stamp,
        // so we can just request by DNR rule match index
        let eventIndex = filterTextEventIndexMap.get(filter.text);
        if (eventIndex == null)
          eventIndex = 0;
        else
          eventIndex++;
        filterTextEventIndexMap.set(filter.text, eventIndex);

        if (eventIndex < events.length)
          event = events[eventIndex];
        else
          event = null;
      }
      else {
        event = null;
      }

      if (event)
        (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_4__.emitLogItem)(event.details, filter, event.matchInfo);
    }
    // It can happen, that scheduler check happened too early,
    // eg. page loading is not finished or element hiding is not finished.
    // So we might need to wait for the next scheduler check.
    // If we clear matched MV2 events after every scheduler tick,
    // we will be unable to find them for the matched MV3 (DNR) rules
    // so we need them to survive at least 1 `clear()` call.
    // On other hand we need to actually clean it when we need
    // (eg. in the testing between the tests)
    if (clearCounter++ % 2 == 0)
      (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_4__.clearMatchedFilterEvents)();
  }
  catch (e) {
    console.error(e.message);
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * Returns the version of the first ever downloaded resource.
   * @return {string}
   * @see {@link https://gitlab.com/eyeo/adblockplus/abc/adblockpluscore/-/jobs/artifacts/0.6.0/file/build/docs/module-analytics-Analytics.html?job=docs#getFirstVersion|Adblock Plus core analytics documentation}
   * @external
   */
  getFirstVersion: adblockpluscore_lib_analytics_js__WEBPACK_IMPORTED_MODULE_1__.analytics.getFirstVersion,

  /**
  * @typedef {Object} FilterMatchInfo
  * @property {string|null} docDomain The hostname of the document that caused
  *   the request. This will be null for "main_frame" requests since those
  *   create the top-level document in the first place.
  * @property {?string} rewrittenUrl The name of the internal resource to which
  *   to rewrite the URL.
  * @property {?boolean} specificOnly Whether selectors from generic filters
  *   should be included.
  * @property {string} method The method used to match this filter. This can be
  *   the string "request", "header", "csp", "popup", "elemhide", "snippet",
  *   "allowing", or "unmatched".
  * @property {?string} allowingReason When the type in request details is
  *   undefined, this contains the reason why the request/frame got
  *   allowlisted. That is either "document", "elemhide", "genericblock",
  *   "generichide", or "extensionInitiated". "extensionInitiated" refers to any
  *   web requests initiated by a browser extension rather than a web page
  *   (those requests are not blockable).
  */

  /**
   * Emitted when any blockable item is matched.
   *
   * This includes both filters being applied on a document level and web
   * requests. Multiple events may be emitted for a document, one for each
   * filter being applied to the document. There will generally only be one
   * event emitted for each web request. The exception to this is CSP filters,
   * where multiple CSP filters may be applied to a request at the same time,
   * and an event will be emitted for each filter applied.
   * @event
   * @param {object|{frameId: number, tabId: number, url: string}} request
   *   Either
   *   the {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onBeforeRequest#details|onBeforeRequest details}
   *   object or the {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/onHeadersReceived#details|onHeadersReceived details}
   *   object from the web extensions API, or an object with the properties
   *   `frameId`, `tabId` and `url`.
   * @param {?Filter} filter The filter that matched, if any.
   * @param {FilterMatchInfo} matchInfo Extra information that might be
   *                                    relevant depending on the context.
   * @type {BlockableEventDispatcher<{request: object,
   *                                   filter: Filter,
   *                                   matchInfo: FilterMatchInfo}>}
   */
  onBlockableItem: new _diagnostics_js__WEBPACK_IMPORTED_MODULE_4__.BlockableEventDispatcher(),

  /**
   * Returns a mapping between resourceTypes and contentTypes.
   * @return {Map<string, string>}
   */
  contentTypesMap,

  /**
   * Emitted when a subscribe link is clicked on a web page.
   *
   * A subscribe link has a URL pointing to `https://subscribe.adblockplus.org/`
   * or starting with `abp:subscribe` (deprecated), followed by a query string
   * with a `location` parameter, and optionally a `title` parameter. Subscribe
   * links can only be used on certain trusted domains (including `localhost`).
   * @example
   * <a href="https://subscribe.adblockplus.org?location=http%3A%2F%2Flocalhost%2Flist.txt&title=Example">Example</a>
   * <a href="abp:subscribe?location=location=http%3A%2F%2Flocalhost%2Flist.txt&title=Example">Example (deprecated)</a>
   * @event
   * @param {string} url The subscription URL from the subscribe link
   *                     `location`'s parameter.
   * @param {string} title The subscription title from the subscribe link
   *                       `title`'s parameter.
   * @type {EventDispatcher<{url: string, title: string}>}
   */
  onSubscribeLinkClicked: _subscribe_links_js__WEBPACK_IMPORTED_MODULE_6__.onSubscribeLinkClicked,

  /**
   * @ignore
   * Start monitoring for the matched rules
   * @returns {Promise} starting promise.
   */
  async start() {
    if (!_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest)
      return;

    await _reporting_scheduler_js__WEBPACK_IMPORTED_MODULE_7__.default.start(onCheck);
  }
});


/***/ }),

/***/ "./sdk/api/request-filter.js":
/*!***********************************!*\
  !*** ./sdk/api/request-filter.js ***!
  \***********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_784958__) => {

"use strict";
__nested_webpack_require_784958__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_784958__.d(__webpack_exports__, {
/* harmony export */   "resourceTypes": () => (/* binding */ resourceTypes),
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_784958__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_784958__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_784958__(/*! adblockpluscore/lib/contentTypes.js */ "./node_modules/adblockpluscore/lib/contentTypes.js");
/* harmony import */ var adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_784958__(/*! adblockpluscore/lib/filterNotifier.js */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
/* harmony import */ var adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_784958__(/*! adblockpluscore/lib/url.js */ "./node_modules/adblockpluscore/lib/url.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_784958__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _frame_state_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_784958__(/*! ./frame-state.js */ "./sdk/api/frame-state.js");
/* harmony import */ var _errors_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_784958__(/*! ../errors.js */ "./sdk/errors.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_784958__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _sitekey_js__WEBPACK_IMPORTED_MODULE_9__ = __nested_webpack_require_784958__(/*! ./sitekey.js */ "./sdk/api/sitekey.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */














const EXTENSION_PROTOCOL = new URL(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.runtime.getURL("")).protocol;

let resourceTypes = new Map();
for (let type in adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes)
  resourceTypes.set(type.toLowerCase(), adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes[type]);
resourceTypes.set("sub_frame", adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.SUBDOCUMENT);
resourceTypes.set("beacon", adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.PING);
resourceTypes.set("imageset", adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.IMAGE);
resourceTypes.set("object_subrequest", adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.OBJECT);
resourceTypes.set("main_frame", adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT);

let typeSelectors = new Map([
  [adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.IMAGE, "img,input"],
  [adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.MEDIA, "audio,video"],
  [adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.SUBDOCUMENT, "frame,iframe,object,embed"],
  [adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.OBJECT, "object,embed"]
]);

let pendingAllowlistedRequests = new Set();
let pendingCspRequests = new Set();
/**
 * @type {Map<tabId, Map<frameId, details>>}
 */
let pendingDetails = new Map();

class BaseFilter {
  register() {
    if (!this.listener) {
      this.listener = this.filter.bind(this);
      this.event.addListener(this.listener, ...this.eventArgs);
    }
  }

  unregister() {
    if (this.listener) {
      this.event.removeListener(this.listener);
      this.listener = null;
    }
  }

  getFrameId(details) {
    // sub_frame requests are loading the iframe document itself, so
    // from our point of view the initiating frame is actually the
    // parent of the iframe.
    return details.type == "sub_frame" ? details.parentFrameId :
                                         details.frameId;
  }

  getParentFrameId(details) {
    if (details.type == "sub_frame") {
      // frameAncestors is exactly what we need, but it's only
      // available in Firefox so sometimes we just don't have what we
      // need :(
      if (!details.frameAncestors)
        return null;

      return details.frameAncestors.length > 1 ?
        details.frameAncestors[1].frameId : -1;
    }
    return details.parentFrameId;
  }

  getDocDomain(type, hostname) {
    return type == "main_frame" ? null : hostname;
  }

  getInitiator(details) {
    // Chrome calls it initiator, Firefox calls it documentUrl
    return details.initiator || details.documentUrl;
  }

  getDocumentUrl(details) {
    return details.documentUrl || details.initiator;
  }

  getFrameInfo(details) {
    let tabId = details.tabId;
    let frameId = this.getFrameId(details);
    let parentFrameId = this.getParentFrameId(details);
    let initiator = this.getInitiator(details);
    let documentUrl = this.getDocumentUrl(details);

    return (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.getFrameInfo)(tabId, frameId, {
      initiator,
      parentFrameId,
      documentUrl
    });
  }

  getContentType(details) {
    let contentType = resourceTypes.get(details.type) || adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.OTHER;
    if (contentType == adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT)
      return adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.OTHER;
    return contentType;
  }

  collapse(details) {
    let selector = typeSelectors.get(this.getContentType(details));
    let frameId = this.getFrameId(details);

    let sendCollapseMessage = () => {
      return webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.tabs.sendMessage(
        details.tabId,
        {type: "ewe:collapse", selector, url: details.url}, {frameId}
      );
    };

    if (selector && frameId != -1) {
      // Retrying to fix a connection error on Chromium 90
      sendCollapseMessage()
        .catch(() => (0,_errors_js__WEBPACK_IMPORTED_MODULE_7__.ignoreNoConnectionError)(sendCollapseMessage()));
    }
  }

  block(details, filter, matchInfo) {
    let value = (() => {
      if (typeof filter.rewrite == "string") {
        let rewrittenUrl = filter.rewriteUrl(details.url);
        // If no rewrite happened (error, different origin), we'll
        // return undefined in order to avoid an "infinite" loop.
        if (rewrittenUrl != details.url) {
          matchInfo.rewrittenUrl = rewrittenUrl;
          return {redirectUrl: rewrittenUrl};
        }
      }
      else {
        this.collapse(details);
        return {cancel: true};
      }
    })();
    (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_8__.logItem)(details, filter, matchInfo);
    return value;
  }

  allow(details, filter, matchInfo) {
    pendingAllowlistedRequests.add(details.requestId);
    (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_8__.logItem)(details, filter, matchInfo);
  }

  match(details, frame, specificOnly, contentType, docDomain) {
    // This does nothing in BaseFilter, but should be overridden in
    // any child class that uses the default implementation of
    // BaseFilter.filter.
  }

  filter(details) {
    if (pendingAllowlistedRequests.has(details.requestId))
      return;

    let initiator = this.getInitiator(details);
    if (initiator && initiator.startsWith(EXTENSION_PROTOCOL)) {
      // These are requests sent by an extension, so if we block these
      // we could block our own ability to update subscriptions etc.
      return this.allow(details, null, {
        method: "allowing", allowingReason: "extensionInitiated"
      });
    }

    let frame = this.getFrameInfo(details);
    if (!frame)
      return;

    let specificOnly = (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICBLOCK) != 0;
    let docDomain = this.getDocDomain(details.type, frame.hostname);
    if (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT) {
      return this.allow(details, frame.allowingDocumentFilter, {
        docDomain,
        method: "allowing",
        specificOnly
      });
    }

    let contentType = this.getContentType(details);

    return this.match(details, frame, specificOnly, contentType, docDomain);
  }
}

class RequestFilter extends BaseFilter {
  getDocumentUrl(details) {
    // We can be more idealistic here since we are doing this check
    // again later if we don't have enough info. documentUrl SHOULD
    // only ever be documentUrl (not initiator).
    return details.documentUrl;
  }

  getFrameInfo(details) {
    let frame = super.getFrameInfo(details);

    // Chromium-based browsers sometimes emit onBeforeRequest events
    // for resources on a frame before we get the onCommitted event
    // for the frame itself. This could mean that we're missing some
    // frame-level allowlisting filters, and can't actually make a
    // blocking decision yet. We only do this wait in the
    // onBeforeRequest filter because we can still do the blocking /
    // allowing when we have all the necessary info later in the
    // onHeadersReceived event.
    //
    // As an aside, if in the future we only needed to support Firefox
    // here, Firefox supports asynchronous blocking responses in the
    // webRequest API.
    if (frame) {
      // We might be missing sitekeys if we haven't received headers yet.
      if (!frame.headersReceived)
        return null;

      // A wrong URL likely means that we've navigated to a new page
      // and frame-state hasn't caught up yet.
      let {documentUrl, initiator} = details;
      if ((documentUrl && frame.url != documentUrl) ||
         (initiator && frame.hostname != (0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_4__.parseURL)(initiator).hostname))
        return null;
    }

    return frame;
  }

  match(details, frame, specificOnly, contentType, docDomain) {
    let filter = _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.defaultMatcher.match(
      details.url, contentType, docDomain, frame.sitekey, specificOnly, true
    );
    if (filter) {
      let matchInfo = {docDomain, specificOnly, method: "request"};
      if (filter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.BlockingFilter)
        return this.block(details, filter, matchInfo);
      return this.allow(details, filter, matchInfo);
    }
  }
}

RequestFilter.prototype.event = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onBeforeRequest;
RequestFilter.prototype.eventArgs = [
  {
    types: Object.values(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.ResourceType)
                 .filter(type => type != "main_frame"),
    urls: ["http://*/*", "https://*/*", "ws://*/*", "wss://*/*"]
  },
  ["blocking"]
];

class MatchedFilterObserver extends RequestFilter {
  defer(details) {
    let frameIdToDetailsListMap = pendingDetails.get(details.tabId);
    if (!frameIdToDetailsListMap) {
      frameIdToDetailsListMap = new Map();
      pendingDetails.set(details.tabId, frameIdToDetailsListMap);
    }
    let detailsList = frameIdToDetailsListMap.get(details.frameId);
    if (!detailsList) {
      detailsList = [];
      frameIdToDetailsListMap.set(details.frameId, detailsList);
    }
    detailsList.push(details);
  }

  getFrameInfo(details) {
    let frame = super.getFrameInfo(details);
    if (!frame)
      this.defer(details);
    return frame;
  }
}

MatchedFilterObserver.prototype.event = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onBeforeRequest;
MatchedFilterObserver.prototype.eventArgs = [
  {
    types: Object.values(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.ResourceType)
                 .filter(type => type != "main_frame"),
    urls: ["http://*/*", "https://*/*", "ws://*/*", "wss://*/*"]
  }
];

class HeaderFilter extends BaseFilter {
  match(details, frame, specificOnly, contentType, docDomain) {
    let matcher = _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.defaultMatcher;

    // This is a repeat of the RequestFilter check, in case it was
    // skipped due to not having enough frame information at the time.
    let requestFilter = matcher.match(
      details.url, contentType, docDomain, frame.sitekey, specificOnly, true
    );
    if (requestFilter) {
      let requestMatchInfo = {docDomain, specificOnly, method: "request"};
      if (requestFilter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.BlockingFilter)
        return this.block(details, requestFilter, requestMatchInfo);
      return this.allow(details, requestFilter, requestMatchInfo);
    }

    let matchInfo = {docDomain, specificOnly, method: "header"};
    let typeMask = adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.HEADER | contentType;
    let allowingFilter = matcher.match(details.url, typeMask, docDomain,
                                       frame.sitekey, specificOnly, true);

    if (allowingFilter && allowingFilter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.AllowingFilter)
      return this.allow(details, allowingFilter, matchInfo);

    let matches = matcher.search(details.url, typeMask, docDomain,
                                 frame.sitekey, specificOnly, "blocking");

    let filter = matches.blocking.find(blockingFilter => {
      return blockingFilter.filterHeaders(details.responseHeaders);
    });

    if (filter)
      return this.block(details, filter, matchInfo);
  }
}

HeaderFilter.prototype.event = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onHeadersReceived;
HeaderFilter.prototype.eventArgs = [
  {
    types: Object.values(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.ResourceType)
                 .filter(type => type != "main_frame"),
    urls: ["http://*/*", "https://*/*"]
  },
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest ? ["responseHeaders"] : ["blocking", "responseHeaders"]
];

class CSPFilter extends BaseFilter {
  filter(details) {
    let {requestId, tabId, frameId, parentFrameId, responseHeaders, url, type} =
        details;

    if (pendingAllowlistedRequests.has(requestId))
      return;

    let initiator = this.getInitiator(details);
    if (initiator && initiator.startsWith(EXTENSION_PROTOCOL)) {
      // These are requests sent by an extension, so if we block these
      // we could block our own ability to update subscriptions etc.
      return this.allow(details, null, {
        method: "allowing", allowingReason: "extensionInitiated"
      });
    }

    let parentFrame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.getFrameInfo)(tabId, parentFrameId);
    let {hostname: parentHostname, sitekey: parentSitekey} = parentFrame || {};
    let matcher = _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.defaultMatcher;

    let urlInfo = (0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_4__.parseURL)(url);
    let hostname = parentHostname || urlInfo.hostname;
    let sitekey = (0,_sitekey_js__WEBPACK_IMPORTED_MODULE_9__.setSitekeyFromHeaders)(
      tabId, frameId, url, responseHeaders
    ) || parentSitekey;

    let specificOnlyFilter = matcher.match(
      url, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICBLOCK, hostname, sitekey
    );
    let documentFilter = matcher.match(
      url, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.DOCUMENT, hostname, sitekey
    );
    let specificOnly = !!specificOnlyFilter;

    if (documentFilter) {
      return this.allow(details, documentFilter, {
        docDomain: this.getDocDomain(type, urlInfo.hostname),
        method: "allowing",
        specificOnly
      });
    }

    let docDomain =
      this.getDocDomain(type, parentHostname);
    let typeMask = adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.CSP | this.getContentType(details);
    let matchInfo = {docDomain: docDomain || urlInfo.hostname,
                     specificOnly, method: "csp"};

    let allowingFilter = matcher.match(url, typeMask, docDomain,
                                       sitekey, specificOnly, true);
    if (allowingFilter && allowingFilter instanceof adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_1__.AllowingFilter)
      return this.allow(details, allowingFilter, matchInfo);

    let matches = matcher.search(url, typeMask, docDomain,
                                 sitekey, specificOnly, "blocking");

    if (matches.blocking.length > 0) {
      pendingCspRequests.add(requestId);
      for (let filter of matches.blocking) {
        (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_8__.logItem)(details, filter, matchInfo);
        responseHeaders.push(
          {name: "Content-Security-Policy", value: filter.csp}
        );
      }
    }

    return {responseHeaders};
  }
}

CSPFilter.prototype.event = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onHeadersReceived;
CSPFilter.prototype.eventArgs = [
  {
    types: ["main_frame", "sub_frame"],
    urls: ["http://*/*", "https://*/*"]
  },
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest ? ["responseHeaders"] : ["blocking", "responseHeaders"]
];

class RequestCompletionFilter extends BaseFilter {
  filter(details) {
    let {requestId, tabId, frameId, parentFrameId, url, type} = details;
    let wasAllowlisted = pendingAllowlistedRequests.delete(requestId);
    let wasCsp = pendingCspRequests.delete(requestId);
    if (wasAllowlisted || wasCsp)
      return;

    if (type == "main_frame" || type == "sub_frame") {
      // for these two types, it's unreliable if frame is there or not
      // yet. The request could be completed before or after the new
      // frame is committed.
      let parentFrame = (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.getFrameInfo)(tabId, parentFrameId);
      let {hostname: parentHostname, sitekey: parentSitekey} =
          parentFrame || {};

      let hostname = parentHostname || (0,adblockpluscore_lib_url_js__WEBPACK_IMPORTED_MODULE_4__.parseURL)(url).hostname;
      let sitekey = (0,_sitekey_js__WEBPACK_IMPORTED_MODULE_9__.getSitekey)(tabId, frameId, url) || parentSitekey;
      let matcher = _core_js__WEBPACK_IMPORTED_MODULE_5__.filterEngine.defaultMatcher;
      let specificOnlyFilter = matcher.match(
        url, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICBLOCK, hostname, sitekey
      );
      let specificOnly = !!specificOnlyFilter;

      if ((0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.isTopLevelFrameId)(frameId)) {
        let popupFilter = matcher.match(
          url, adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.POPUP, hostname, sitekey, specificOnly
        );
        if (popupFilter)
          return;
      }
      let matchInfo = {
        docDomain: this.getDocDomain(type, hostname),
        method: "unmatched",
        specificOnly
      };
      (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_8__.logItem)(details, null, matchInfo);
    }
    else {
      let frame = this.getFrameInfo(details);
      if (!frame)
        return;

      let specificOnly = (frame.allowlisted & adblockpluscore_lib_contentTypes_js__WEBPACK_IMPORTED_MODULE_2__.contentTypes.GENERICBLOCK) != 0;
      let matchInfo = {
        docDomain: this.getDocDomain(type, frame.hostname),
        method: "unmatched",
        specificOnly
      };
      (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_8__.logItem)(details, null, matchInfo);
    }
  }
}

RequestCompletionFilter.prototype.event = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onCompleted;
RequestCompletionFilter.prototype.eventArgs = [
  {
    types: Object.values(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.ResourceType),
    urls: ["http://*/*", "https://*/*", "ws://*/*", "wss://*/*"]
  }
];

class RequestErrorFilter extends BaseFilter {
  filter(details) {
    pendingAllowlistedRequests.delete(details.requestId);
    pendingCspRequests.delete(details.requestId);
  }
}

RequestErrorFilter.prototype.event = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.onErrorOccurred;
RequestErrorFilter.prototype.eventArgs = [
  {
    types: Object.values(webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.ResourceType),
    urls: ["http://*/*", "https://*/*", "ws://*/*", "wss://*/*"]
  }
];

let matchedFiltersObserver = new MatchedFilterObserver();

let filters = webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest ? [
  matchedFiltersObserver,
  new CSPFilter(),
  new RequestCompletionFilter(),
  new RequestErrorFilter()
] : [
  new RequestFilter(),
  new HeaderFilter(),
  new CSPFilter(),
  new RequestCompletionFilter(),
  new RequestErrorFilter()
];

function onTabRemoved(tabId) {
  pendingDetails.delete(tabId);
  (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_8__.clearMatchedFilterEvents)(tabId);
}

function onFrameInfo(tabId, frameId) {
  let frameIdToDetailsListMap = pendingDetails.get(tabId);
  if (!frameIdToDetailsListMap)
    return;

  let detailsList = frameIdToDetailsListMap.get(frameId);
  if (!detailsList)
    return;

  for (let details of detailsList)
    matchedFiltersObserver.filter(details);

  frameIdToDetailsListMap.delete(frameId);
  if (frameIdToDetailsListMap.size == 0)
    pendingDetails.delete(tabId);
}

function onBeforeNavigate() {
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onBeforeNavigate.removeListener(onBeforeNavigate);
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webRequest.handlerBehaviorChanged();
}

function onFilterChange() {
  webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.webNavigation.onBeforeNavigate.addListener(onBeforeNavigate);
}

const FILTER_EVENTS = ["subscription.added",
                       "subscription.removed",
                       "subscription.updated",
                       "subscription.disabled",
                       "filter.added",
                       "filter.removed",
                       "filterState.enabled"];

/**
 * Starts filtering requests. Must only be called after filter engine and
 * frame state are initialized.
 */
function start() {
  if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
    (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.addOnFrameInfoListener)(onFrameInfo);
    (0,_frame_state_js__WEBPACK_IMPORTED_MODULE_6__.addOnTabRemovedListener)(onTabRemoved);
  }

  for (let filter of filters)
    filter.register();

  for (let event of FILTER_EVENTS) {
    if (!adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_3__.filterNotifier.listeners(event).includes(onFilterChange))
      adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_3__.filterNotifier.on(event, onFilterChange);
  }
}


/***/ }),

/***/ "./sdk/api/sitekey.js":
/*!****************************!*\
  !*** ./sdk/api/sitekey.js ***!
  \****************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_809179__) => {

"use strict";
__nested_webpack_require_809179__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_809179__.d(__webpack_exports__, {
/* harmony export */   "addListener": () => (/* binding */ addListener),
/* harmony export */   "getSitekey": () => (/* binding */ getSitekey),
/* harmony export */   "_getSitekeySignature": () => (/* binding */ _getSitekeySignature),
/* harmony export */   "_setSitekey": () => (/* binding */ _setSitekey),
/* harmony export */   "clearAllSitekeys": () => (/* binding */ clearAllSitekeys),
/* harmony export */   "clearTabSitekeys": () => (/* binding */ clearTabSitekeys),
/* harmony export */   "setSitekeyFromHeaders": () => (/* binding */ setSitekeyFromHeaders),
/* harmony export */   "merge": () => (/* binding */ merge),
/* harmony export */   "_loadSitekeys": () => (/* binding */ _loadSitekeys),
/* harmony export */   "_doSaveSitekeys": () => (/* binding */ _doSaveSitekeys),
/* harmony export */   "_saveSitekeys": () => (/* binding */ _saveSitekeys),
/* harmony export */   "_awaitSavingComplete": () => (/* binding */ _awaitSavingComplete),
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var adblockpluscore_lib_rsa_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_809179__(/*! adblockpluscore/lib/rsa.js */ "./node_modules/adblockpluscore/lib/rsa.js");
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_809179__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var _browser_features_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_809179__(/*! ./browser-features.js */ "./sdk/api/browser-features.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */





/**
 * All known sitekeys, that can be looked up by
 * `tabId`, and then by `frameId`, and then by `url`
 *  (`[tabId, [frameId, [url, {sitekey, signature}]]]]`).
 *
 * @type {Object}
 */
let sitekeys = {};
let startupPromise;
let listeners = [];

function notifySitekey(tabId, frameId, url, sitekey) {
  for (let listener of listeners)
    listener(tabId, frameId, url, sitekey);
}

function notifyAllSitekeys() {
  for (let [tabId, framesMap] of Object.entries(sitekeys)) {
    for (let [frameId, sitekeysMap] of Object.entries(framesMap)) {
      for (let [url, sitekeyInfo] of Object.entries(sitekeysMap))
        notifySitekey(tabId, frameId, url, sitekeyInfo.sitekey);
    }
  }
}

function onHeadersReceived({tabId, frameId, url, responseHeaders}) {
  let sitekey = setSitekeyFromHeaders(tabId, frameId, url, responseHeaders);
  if (sitekey)
    notifySitekey(tabId, frameId, url, sitekey);
}

function addListener(listener) {
  listeners.push(listener);
}

/**
 * Gets the stored sitekey for a given frame. Sitekeys are retrieved
 * from the headers of main_frame and sub_frame requests (the html
 * documents in tabs and iframes).
 * @param {number} tabId Id of the tab the frame is on.
 * @param {number} frameId Id of the frame on the tab.
 * @param {string} url Url for the frame.
 * @return {string|null|undefined} The sitekey if we have it, null if
 *   we've processed headers for this frame but it didn't have a
 *   sitekey, undefined if we haven't seen any headers for this frame.
 */
function getSitekey(tabId, frameId, url) {
  let sitekeysForTab = sitekeys[tabId];
  if (!sitekeysForTab)
    return null;
  let sitekeysForFrame = sitekeysForTab[frameId];
  if (!sitekeysForFrame)
    return null;
  let sitekeyInfo = sitekeysForFrame[url];
  return sitekeyInfo ? sitekeyInfo.sitekey : null;
}

function _getSitekeySignature(tabId, frameId, url) {
  return sitekeys[tabId][frameId][url].signature;
}

function _setSitekey(tabId, frameId, url, sitekey, signature) {
  let sitekeysForTab = sitekeys[tabId];
  if (!sitekeysForTab) {
    sitekeysForTab = {};
    sitekeys[tabId] = sitekeysForTab;
  }

  let sitekeysForFrame = sitekeysForTab[frameId];
  if (!sitekeysForFrame) {
    sitekeysForFrame = {};
    sitekeysForTab[frameId] = sitekeysForFrame;
  }

  sitekeysForFrame[url] = {sitekey, signature};
}

function clearAllSitekeys(save = true) {
  sitekeys = {};
  if (save)
    _saveSitekeys();
}

function clearTabSitekeys(tabId) {
  delete sitekeys[tabId];
  _saveSitekeys();
}

/**
 * Use the headers from an onHeadersReceived event for an main_frame
 * and sub_frame request to update our sitekey map. This also
 * validates the sitekey before storing.
 *
 * If there is no sitekey, this inserts a null entry in the sitekey
 * map so you can differentiate between not having a sitekey because
 * there wasn't one in the headers and because the headers haven't
 * been received yet.
 * @param {number} tabId Id of the tab the frame is on.
 * @param {number} frameId Id of the frame on the tab.
 * @param {string} url Url for the frame.
 * @param {webRequest.HttpHeaders} headers the HTTP response headers
 *   to check for a sitekey. See {@link webRequest API
 *   https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/webRequest/HttpHeaders}.
 * @return {string|null} The sitekey if it was found and is
 *   valid. Null if there was no valid sitekey.
 */
function setSitekeyFromHeaders(tabId, frameId, url, headers) {
  let sitekeyHeader = getSitekeyHeader(headers);
  let newSitekey = sitekeyHeader ? sitekeyHeader.sitekey : null;

  // If this sitekey is the same as the one we already have, we can
  // just leave the existing one. No need to do signature verification
  // since we've already checked this sitekey on this site.
  let existingSitekeyInfo = getSitekey(tabId, frameId, url);
  if (existingSitekeyInfo &&
      existingSitekeyInfo.sitekey &&
      newSitekey == existingSitekeyInfo.sitekey)
    return existingSitekeyInfo.sitekey;

  if (newSitekey && verifySitekey(newSitekey, sitekeyHeader.signature, url)) {
    _setSitekey(tabId, frameId, url, newSitekey, sitekeyHeader.signature);
    _saveSitekeys();
    return newSitekey;
  }

  // Inserting null here indicates that we've received headers for a
  // URL and it didn't have sitekeys (as opposed to not receiving
  // filters yet).
  _setSitekey(tabId, frameId, url, null, null);
  _saveSitekeys();
  return null;
}

function getSitekeyHeader(headers) {
  for (let header of headers) {
    if (header.name.toLowerCase() == "x-adblock-key" && header.value) {
      let parts = header.value.split("_");
      if (parts.length < 2)
        return null;

      return {
        sitekey: parts[0].replace(/=/g, ""),
        signature: parts[1]
      };
    }
  }
  return null;
}

function verifySitekey(sitekey, signature, url) {
  let urlObj = new URL(url);
  let data = [
    urlObj.pathname + urlObj.search,
    urlObj.host,
    navigator.userAgent
  ].join("\0");
  return (0,adblockpluscore_lib_rsa_js__WEBPACK_IMPORTED_MODULE_0__.verifySignatureSync)(sitekey, signature, data);
}

const STORAGE_KEY = "ewe:sitekeys";

function verifySitekeys(_sitekeys) {
  for (let [tabId, framesMap] of Object.entries(_sitekeys)) {
    for (let [frameId, sitekeysMap] of Object.entries(framesMap)) {
      for (let [url, sitekeyInfo] of Object.entries(sitekeysMap)) {
        try {
          let verified = sitekeyInfo.sitekey === null ||
              verifySitekey(sitekeyInfo.sitekey, sitekeyInfo.signature, url);

          if (!verified)
            delete sitekeysMap[url];
        }
        catch (e) {
          delete sitekeysMap[url];
        }
      }
      if (Object.keys(sitekeysMap).length == 0)
        delete framesMap[frameId];
    }
    if (Object.keys(framesMap).length == 0)
      delete _sitekeys[tabId];
  }
}

function merge(obj1, obj2) {
  if (obj1 instanceof Array)
    return [...obj1, ...obj2];

  if (!(obj1 instanceof Object))
    return obj2;

  let resultObj = {};

  for (let [key, obj1Values] of Object.entries(obj1))
    resultObj[key] = obj1Values;

  for (let [key, obj2Values] of Object.entries(obj2)) {
    let map1Values = resultObj[key];
    resultObj[key] = map1Values ? merge(map1Values, obj2Values) : obj2Values;
  }

  return resultObj;
}

async function _loadSitekeys(verify = true) {
  let persistObj = await _browser_js__WEBPACK_IMPORTED_MODULE_1__.default.storage.session.get(STORAGE_KEY);
  if (!persistObj || !persistObj[STORAGE_KEY])
    return;

  let savedSitekeys = persistObj[STORAGE_KEY];

  if (verify)
    verifySitekeys(savedSitekeys);

  // We might have `onHeadersReceived` triggered earlier than Filter Engine
  // loading is finished. Thus we might need to merge the saved and new
  // sitekey maps.
  sitekeys = merge(savedSitekeys, sitekeys);

  notifyAllSitekeys();
}

function _doSaveSitekeys() {
  let obj = {};
  obj[STORAGE_KEY] = sitekeys;
  trackSaving(_browser_js__WEBPACK_IMPORTED_MODULE_1__.default.storage.session.set(obj));
}

function _saveSitekeys() {
  if (!(0,_browser_features_js__WEBPACK_IMPORTED_MODULE_2__.isRunningInServiceWorker)())
    return;

  _doSaveSitekeys();
}

let activeSaveActions = new Set();

function trackSaving(savePromise) {
  activeSaveActions.add(savePromise);
  savePromise.finally(() => activeSaveActions.delete(savePromise));
  return savePromise;
}

async function _awaitSavingComplete() {
  if (Promise.allSettled) {
    await Promise.allSettled(activeSaveActions);
    return;
  }

  // Promise.allSettled isn't supported in oldest Firefox.
  // It was added in Firefox 71.
  for (let saveAction of activeSaveActions) {
    try {
      await saveAction;
    }
    catch (e) {
    }
  }
}

async function start() {
  if (!startupPromise) {
    _browser_js__WEBPACK_IMPORTED_MODULE_1__.default.webRequest.onHeadersReceived.addListener(
      onHeadersReceived,
      {
        urls: ["http://*/*", "https://*/*"],
        types: ["main_frame", "sub_frame"]
      },
      ["responseHeaders"]
    );

    startupPromise = ((0,_browser_features_js__WEBPACK_IMPORTED_MODULE_2__.isRunningInServiceWorker)() ?
      _loadSitekeys() : Promise.resolve(null));
  }

  await startupPromise;
}


/***/ }),

/***/ "./sdk/api/subscribe-links.js":
/*!************************************!*\
  !*** ./sdk/api/subscribe-links.js ***!
  \************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_819978__) => {

"use strict";
__nested_webpack_require_819978__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_819978__.d(__webpack_exports__, {
/* harmony export */   "subscribeLinkClicked": () => (/* binding */ subscribeLinkClicked),
/* harmony export */   "onSubscribeLinkClicked": () => (/* binding */ onSubscribeLinkClicked)
/* harmony export */ });
/* harmony import */ var _types_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_819978__(/*! ./types.js */ "./sdk/api/types.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



let dispatchFunction;

function subscribeLinkClicked(url, title) {
  if (dispatchFunction)
    dispatchFunction({url, title});
}

let onSubscribeLinkClicked = new _types_js__WEBPACK_IMPORTED_MODULE_0__.EventDispatcher(
  dispatch => {
    dispatchFunction = dispatch;
  },
  () => {
    dispatchFunction = null;
  }
);


/***/ }),

/***/ "./sdk/api/subscriptions-utils.js":
/*!****************************************!*\
  !*** ./sdk/api/subscriptions-utils.js ***!
  \****************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_821722__) => {

"use strict";
__nested_webpack_require_821722__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_821722__.d(__webpack_exports__, {
/* harmony export */   "rulesetExistsInManifest": () => (/* binding */ rulesetExistsInManifest),
/* harmony export */   "subscriptionFileExists": () => (/* binding */ subscriptionFileExists)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_821722__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



function rulesetExistsInManifest(rulesetId) {
  let manifest = _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getManifest();

  return manifest.declarative_net_request &&
    manifest.declarative_net_request.rule_resources &&
    manifest.declarative_net_request.rule_resources.find(
      ruleset => ruleset.id == rulesetId
    );
}

async function subscriptionFileExists(subscription, path) {
  let subscriptionPath = `${path}/${subscription.id}`;
  const url = _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getURL(subscriptionPath);
  try {
    const fetchResult = await fetch(url, {method: "HEAD"});
    return fetchResult.ok;
  }
  catch (error) {
    return false;
  }
}


/***/ }),

/***/ "./sdk/api/subscriptions-validator.js":
/*!********************************************!*\
  !*** ./sdk/api/subscriptions-validator.js ***!
  \********************************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_823880__) => {

"use strict";
__nested_webpack_require_823880__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_823880__.d(__webpack_exports__, {
/* harmony export */   "validate": () => (/* binding */ validate)
/* harmony export */ });
/* harmony import */ var _subscriptions_utils_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_823880__(/*! ./subscriptions-utils.js */ "./sdk/api/subscriptions-utils.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



async function validate(bundledSubscriptions,
                               bundledSubscriptionsPath) {
  let warnings = [];

  for (let subscription of bundledSubscriptions) {
    // Circumvention subscriptions don't count.
    if (subscription.type == "circumvention")
      continue;

    let fileExists = await (0,_subscriptions_utils_js__WEBPACK_IMPORTED_MODULE_0__.subscriptionFileExists)(
      subscription, bundledSubscriptionsPath);
    if (!fileExists)
      warnings.push(`No subscription content file for ID=${subscription.id}`);

    if (!(0,_subscriptions_utils_js__WEBPACK_IMPORTED_MODULE_0__.rulesetExistsInManifest)(subscription.id))
      warnings.push(`No ruleset with ID=${subscription.id} declared in the manifest`);
  }

  return warnings;
}


/***/ }),

/***/ "./sdk/api/subscriptions.js":
/*!**********************************!*\
  !*** ./sdk/api/subscriptions.js ***!
  \**********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_825970__) => {

"use strict";
__nested_webpack_require_825970__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_825970__.d(__webpack_exports__, {
/* harmony export */   "getDefaultSubscriptions": () => (/* binding */ getDefaultSubscriptions),
/* harmony export */   "validate": () => (/* binding */ validate),
/* harmony export */   "updateFilterText": () => (/* binding */ updateFilterText),
/* harmony export */   "migrate": () => (/* binding */ migrate),
/* harmony export */   "ensureDNRRulesetsEnabled": () => (/* binding */ ensureDNRRulesetsEnabled),
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var _browser_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_825970__(/*! ./browser.js */ "./sdk/api/webext-browser.js");
/* harmony import */ var _subscriptions_validator_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_825970__(/*! ./subscriptions-validator.js */ "./sdk/api/subscriptions-validator.js");
/* harmony import */ var _subscriptions_utils_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_825970__(/*! ./subscriptions-utils.js */ "./sdk/api/subscriptions-utils.js");
/* harmony import */ var adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_825970__(/*! adblockpluscore/lib/subscriptionClasses.js */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
/* harmony import */ var adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_825970__(/*! adblockpluscore/lib/filterNotifier.js */ "./node_modules/adblockpluscore/lib/filterNotifier.js");
/* harmony import */ var adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_825970__(/*! adblockpluscore/lib/recommendations.js */ "./node_modules/adblockpluscore/lib/recommendations.js");
/* harmony import */ var adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_825970__(/*! adblockpluscore/lib/filterClasses.js */ "./node_modules/adblockpluscore/lib/filterClasses.js");
/* harmony import */ var adblockpluscore_lib_filters_lists_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_825970__(/*! adblockpluscore/lib/filters/lists.js */ "./node_modules/adblockpluscore/lib/filters/lists.js");
/* harmony import */ var _info_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_825970__(/*! ./info.js */ "./sdk/api/info.js");
/* harmony import */ var _initializer_js__WEBPACK_IMPORTED_MODULE_9__ = __nested_webpack_require_825970__(/*! ./initializer.js */ "./sdk/api/initializer.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_10__ = __nested_webpack_require_825970__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _types_js__WEBPACK_IMPORTED_MODULE_11__ = __nested_webpack_require_825970__(/*! ./types.js */ "./sdk/api/types.js");
/* harmony import */ var _filters_js__WEBPACK_IMPORTED_MODULE_12__ = __nested_webpack_require_825970__(/*! ./filters.js */ "./sdk/api/filters.js");
/* harmony import */ var _io_js__WEBPACK_IMPORTED_MODULE_13__ = __nested_webpack_require_825970__(/*! ./io.js */ "./sdk/api/io.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_14__ = __nested_webpack_require_825970__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */




















const ACCEPTABLE_ADS_ID = "0798B6A2-94A4-4ADF-89ED-BEC112FC4C7F";
const ACCEPTABLE_ADS_MV2_URL = "https://easylist-downloads.adblockplus.org/exceptionrules.txt";
const ACCEPTABLE_ADS_MV3_URL = "https://easylist-downloads.adblockplus.org/v3/full/exceptionrules.txt";

const ACCEPTABLE_ADS_PRIVACY_ID = "F12E0801-A00B-49DE-B1E3-52C9C4F90C8C";
const ACCEPTABLE_ADS_PRIVACY_MV2_URL = "https://easylist-downloads.adblockplus.org/exceptionrules-privacy-friendly.txt";
const ACCEPTABLE_ADS_PRIVACY_MV3_URL = "https://easylist-downloads.adblockplus.org/v3/full/exceptionrules-privacy-friendly.txt";

function convertSubscription(subscription) {
  let {id, disabled, downloadStatus, homepage,
       version, lastDownload, lastSuccess,
       softExpiration, expires, title, url,
       downloadable, downloadCount} = subscription;

  let newSubscription = {
    id, enabled: !disabled,
    homepage, downloadable, title, url, downloadCount, version
  };

  if (downloadable) {
    let {synchronizer} = _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage;

    Object.assign(newSubscription, {
      downloading: synchronizer.isExecuting(url),
      version, downloadStatus, lastSuccess, lastDownload,
      softExpiration, expires, downloadCount
    });
  }

  return newSubscription;
}

function convertRecommendation({id, languages, title, requires, type, url,
                                // eslint-disable-next-line camelcase
                                mv2URL}) {
  if (!_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest)
    // In MV2 we have to switch the URL to be the mv2URL
    return {id, languages, title, requires, type, url: mv2URL};

  return {id, languages, title, requires, type, url, mv2URL};
}

function getSubscription(url) {
  let subscription = adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.Subscription.fromURL(url);

  if (_core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.hasSubscription(subscription) &&
      subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.RegularSubscription)
    return subscription;

  return null;
}

function makeListener(dispatch) {
  return subscription => {
    if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.RegularSubscription)
      dispatch(convertSubscription(subscription));
  };
}

function getDefaultSubscriptions(uiLanguage) {
  let hasCurrentLang = false;
  let hasDefaultLang = false;
  let hasAA = false;
  let hasAntiCV = false;

  if (!uiLanguage) {
    // https://bugs.chromium.org/p/chromium/issues/detail?id=1159438
    if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.i18n.getUILanguage)
      uiLanguage = _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.i18n.getUILanguage();
    else
      uiLanguage = navigator.language;
  }

  let currentLang = uiLanguage.split("-")[0];
  let defaultLang = (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getManifest()
                                    .default_locale || "en").split("_")[0];

  let adSubscriptions = [];
  let adSubscriptionsDefaultLang = [];
  let aaSubscriptions = [];
  let chosenSubscriptions = [];

  for (let subscription of (0,adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_5__.recommendations)()) {
    switch (subscription.type) {
      case "ads":
        if (subscription.languages.includes(currentLang)){
          hasCurrentLang = true;
          adSubscriptions.push(subscription);
        }

        if (subscription.languages.includes(defaultLang)) {
          hasDefaultLang = true;
          adSubscriptionsDefaultLang.push(subscription);
        }
        break;

      case "circumvention":
        chosenSubscriptions.push(subscription);
        hasAntiCV = true;
        break;

      case "allowing":
        aaSubscriptions.push(subscription);
        hasAA = true;
        break;
    }
  }

  if (adSubscriptions.length == 0)
    adSubscriptions = adSubscriptionsDefaultLang;

  // if we have the preferred AA in the list - use it only,
  // otherwise use all listed AA subscriptions
  let preferredAASubscription = aaSubscriptions.find(
    it => it.id == ACCEPTABLE_ADS_ID);
  if (preferredAASubscription)
    aaSubscriptions = [preferredAASubscription];
  chosenSubscriptions.unshift(...aaSubscriptions);

  chosenSubscriptions.unshift(...adSubscriptions);

  return {chosenSubscriptions, hasAA, hasAntiCV,
          hasCurrentLang, hasDefaultLang};
}

function shouldAddDefaultSubscriptions() {
  let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine;
  for (let subscription of filterStorage.subscriptions()) {
    if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.DownloadableSubscription &&
        subscription.url != ACCEPTABLE_ADS_MV2_URL &&
        subscription.type != "circumvention")
      return false;

    if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.SpecialSubscription &&
        subscription.filterCount > 0)
      return false;
  }

  return true;
}

async function enableRuleset(rulesetId) {
  if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest && (0,_subscriptions_utils_js__WEBPACK_IMPORTED_MODULE_2__.rulesetExistsInManifest)(rulesetId)) {
    await _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.updateEnabledRulesets({
      enableRulesetIds: [rulesetId]
    });
  }
}

async function disableRuleset(rulesetId) {
  if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest && (0,_subscriptions_utils_js__WEBPACK_IMPORTED_MODULE_2__.rulesetExistsInManifest)(rulesetId)) {
    await _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.updateEnabledRulesets({
      disableRulesetIds: [rulesetId]
    });
  }
}

async function getFilterText(subscription, path) {
  let subscriptionPath = `${path}/${subscription.id}`;
  let rawLines = (await (0,_io_js__WEBPACK_IMPORTED_MODULE_13__.readFileContent)(subscriptionPath));
  let {lines, error} = (0,adblockpluscore_lib_filters_lists_js__WEBPACK_IMPORTED_MODULE_7__.parseFilterList)(rawLines, true);
  // `true` as we need to preserve empty lines to find the line
  // when reporting filter hits (we encode line into DNR rule id).
  if (error)
    throw new Error(error);
  if (!lines)
    throw new Error("invalid filter list");
  lines.shift();
  return lines;
}

async function validate(bundledSubscriptions,
                               bundledSubscriptionsPath) {
  return (0,_subscriptions_validator_js__WEBPACK_IMPORTED_MODULE_1__.validate)(
    bundledSubscriptions, bundledSubscriptionsPath);
}

async function remove(url) {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

  let subscription = getSubscription(url);

  if (!subscription)
    throw new Error(`Subscription does not exist: ${url}`);

  _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.removeSubscription(subscription);

  await disableRuleset(subscription.id);
}

async function updateFilterText() {
  let removeUrls = [];

  for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.subscriptions()) {
    if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.RegularSubscription) {
      let subscriptionInfo = _info_js__WEBPACK_IMPORTED_MODULE_8__.addonBundledSubscriptions.find(
        x => x.url == subscription.url);

      if (subscriptionInfo) {
        let filterText = await getFilterText(
          subscriptionInfo, _info_js__WEBPACK_IMPORTED_MODULE_8__.addonBundledSubscriptionsPath);
        subscription.setFilterText(filterText);
      }
      else {
        removeUrls.push(subscription.url);
      }
    }
  }

  for (let url of removeUrls)
    await remove(url);
}

async function getDownloadable() {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

  let result = [];

  for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.subscriptions()) {
    if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.RegularSubscription)
      result.push(convertSubscription(subscription));
  }

  return result;
}

async function add(url, properties = {}) {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

  if (!adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.Subscription.isValidURL(url))
    throw new Error(`Invalid subscription URL provided: ${url}`);

  let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine;

  let subscription = adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.Subscription.fromURL(url);

  if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest) {
    let subscriptionInfo = _info_js__WEBPACK_IMPORTED_MODULE_8__.addonBundledSubscriptions.find(x => x.url == url);
    if (!subscriptionInfo)
      throw new Error(`Failed to find the subscription with URL=${url}`);

    if (!subscription.downloadable) {
      let filterText;
      try {
        filterText = await getFilterText(
          subscriptionInfo, _info_js__WEBPACK_IMPORTED_MODULE_8__.addonBundledSubscriptionsPath);
      }
      catch (e) {
        // We already warn if the file doesn't exist on startup, so
        // we can ignore an error loading the bundled file here.
      }

      if (filterText)
        subscription.setFilterText(filterText);
    }
  }
  await enableRuleset(subscription.id);

  if ("title" in properties)
    subscription.title = properties.title;
  if ("homepage" in properties)
    subscription.homepage = properties.homepage;
  if ("downloadCount" in properties)
    subscription.downloadCount = properties.downloadCount;
  if ("version" in properties)
    subscription.version = properties.version;
  if ("lastDownload" in properties)
    subscription.lastDownload = properties.lastDownload;

  filterStorage.addSubscription(subscription);

  if (!subscription.lastDownload)
    filterStorage.synchronizer.execute(subscription);
}

async function disable(url) {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

  let subscription = getSubscription(url);

  if (!subscription)
    throw new Error(`Subscription does not exist: ${url}`);

  subscription.disabled = true;

  await disableRuleset(subscription.id);
}

function migrationNeeded() {
  if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.runtime.getManifest().manifest_version == 2)
    return false;

  for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.subscriptions()) {
    // anti-cv subscriptions stay `DownloadableSubscriptions` even in MV3
    if (subscription.downloadable && subscription.type != "circumvention")
      return true;
  }

  return false;
}

function saveMigrationError(subscription, error) {
  let errors = _prefs_js__WEBPACK_IMPORTED_MODULE_14__.Prefs.migration_subscription_errors;
  errors.push({subscription, error});
  _prefs_js__WEBPACK_IMPORTED_MODULE_14__.Prefs.migration_subscription_errors = errors;
}

async function migrate() {
  if (!migrationNeeded())
    return;

  let downloadables = await getDownloadable();
  for (let downloadable of downloadables) {
    await remove(downloadable.url); // MV2 URL
    let subscriptionInfo = _info_js__WEBPACK_IMPORTED_MODULE_8__.addonBundledSubscriptions.find(
      it => it.mv2_url == downloadable.url);
    if (subscriptionInfo) {
      try {
        await add(subscriptionInfo.url, {
          downloadCount: downloadable.downloadCount,
          version: downloadable.version,
          lastDownload: downloadable.lastDownload
        });
        if (!downloadable.enabled)
          await disable(subscriptionInfo.url);
      }
      catch (e) {
        saveMigrationError(downloadable, e.message);
      }
    }
    else {
      saveMigrationError(
        downloadable,
        `Failed to find the subscription with URL=${downloadable.url}`);
    }
  }
}

async function ensureDNRRulesetsEnabled() {
  if (_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest) {
    let enabledItems = await _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest.getEnabledRulesets();

    for (let subscription of _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.subscriptions()) {
      if (!enabledItems.includes(subscription.id) && !subscription.disabled)
        enableRuleset(subscription.id);
    }
  }
}

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  /**
   * The URL of the Acceptable Ads subscription.
   * @type {string}
   */
  get ACCEPTABLE_ADS_URL() {
    return _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest ?
      ACCEPTABLE_ADS_MV3_URL :
      ACCEPTABLE_ADS_MV2_URL;
  },

  /**
   * The UUID of the Acceptable Ads subscription.
   * @type {string}
   */
  ACCEPTABLE_ADS_ID,

  /**
   * The URL of the Acceptable Ads
   * without third-party tracking subscription.
   * @type {string}
   */
  get ACCEPTABLE_ADS_PRIVACY_URL() {
    return _browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest ?
      ACCEPTABLE_ADS_PRIVACY_MV3_URL :
      ACCEPTABLE_ADS_PRIVACY_MV2_URL;
  },

  /**
   * The UUID of the Acceptable Ads without third-party tracking subscription.
   * @type {string}
   */
  ACCEPTABLE_ADS_PRIVACY_ID,

  /**
   * A resource that provides a list of filters that decide what to block.
   * @typedef {Object} Subscription
   * @property {boolean} downloadable Indicates whether this subscription is
   *                                  downloaded and updated over the network.
   *                                  If `false` the subscription is merely
   *                                  a container for user-defined filters.
   * @property {?boolean} downloading Indicates whether the subscription is
   *                                  currently downloading (downloadble
   *                                  subscriptions only).
   * @property {?string} downloadStatus The {@link https://gitlab.com/eyeo/adblockplus/abc/adblockpluscore/-/jobs/artifacts/0.6.0/file/build/docs/module-subscriptionClasses.DownloadableSubscription.html?job=docs#downloadStatus|status}
   *                                    of the most recent download attempt
   *                                    (downloadble subscriptions only).
   * @property {boolean} enabled Indicates whether this subscription will
   *                             be applied.
   * @property {?number} expires Epoch time when the subscription must be
   *                             downloaded (downloadble subscriptions
   *                             only).
   * @property {?string} homepage Website of the project that manages
   *                              this filter list.
   * @property {?number} lastDownload Epoch time when the subscription
   *                                  was last downloaded to your machine
   *                                  (downloadble subscriptions only).
   * @property {?number} lastSuccess Epoch time when this subscription was last
   *                                 successfully downloaded (downloadble
   *                                 subscriptions only).
   * @property {?number} softExpiration Epoch time for the next attempt to
   *                                    download the subscription. Can be
   *                                    updated even if the subscription was
   *                                    not downloaded. If `expires` is closer,
   *                                    then `expires` prevail. (downloadble
   *                                    subscriptions only).
   * @property {string} title The display name of the subscription.
   *                          If not provided, falls back to the URL.
   * @property {string} url Where the subscription can be found in plain text.
   *                        Used a the identifier.
   * @property {string} version The version provided by the subscription's
   *                            metadata. Defaults to '0' if not provided. It
   *                            might be set if the subscription is not
   *                            downloadable.
   */

  /**
   * Creates a new subscription from a given URL. The subscription also gets
   * synchronised if it had not been previously downloaded.
   * @param {string} url The URL of the subscription to be added.
   * @param {object} [properties] An object containing properties to be
   *                              set on the new subscription.
   * @param {string} [properties.title] The display name of the subscription.
   *                                    If not provided, falls back to the URL.
   * @param {string} [properties.homepage] Website of the project that
   *                                       manages this filter list.
   * @return {Promise}
   * @throws {Error} Invalid subscription URL provided.
   */
  add,

  /**
   * Adds a list of default subscriptions based on the provided bundled
   * subscriptions from the EWE.start() call.
   * Subscriptions are selected based on relevant language, type of
   * circumvention, and type of allowing.
   * @param {string} [uiLanguage] The relevant language used for
   * determining which subscriptions to add. If omitted,
   * browser.i18n.getUILanguage will be used. If
   * browser.i18n.getUILanguage is unavailable, navigator.language is
   * used.
   * @throws {Error} No default language subscription
   * @throws {Error} No current language subscription
   * @throws {Error} No anti-circumvention subscription
   * @throws {Error} No allowing subscription
   * @see {@link #start|start()}
   * @return {Promise}
   */
  async addDefaults(uiLanguage) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

    let subscriptions = [];

    if (shouldAddDefaultSubscriptions()) {
      let defaultSubscriptions = getDefaultSubscriptions(uiLanguage);
      if (!defaultSubscriptions.hasDefaultLang)
        throw Error("No default language subscription");

      if (!defaultSubscriptions.hasCurrentLang)
        throw Error("No current language subscription");

      if (!defaultSubscriptions.hasAntiCV)
        throw Error("No anti-circumvention subscription");

      if (!defaultSubscriptions.hasAA)
        throw Error("No allowing subscription");

      subscriptions.push(...defaultSubscriptions.chosenSubscriptions);
    }

    for (let subscription of subscriptions) {
      await this.add(_browser_js__WEBPACK_IMPORTED_MODULE_0__.default.declarativeNetRequest ?
        subscription.url : subscription.mv2URL);
    }
  },

  /**
   * Returns an array of subscription objects for all subscriptions that are
   * downloaded and updated over the network.
   * @return {Promise<Array<Subscription>>}
   */
  getDownloadable,

  /**
   * Returns an array of subscription objects for a given filter.
   * @param {string} text The filter rule for which to look.
   * @return {Promise<Array<Subscription>>}
   */
  async getForFilter(text) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

    return text ? Array.from(_core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine.filterStorage.subscriptions(text),
                             convertSubscription) : [];
  },

  /**
   * Returns the filter list of a given subscription URL.
   * @param {string} url The URL of the subscription.
   * @return {Promise<Array<Filter>>} Filters from the subscription.
   */
  async getFilters(url) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

    let subscription = getSubscription(url);
    if (subscription) {
      return Array.from(subscription.filterText(),
                        text => (0,_filters_js__WEBPACK_IMPORTED_MODULE_12__.convertFilter)(adblockpluscore_lib_filterClasses_js__WEBPACK_IMPORTED_MODULE_6__.Filter.fromText(text)));
    }

    return [];
  },

  /**
   * Checks if a subscription has been added.
   * @param {string} url The URL of the subscription to be checked.
   * @return {Promise<boolean>} True if a subscription has been added.
   * @throws {TypeError} Invalid URL provided.
   */
  async has(url) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

    return getSubscription(new URL(url).href) != null;
  },

  /**
   * Enables a previously disabled subscription. Has no effect otherwise.
   * @param {string} url The URL of the subscription to be enabled.
   * @return {Promise}
   * @throws {Error} Subscription does not exist.
   */
  async enable(url) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

    let subscription = getSubscription(url);

    if (!subscription)
      throw new Error(`Subscription does not exist: ${url}`);

    subscription.disabled = false;

    await enableRuleset(subscription.id);
  },

  /**
   * Disables a subscription so that it doesn't have any
   * effect until it gets enabled again.
   * @param {string} url The URL of the subscription to be disabled.
   * @return {Promise}
   * @throws {Error} Subscription does not exist.
   */
  disable,

  /**
   * Removes the subscription for the given URL.
   * It will no longer have any effect.
   * @param {string} url The URL of the subscription to be removed.
   * @return {Promise}
   * @throws {Error} Subscription does not exist.
   */
  remove,

  /**
   * Forces a new version of a subscription with the
   * given URL to be downloaded immediately.
   * @param {string} [url] The URL of the subscription to be synchronized.
   *   If omitted, all subscriptions will be synchronized.
   * @return {Promise} Resolves when syncing has been successfully
   *   triggered. Syncing may not be completed when this promise
   *   resolves.
   * @throws {Error} Subscription does not exist.
   */
  async sync(url) {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();

    let subscriptions = [];
    let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_10__.filterEngine;

    if (url) {
      let subscription = getSubscription(url);

      if (!subscription)
        throw new Error(`Subscription does not exist: ${url}`);

      subscriptions.push(subscription);
    }
    else {
      for (let subscription of filterStorage.subscriptions()) {
        if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.RegularSubscription)
          subscriptions.push(subscription);
      }
    }
    for (let subscription of subscriptions)
      filterStorage.synchronizer.execute(subscription, true);
  },

  /**
   * Defines the recommended filter subscriptions per language.
   * @typedef {Object} Recommendation
   * @property {string} id The identifier for this subscription.
   * @property {Array<string>} languages The languages that this recommendation
   *                                      would match to.
   * @property {string} title The display name of the recommended subscription.
   * @property {Array<string>} requires A list of subscriptions that this
   *                                    one depends on.
   * @property {Array<string>} includes A list of subscriptions that this
   *                                    one also contains.
   * @property {string} type The kind of content targeted by this
   *                         recommended subscription.
   * @property {string} url Where the recommended subscription can be found
   *                        in plain text.
   * @property {?string} mv2URL Where the recommended subscription can be found
   *                            for MV2 in plain text (Manifest V3 only).
   */

  /**
   * Returns an array of all recommended subscriptions.
   * @return {Array<Recommendation>}
   */
  getRecommendations() {
    return Array.from((0,adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_5__.recommendations)(), convertRecommendation);
  },

  /**
   * Returns an array of MV2 to MV3 migration errors and the related
   * subscription.
   * @return {Promise<array<Subscription, string>>} The migration errors.
   */
  async getMigrationErrors() {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();
    return _prefs_js__WEBPACK_IMPORTED_MODULE_14__.Prefs.migration_subscription_errors;
  },

  /**
   * Clears the migration errors.
   * @return {Promise}
   */
  async clearMigrationErrors() {
    await _initializer_js__WEBPACK_IMPORTED_MODULE_9__.default.start();
    _prefs_js__WEBPACK_IMPORTED_MODULE_14__.Prefs.migration_subscription_errors = [];
  },

  /**
   * Emitted when a new subscription is added.
   * @event
   * @type {EventDispatcher<Subscription>}
   */
  onAdded: new _types_js__WEBPACK_IMPORTED_MODULE_11__.EventDispatcher(dispatch => {
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("subscription.added", makeListener(dispatch));
  }),

  /**
   * Emitted when any property of the subscription has changed.
   * The name of the specific property is provided as a string, except
   * when the subscription has been updated, where it will be null.
   *
   * @event
   * @type {EventDispatcher<Subscription, string>}
   */
  onChanged: new _types_js__WEBPACK_IMPORTED_MODULE_11__.EventDispatcher(dispatch => {
    function makeChangeListener(property) {
      // This name differs between EWE and adblockpluscore.
      if (property == "disabled")
        property = "enabled";

      return subscription => {
        if (subscription instanceof adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_3__.RegularSubscription)
          dispatch(convertSubscription(subscription), property);
      };
    }

    let properties = ["disabled", "title", "homepage", "lastDownload",
                      "downloadStatus", "downloading"];
    for (let property of properties) {
      adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on(`subscription.${property}`,
                        makeChangeListener(property));
    }

    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("subscription.updated", makeChangeListener(null));
  }),

  /**
   * Emitted when a subscription is removed.
   * @event
   * @type {EventDispatcher<Subscription>}
   */
  onRemoved: new _types_js__WEBPACK_IMPORTED_MODULE_11__.EventDispatcher(dispatch => {
    adblockpluscore_lib_filterNotifier_js__WEBPACK_IMPORTED_MODULE_4__.filterNotifier.on("subscription.removed", makeListener(dispatch));
  })
});


/***/ }),

/***/ "./sdk/api/testing.js":
/*!****************************!*\
  !*** ./sdk/api/testing.js ***!
  \****************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_856713__) => {

"use strict";
__nested_webpack_require_856713__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_856713__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_856713__(/*! adblockpluscore/lib/subscriptionClasses.js */ "./node_modules/adblockpluscore/lib/subscriptionClasses.js");
/* harmony import */ var adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_856713__(/*! adblockpluscore/lib/recommendations.js */ "./node_modules/adblockpluscore/lib/recommendations.js");
/* harmony import */ var adblockpluscore_lib_notifications_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_856713__(/*! adblockpluscore/lib/notifications.js */ "./node_modules/adblockpluscore/lib/notifications.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_856713__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_856713__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/* harmony import */ var _debugging_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_856713__(/*! ./debugging.js */ "./sdk/api/debugging.js");
/* harmony import */ var _subscriptions_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_856713__(/*! ./subscriptions.js */ "./sdk/api/subscriptions.js");
/* harmony import */ var _info_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_856713__(/*! ./info.js */ "./sdk/api/info.js");
/* harmony import */ var _dnr_filters_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_856713__(/*! ./dnr-filters.js */ "./sdk/api/dnr-filters.js");
/* harmony import */ var _reporting_requester_js__WEBPACK_IMPORTED_MODULE_9__ = __nested_webpack_require_856713__(/*! ./reporting-requester.js */ "./sdk/api/reporting-requester.js");
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_10__ = __nested_webpack_require_856713__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/* harmony import */ var _reporting_js__WEBPACK_IMPORTED_MODULE_11__ = __nested_webpack_require_856713__(/*! ./reporting.js */ "./sdk/api/reporting.js");
/* harmony import */ var _sitekey_js__WEBPACK_IMPORTED_MODULE_12__ = __nested_webpack_require_856713__(/*! ./sitekey.js */ "./sdk/api/sitekey.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */

















/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({
  ..._sitekey_js__WEBPACK_IMPORTED_MODULE_12__, // everything exported from "sitekey.js"
  /**
   * @ignore
   */
  _getMatchedFilters: _reporting_requester_js__WEBPACK_IMPORTED_MODULE_9__.getMatchedFilters,

  /**
   * @ignore
   * Used internally. Sets the preference value.
   * @param {string} [key] Preference key
   * @param {Object} [value] Preference value
   */
  async _setPrefs(key, value) {
    await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_4__.init)();
    _prefs_js__WEBPACK_IMPORTED_MODULE_4__.Prefs[key] = value;
  },

  /**
   * @ignore
   * Used internally. Gets the preference value.
   * @param {string} [key] Preference key
   * @returns {Object} Preference value
   */
  async _getPrefs(key) {
    await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_4__.init)();
    return _prefs_js__WEBPACK_IMPORTED_MODULE_4__.Prefs[key];
  },

  /**
   * @ignore
   * Used internally. Restart the Synchronizer.
   */
  _restartSynchronizer() {
    let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine;
    filterStorage.synchronizer.stop();
    filterStorage.synchronizer.start();
  },

  /**
   * @ignore
   * Used internally. Sets the subscription property.
   * @param {string} [url] Subscription URL
   * @param {Object} [prototype] Object to set the subscription properties from.
   */
  async _setSubscriptionProperties(url, prototype) {
    let subscription = adblockpluscore_lib_subscriptionClasses_js__WEBPACK_IMPORTED_MODULE_0__.Subscription.fromURL(url);
    for (let property in prototype)
      subscription[property] = prototype[property];

    await _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine.filterStorage.saveToDisk();
    await _debugging_js__WEBPACK_IMPORTED_MODULE_5__.default.ensureEverythingHasSaved();
  },

  /**
   * @ignore
   * @param {Recommendation} subscriptions
   */
  _setSubscriptions(subscriptions) {
    (0,_info_js__WEBPACK_IMPORTED_MODULE_7__.setAddonInfo)({bundledSubscriptions: subscriptions,
                  bundledSubscriptionsPath: _info_js__WEBPACK_IMPORTED_MODULE_7__.addonBundledSubscriptionsPath});
    (0,adblockpluscore_lib_recommendations_js__WEBPACK_IMPORTED_MODULE_1__.setRecommendations)(subscriptions);
  },

  /**
   * @ignore
   */
  _setAddonInfo: _info_js__WEBPACK_IMPORTED_MODULE_7__.setAddonInfo,

  /**
   * @ignore
   * Clears all subscriptions and filters.
   * @return {Promise} A function that can be called to
   *                    restore the removed subscriptions and filters.
   */
  async _removeAllSubscriptions() {
    for (let subscription of await _subscriptions_js__WEBPACK_IMPORTED_MODULE_6__.default.getDownloadable())
      await _subscriptions_js__WEBPACK_IMPORTED_MODULE_6__.default.remove(subscription.url);

    await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_8__.removeDynamicFilters)();

    const {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_3__.filterEngine;
    for (let subscription of filterStorage.subscriptions())
      filterStorage.removeSubscription(subscription);
  },

  /**
   * @ignore
   */
  async _clearNotifications() {
    await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_4__.init)();
    for (let notification of adblockpluscore_lib_notifications_js__WEBPACK_IMPORTED_MODULE_2__.notifications._localNotifications)
      adblockpluscore_lib_notifications_js__WEBPACK_IMPORTED_MODULE_2__.notifications.removeNotification(notification);

    _prefs_js__WEBPACK_IMPORTED_MODULE_4__.Prefs.notificationdata = {};
    _prefs_js__WEBPACK_IMPORTED_MODULE_4__.Prefs.notifications_ignoredcategories = [];
    await (0,_prefs_js__WEBPACK_IMPORTED_MODULE_4__.awaitSavingComplete)();
  },

  async clearFilterMatches() {
    (0,_diagnostics_js__WEBPACK_IMPORTED_MODULE_10__.clearMatchedFilterEvents)();
    (0,_reporting_js__WEBPACK_IMPORTED_MODULE_11__.resetClearCounter)();
  },

  setLastCheckTimestamp: _reporting_js__WEBPACK_IMPORTED_MODULE_11__.setLastCheckTimestamp,
  setForceEnableTracing: _diagnostics_js__WEBPACK_IMPORTED_MODULE_10__.setForceEnableTracing
});


/***/ }),

/***/ "./sdk/api/types.js":
/*!**************************!*\
  !*** ./sdk/api/types.js ***!
  \**************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_863978__) => {

"use strict";
__nested_webpack_require_863978__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_863978__.d(__webpack_exports__, {
/* harmony export */   "BlockableEventDispatcher": () => (/* reexport safe */ _diagnostics_js__WEBPACK_IMPORTED_MODULE_0__.BlockableEventDispatcher),
/* harmony export */   "EventDispatcher": () => (/* binding */ EventDispatcher),
/* harmony export */   "FilterError": () => (/* binding */ FilterError)
/* harmony export */ });
/* harmony import */ var _diagnostics_js__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_863978__(/*! ./diagnostics.js */ "./sdk/api/diagnostics.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */



/**
 * The EventDispatcher class allows users to listen to
 * certain events that are emitted.
 * @hideconstructor
 * @param {function} initializer
 * @param {function} [finalizer]
 */
class EventDispatcher {
  constructor(initializer, finalizer) {
    this._listeners = new Set();
    this._initialized = false;

    let dispatch = (...args) => {
      for (let listener of this._listeners)
        listener(...args);
    };

    this._initialize = initializer.bind(null, dispatch);
    this._finalize = finalizer && finalizer.bind(null, dispatch);
  }

  /**
    * Attaches a listener function to an event. This listener will be called
    * when the event is emitted. Please note that in an MV3 context this has
    * to happen in the first turn of the event loop. This should happen when
    * your service worker starts.
    * @param {function} listener The user defined function that will be called
    *                            once the specified event is emitted.
    */
  addListener(listener) {
    if (!this._initialized) {
      this._initialize();
      this._initialized = true;
    }

    this._listeners.add(listener);
  }

  /**
    * Removes the added function. The listener will no longer be called
    * by the event.
    * @param {function} listener The user defined function to be removed.
    */
  removeListener(listener) {
    this._listeners.delete(listener);

    if (this._initialized && this._finalize && this._listeners.size == 0) {
      this._finalize();
      this._initialized = false;
    }
  }
}

/**
 * The result of parsing an invalid filter.
 * @property {string} type Either `invalid_filter` or `invalid_domain`.
 * @property {string} reason The reason why the filter is invalid.
 * @property {string?} option The filter option that made the filter invalid.
 * @param {string} type
 * @param {string} reason
 * @param {string?} option
 * @hideconstructor
 */
class FilterError extends Error {
  constructor(type, reason, option = null) {
    super(JSON.stringify({type, reason, option}));
    this.name = "FilterError";
    this.type = type;
    this.reason = reason;
    this.option = option;
  }
}


/***/ }),

/***/ "./sdk/api/webext-browser.js":
/*!***********************************!*\
  !*** ./sdk/api/webext-browser.js ***!
  \***********************************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_867662__) => {

"use strict";
__nested_webpack_require_867662__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_867662__.d(__webpack_exports__, {
/* harmony export */   "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_867662__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */

// reexport polyfill browser

/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__);


/***/ }),

/***/ "./sdk/errors.js":
/*!***********************!*\
  !*** ./sdk/errors.js ***!
  \***********************/
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __nested_webpack_require_869115__) => {

"use strict";
__nested_webpack_require_869115__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_869115__.d(__webpack_exports__, {
/* harmony export */   "ERROR_DUPLICATE_FILTERS": () => (/* binding */ ERROR_DUPLICATE_FILTERS),
/* harmony export */   "ERROR_FILTER_NOT_FOUND": () => (/* binding */ ERROR_FILTER_NOT_FOUND),
/* harmony export */   "ERROR_TOO_MANY_FILTERS": () => (/* binding */ ERROR_TOO_MANY_FILTERS),
/* harmony export */   "ignoreNoConnectionError": () => (/* binding */ ignoreNoConnectionError)
/* harmony export */ });
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */

const ERROR_NO_CONNECTION = "Could not establish connection. " +
      "Receiving end does not exist.";
const ERROR_CLOSED_CONNECTION = "A listener indicated an asynchronous " +
      "response by returning true, but the message channel closed before a " +
      "response was received";

const ERROR_DUPLICATE_FILTERS = "storage_duplicate_filters";
const ERROR_FILTER_NOT_FOUND = "filter_not_found";
const ERROR_TOO_MANY_FILTERS = "too_many_filters";

function ignoreNoConnectionError(promise) {
  return promise.catch(error => {
    if (typeof error == "object" &&
        (error.message == ERROR_NO_CONNECTION ||
         error.message == ERROR_CLOSED_CONNECTION))
      return;

    throw error;
  });
}


/***/ }),

/***/ "perf_hooks":
/*!***********************!*\
  !*** external "self" ***!
  \***********************/
/***/ ((module) => {

"use strict";
module.exports = self;

/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __nested_webpack_require_871467__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __nested_webpack_require_871467__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__nested_webpack_require_871467__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__nested_webpack_require_871467__.o(definition, key) && !__nested_webpack_require_871467__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/global */
/******/ 	(() => {
/******/ 		__nested_webpack_require_871467__.g = (function() {
/******/ 			if (typeof globalThis === 'object') return globalThis;
/******/ 			try {
/******/ 				return this || new Function('return this')();
/******/ 			} catch (e) {
/******/ 				if (typeof window === 'object') return window;
/******/ 			}
/******/ 		})();
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__nested_webpack_require_871467__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__nested_webpack_require_871467__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";
/*!**************************!*\
  !*** ./sdk/api/index.js ***!
  \**************************/
__nested_webpack_require_871467__.r(__webpack_exports__);
/* harmony export */ __nested_webpack_require_871467__.d(__webpack_exports__, {
/* harmony export */   "subscriptions": () => (/* reexport safe */ _subscriptions_js__WEBPACK_IMPORTED_MODULE_10__.default),
/* harmony export */   "filters": () => (/* reexport safe */ _filters_js__WEBPACK_IMPORTED_MODULE_14__.default),
/* harmony export */   "reporting": () => (/* reexport safe */ _reporting_js__WEBPACK_IMPORTED_MODULE_15__.default),
/* harmony export */   "debugging": () => (/* reexport safe */ _debugging_js__WEBPACK_IMPORTED_MODULE_16__.default),
/* harmony export */   "allowlisting": () => (/* reexport safe */ _allowlisting_js__WEBPACK_IMPORTED_MODULE_17__.default),
/* harmony export */   "testing": () => (/* reexport safe */ _testing_js__WEBPACK_IMPORTED_MODULE_18__.default),
/* harmony export */   "notifications": () => (/* reexport safe */ _notifications_js__WEBPACK_IMPORTED_MODULE_19__.notifications),
/* harmony export */   "snippets": () => (/* binding */ snippets),
/* harmony export */   "start": () => (/* binding */ start)
/* harmony export */ });
/* harmony import */ var webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__ = __nested_webpack_require_871467__(/*! webextension-polyfill */ "./node_modules/webextension-polyfill/dist/browser-polyfill.js");
/* harmony import */ var _initializer_js__WEBPACK_IMPORTED_MODULE_1__ = __nested_webpack_require_871467__(/*! ./initializer.js */ "./sdk/api/initializer.js");
/* harmony import */ var _message_responder_js__WEBPACK_IMPORTED_MODULE_2__ = __nested_webpack_require_871467__(/*! ./message-responder.js */ "./sdk/api/message-responder.js");
/* harmony import */ var _popup_blocker_background_page_js__WEBPACK_IMPORTED_MODULE_3__ = __nested_webpack_require_871467__(/*! ./popup-blocker-background-page.js */ "./sdk/api/popup-blocker-background-page.js");
/* harmony import */ var _popup_blocker_service_worker_js__WEBPACK_IMPORTED_MODULE_4__ = __nested_webpack_require_871467__(/*! ./popup-blocker-service-worker.js */ "./sdk/api/popup-blocker-service-worker.js");
/* harmony import */ var _request_filter_js__WEBPACK_IMPORTED_MODULE_5__ = __nested_webpack_require_871467__(/*! ./request-filter.js */ "./sdk/api/request-filter.js");
/* harmony import */ var _sitekey_js__WEBPACK_IMPORTED_MODULE_6__ = __nested_webpack_require_871467__(/*! ./sitekey.js */ "./sdk/api/sitekey.js");
/* harmony import */ var _content_filter_js__WEBPACK_IMPORTED_MODULE_7__ = __nested_webpack_require_871467__(/*! ./content-filter.js */ "./sdk/api/content-filter.js");
/* harmony import */ var _info_js__WEBPACK_IMPORTED_MODULE_8__ = __nested_webpack_require_871467__(/*! ./info.js */ "./sdk/api/info.js");
/* harmony import */ var _core_js__WEBPACK_IMPORTED_MODULE_9__ = __nested_webpack_require_871467__(/*! ./core.js */ "./sdk/api/core.js");
/* harmony import */ var _subscriptions_js__WEBPACK_IMPORTED_MODULE_10__ = __nested_webpack_require_871467__(/*! ./subscriptions.js */ "./sdk/api/subscriptions.js");
/* harmony import */ var _dnr_filters_js__WEBPACK_IMPORTED_MODULE_11__ = __nested_webpack_require_871467__(/*! ./dnr-filters.js */ "./sdk/api/dnr-filters.js");
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_12__ = __nested_webpack_require_871467__(/*! ./prefs.js */ "./sdk/api/prefs.js");
/* harmony import */ var _browser_features_js__WEBPACK_IMPORTED_MODULE_13__ = __nested_webpack_require_871467__(/*! ./browser-features.js */ "./sdk/api/browser-features.js");
/* harmony import */ var _filters_js__WEBPACK_IMPORTED_MODULE_14__ = __nested_webpack_require_871467__(/*! ./filters.js */ "./sdk/api/filters.js");
/* harmony import */ var _reporting_js__WEBPACK_IMPORTED_MODULE_15__ = __nested_webpack_require_871467__(/*! ./reporting.js */ "./sdk/api/reporting.js");
/* harmony import */ var _debugging_js__WEBPACK_IMPORTED_MODULE_16__ = __nested_webpack_require_871467__(/*! ./debugging.js */ "./sdk/api/debugging.js");
/* harmony import */ var _allowlisting_js__WEBPACK_IMPORTED_MODULE_17__ = __nested_webpack_require_871467__(/*! ./allowlisting.js */ "./sdk/api/allowlisting.js");
/* harmony import */ var _testing_js__WEBPACK_IMPORTED_MODULE_18__ = __nested_webpack_require_871467__(/*! ./testing.js */ "./sdk/api/testing.js");
/* harmony import */ var _notifications_js__WEBPACK_IMPORTED_MODULE_19__ = __nested_webpack_require_871467__(/*! ./notifications.js */ "./sdk/api/notifications.js");
/*
 * This file is part of eyeo's Web Extension Ad Blocking Toolkit (EWE),
 * Copyright (C) 2006-present eyeo GmbH
 *
 * EWE is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * EWE is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with EWE.  If not, see <http://www.gnu.org/licenses/>.
 */


























let snippets = {
  /**
   * Snippet callback.
   * @callback SnippetCallback
   * @param {Object} environment
   *   The environment variables
   * @param {...Array.<Array.<string>>} _
   *   The snippets names and arguments.
   */

  /**
   * Enables support for snippet filters.
   * @param {Object} [snippetInfo]
   * @param {SnippetCallback} [snippetInfo.isolatedCode]
   *   The code defining the available snippets to be executed in the isolated
   *   content script context.
   * @param {SnippetCallback} [snippetInfo.injectedCode]
   *   The code defining the available snippets to be injected and executed in
   *   the main context.
   */
  setLibrary: _content_filter_js__WEBPACK_IMPORTED_MODULE_7__.setSnippetLibrary
};

async function onInstalled(details) {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_1__.default.start();

  if (_prefs_js__WEBPACK_IMPORTED_MODULE_12__.Prefs.migration_state === _prefs_js__WEBPACK_IMPORTED_MODULE_12__.MIGRATED_TO_MV2) {
    await (0,_subscriptions_js__WEBPACK_IMPORTED_MODULE_10__.migrate)();
    await (0,_dnr_filters_js__WEBPACK_IMPORTED_MODULE_11__.migrateCustomFilters)();
    _prefs_js__WEBPACK_IMPORTED_MODULE_12__.Prefs.migration_state = _prefs_js__WEBPACK_IMPORTED_MODULE_12__.MIGRATED_TO_MV3;
  }

  await (0,_subscriptions_js__WEBPACK_IMPORTED_MODULE_10__.updateFilterText)();
  await (0,_subscriptions_js__WEBPACK_IMPORTED_MODULE_10__.ensureDNRRulesetsEnabled)();
}

/**
* @typedef {Object} FirstRunInfo
* @property {boolean} foundStorage Whether the subscriptions storage was
*                                  initialized or not.
* @property {boolean} foundSubscriptions True when pre-existing subscriptions
*                                        were found, false otherwise.
*                                        Considers also whether custom filters
*                                        exist.
* @property {Array.<string>?} [warnings] An array of warnings.
*/

/**
 * Initializes the filter engine and starts blocking content.
 *
 * Calling this function is required for the other API calls to work, except for
 * API event listener calls, which could also be done before `start()`.
 *
 * In MV3 extensions, this must be called in the first turn of the
 * event loop.
 *
 * @param {Object?} [addonInfo] An object containing addon
 *   information belonging to sdk consumer, that can be accessed via
 *   `debugging` module. (It is usually used as an identifier in
 *   network requests, etc.). This object can be undefined for MV2. If it is,
 *   name and version will default to the extension's name and version.
 * @param {string} [addonInfo.name] Name of the addon/extension.
 * @param {string} [addonInfo.version] Version of the addon/extension.
 * @param {Array<Recommendation>?} [addonInfo.bundledSubscriptions]
 *   A list of subscriptions provided by the integrator. Cannot be undefined
 *   for MV3.
 * @param {string?} [addonInfo.bundledSubscriptionsPath]
 *   A path to subscription files provided by the integrator. Cannot be
 *   undefined for MV3.
 * @return {Promise<FirstRunInfo>} Promise that is resolved after starting up
 *                                 is completed.
 */
async function start(addonInfo) {
  (0,_info_js__WEBPACK_IMPORTED_MODULE_8__.setAddonInfo)(addonInfo);
  startSubmodulesWithListeners();

  let warnings = [];

  if (webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.declarativeNetRequest) {
    webextension_polyfill__WEBPACK_IMPORTED_MODULE_0__.runtime.onInstalled.addListener(onInstalled);
    warnings = await (0,_subscriptions_js__WEBPACK_IMPORTED_MODULE_10__.validate)(
      addonInfo.bundledSubscriptions, addonInfo.bundledSubscriptionsPath);
  }

  await startSubmodules();

  let {filterStorage} = _core_js__WEBPACK_IMPORTED_MODULE_9__.filterEngine;
  let firstRun = {
    foundSubscriptions: filterStorage.getSubscriptionCount() != 0,
    foundStorage: !filterStorage.firstRun,
    warnings
  };

  return firstRun;
}

function startSubmodulesWithListeners() {
  // for MV3, submodules that register event listeners generally need
  // to register their events in the first turn of the event loop to
  // register their event listeners.
  _message_responder_js__WEBPACK_IMPORTED_MODULE_2__.start();
  if ((0,_browser_features_js__WEBPACK_IMPORTED_MODULE_13__.isRunningInServiceWorker)()) {
    _popup_blocker_service_worker_js__WEBPACK_IMPORTED_MODULE_4__.start();
    _request_filter_js__WEBPACK_IMPORTED_MODULE_5__.start();
  }

  _sitekey_js__WEBPACK_IMPORTED_MODULE_6__.start();
}

async function startSubmodules() {
  await _initializer_js__WEBPACK_IMPORTED_MODULE_1__.default.start();

  // MV2-style popup and request blocking assume that initializer is
  // started first.
  if (!(0,_browser_features_js__WEBPACK_IMPORTED_MODULE_13__.isRunningInServiceWorker)()) {
    _popup_blocker_background_page_js__WEBPACK_IMPORTED_MODULE_3__.start();
    _request_filter_js__WEBPACK_IMPORTED_MODULE_5__.start();
  }

  _core_js__WEBPACK_IMPORTED_MODULE_9__.filterEngine.filterStorage.synchronizer.start();
}

})();

/******/ 	return __webpack_exports__;
/******/ })()
;
});

/***/ }),

/***/ 7718:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "_o": () => (/* binding */ allowlistingState),
/* harmony export */   "s": () => (/* binding */ revalidateAllowlistingStates)
/* harmony export */ });
/* unused harmony export allowlist */
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(209);
/* harmony import */ var _messaging_port_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6960);
/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(9876);
/* harmony import */ var _filterConfiguration_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(8240);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module allowlisting */






let allowlistedDomainRegexp = /^@@\|\|([^/:]+)\^\$document$/;
let eventEmitter = new _events_js__WEBPACK_IMPORTED_MODULE_3__/* .EventEmitter */ .v();

/**
 * @typedef {object} filtersIsAllowlistedResult
 * @property {boolean} hostname
 *   True if an allowing filter for an entire domain matches the given page.
 * @property {boolean} page
 *   True if an allowing filter _not_ for an entire domain matches the given
 *   page.
 */

/**
 * Checks if the given page is allowlisted.
 *
 * @event "filters.isAllowlisted"
 * @returns {filtersIsAllowlistedResult}
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_1__/* .port.on */ .N.on("filters.isAllowlisted", async message =>
{
  let pageAllowlisted = false;
  let hostnameAllowlisted = false;

  for (let filterText of await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.getAllowingFilters(message.tab.id))
  {
    if (allowlistedDomainRegexp.test(filterText))
      hostnameAllowlisted = true;
    else
      pageAllowlisted = true;

    if (pageAllowlisted && hostnameAllowlisted)
      break;
  }

  return {hostname: hostnameAllowlisted, page: pageAllowlisted};
});

async function allowlist({hostname, origin, singlePage = false, url})
{
  let filterText;

  if (!hostname && !url)
    throw new Error("Hostname or URL required");

  if (url)
  {
    if (!(url instanceof URL))
      throw new Error("Invalid URL");

    if (singlePage)
    {
      // We generate a filter which only applies to the same protocol and
      // subdomain, but one which doesn't consider the exact query string or
      // fragment.
      // Our logic here is taken from the legacy Firefox extension.
      // See https://hg.adblockplus.org/adblockplus/file/tip/lib/ui.js#l1517
      let ending = "|";
      url.hash = "";
      if (url.search && url.search.includes("&"))
      {
        url.search = "";
        ending = "?";
      }
      filterText = `@@|${url.href}${ending}$document`;
    }
    else
    {
      hostname = url.hostname;
    }
  }

  if (!filterText)
  {
    let host = hostname.replace(/^www\./, "");
    filterText = `@@||${host}^$document`;
  }

  await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.enable([filterText]);

  const filterSubscriptions = await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.subscriptions.getForFilter(filterText);
  if (filterSubscriptions.length == 0)
    await (0,_filterConfiguration_js__WEBPACK_IMPORTED_MODULE_2__/* .addFilter */ .KJ)(filterText, origin);
}

/**
 * Adds an allowing filter for the given page's hostname, if it is not
 * already allowlisted. Note: If a disabled allowing filter exists, we
 * enable that instead.
 *
 * @event "filters.allowlist"
 * @proper {string} [origin]
 *   String indicating where the filter originated from.
 * @property {boolean} [singlePage=false]
 *   If true we add an allowing filter for the given page's URL instead.
 * @property {object} tab
 *   Tab that contains the page to allowlist.
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_1__/* .port.on */ .N.on("filters.allowlist", async message =>
{
  let page = new ext.Page(message.tab);
  await allowlist({
    origin: message.origin,
    singlePage: message.singlePage,
    url: page.url
  });
});

/**
 * Remove any allowing filters which apply to the given page's URL.
 *
 * @event "filters.unallowlist"
 * @property {boolean} [singlePage=false]
 *   If true we only remove allowing filters which are not for an entire
 *   domain.
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_1__/* .port.on */ .N.on("filters.unallowlist", async message =>
{
  for (let filterText of await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.getAllowingFilters(message.tab.id))
  {
    if (message.singlePage && allowlistedDomainRegexp.test(filterText))
      continue;

    await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.remove([filterText]);

    const filterSubscriptions = await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.subscriptions.getForFilter(filterText);
    if (filterSubscriptions.length != 0)
      await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.disable([filterText]);
  }
});

/**
 * @namespace
 * @static
 */
let allowlistingState = {
  /**
   * Adds a listener for the given event name.
   *
   * @param {string} name
   * @param {function} listener
   */
  addListener: eventEmitter.on.bind(eventEmitter),

  /**
   * Removes a listener for the given event name.
   *
   * @param {string} name
   * @param {function} listener
   */
  removeListener: eventEmitter.off.bind(eventEmitter)
};

async function revalidateAllowlistingState(page)
{
  eventEmitter.emit(
    "changed",
    page,
    await _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.isResourceAllowlisted(page.url, "document", page.id)
  );
}

async function revalidateAllowlistingStates()
{
  let tabs = await browser.tabs.query({});
  for (let tab of tabs)
    revalidateAllowlistingState(new ext.Page(tab));
}

ext.pages.onLoaded.addListener(revalidateAllowlistingState);
_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.onAdded.addListener(revalidateAllowlistingStates);
_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.onChanged.addListener(async(filter, property) =>
{
  if (property !== "enabled")
    return;

  await revalidateAllowlistingStates();
});
_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.filters.onRemoved.addListener(revalidateAllowlistingStates);
_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.subscriptions.onAdded.addListener(revalidateAllowlistingStates);
_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.subscriptions.onChanged.addListener(async(subscription, property) =>
{
  if (property !== null && property !== "enabled")
    return;

  await revalidateAllowlistingStates();
});
_vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.subscriptions.onRemoved.addListener(revalidateAllowlistingStates);


/***/ }),

/***/ 2209:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "c4": () => (/* binding */ setIconPath),
/* harmony export */   "k8": () => (/* binding */ setIconImageData),
/* harmony export */   "q_": () => (/* binding */ setBadge)
/* harmony export */ });
/* unused harmony export toggleBadge */
/* harmony import */ var _storage_tab_session_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(440);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module browserAction */



let badgeStateByPage = new _storage_tab_session_js__WEBPACK_IMPORTED_MODULE_0__/* .TabSessionStorage */ .H("browserAction:blockedState");
let changesByPage = new _storage_tab_session_js__WEBPACK_IMPORTED_MODULE_0__/* .TabSessionStorage */ .H("browserAction:changes");

async function setBadgeState(tabId, key, value)
{
  let badgeState = await badgeStateByPage.get(tabId);

  if (!badgeState)
  {
    badgeState = {
      hiddenState: "visible",
      text: ""
    };
  }

  // We need to ignore any text changes while we're hiding the badge
  if (!(badgeState.hiddenState == "hiding" && key == "text"))
    badgeState[key] = value;

  await badgeStateByPage.set(tabId, badgeState);

  return badgeState;
}

function applyChanges(tabId, changes)
{
  return Promise.all(Object.keys(changes).map(async change =>
  {
    // Firefox for Android displays the browser action not as an icon but
    // as a menu item. There is no icon, but such an option may be added
    // in the future.
    // https://bugzilla.mozilla.org/show_bug.cgi?id=1331746
    if (change == "iconPath" && "setIcon" in browser.action)
    {
      return browser.action.setIcon({
        tabId,
        path: {
          16: changes.iconPath.replace("$size", "16"),
          20: changes.iconPath.replace("$size", "20"),
          32: changes.iconPath.replace("$size", "32"),
          40: changes.iconPath.replace("$size", "40")
        }
      });
    }

    if (change == "iconImageData" && "setIcon" in browser.action)
    {
      return browser.action.setIcon({
        tabId,
        imageData: changes.iconImageData
      });
    }

    // There is no badge on Firefox for Android; the browser action is
    // simply a menu item.
    if (change == "badgeText" && "setBadgeText" in browser.action)
    {
      // Remember changes to the badge text but don't apply them yet
      // as long as the badge is hidden.
      let badgeState = await setBadgeState(tabId, "text", changes.badgeText);
      if (badgeState.hiddenState == "hidden")
        return;

      return browser.action.setBadgeText({
        tabId,
        text: changes.badgeText
      });
    }

    // There is no badge on Firefox for Android; the browser action is
    // simply a menu item.
    if (change == "badgeColor" &&
        "setBadgeBackgroundColor" in browser.action)
    {
      return browser.action.setBadgeBackgroundColor({
        tabId,
        color: changes.badgeColor
      });
    }
  }));
}

async function addChange(tabId, name, value)
{
  const changes = (await changesByPage.get(tabId)) || {};
  changes[name] = value;
  await changesByPage.set(tabId, changes);

  try
  {
    await applyChanges(tabId, changes);
    await changesByPage.delete(tabId);
  }
  catch (e)
  {
    // If the tab is prerendered, browser.action.set* fails
    // and we have to delay our changes until the currently visible tab
    // is replaced with the prerendered tab.
  }
}

async function onReplaced(addedTabId)
{
  const changes = await changesByPage.get(addedTabId);
  if (!changes)
    return;

  try
  {
    await applyChanges(addedTabId, changes);
  }
  catch (e)
  {
    // Ignore if we fail to apply the changes
  }

  await changesByPage.delete(addedTabId);
}
// If the tab is prerendered, browser.action.set* fails
// and we have to delay our changes until the currently visible tab
// is replaced with the prerendered tab.
browser.tabs.onReplaced.addListener(onReplaced);

/**
 * Sets icon badge for given tab.
 *
 * @param {number} tabId
 * @param {object} badge
 * @param {string} badge.color
 * @param {string} badge.number
 */
function setBadge(tabId, badge)
{
  if (!badge)
  {
    addChange(tabId, "badgeText", "");
  }
  else
  {
    if ("number" in badge)
      addChange(tabId, "badgeText", badge.number.toString());

    if ("color" in badge)
      addChange(tabId, "badgeColor", badge.color);
  }
}

/**
 * Sets icon image for given tab using image data.
 *
 * @param  {number} tabId
 * @param  {object} imageData
 */
function setIconImageData(tabId, imageData)
{
  addChange(tabId, "iconImageData", imageData);
}

/**
 * Sets icon image for given tab using file path.
 *
 * @param  {number} tabId
 * @param  {string} path - expected to include "$size" placeholder
 */
function setIconPath(tabId, path)
{
  addChange(tabId, "iconPath", path);
}

/**
 * Toggles icon badge for given tab.
 *
 * @param  {number} tabId
 * @param  {boolean} shouldHide
 */
async function toggleBadge(tabId, shouldHide)
{
  if (shouldHide)
  {
    await setBadgeState(tabId, "hiddenState", "hiding");
    addChange(tabId, "badgeText", "");
    await setBadgeState(tabId, "hiddenState", "hidden");
  }
  else
  {
    let badgeState = await setBadgeState(tabId, "hiddenState", "visible");
    addChange(tabId, "badgeText", badgeState.text);
  }
}


/***/ }),

/***/ 9685:
/***/ ((__unused_webpack___webpack_module__, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var _messaging_port_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6960);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



let lastError = null;

function safeToString(value)
{
  try
  {
    return String(value);
  }
  catch (e)
  {
    return "<string conversion error>";
  }
}

self.addEventListener("error", event =>
{
  lastError = safeToString(event.error);
});

self.addEventListener("unhandledrejection", event =>
{
  lastError = safeToString(event.reason);
});

let consoleError = console.error;
console.error = function error(...args)
{
  lastError = args.map(safeToString).join(" ");
  consoleError.apply(this, args);
};

_messaging_port_js__WEBPACK_IMPORTED_MODULE_0__/* .port.on */ .N.on("debug.getLastError", () =>
{
  let error = lastError;
  lastError = null;
  return error;
});


/***/ }),

/***/ 4921:
/***/ ((__unused_webpack___webpack_module__, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";

// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/build/templates/info.chrome.js.tmpl
var info_chrome_js = __webpack_require__(7269);
// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/events.js
var events = __webpack_require__(5094);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/port.js
var port = __webpack_require__(6960);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/types.js
var types = __webpack_require__(6684);
// EXTERNAL MODULE: ./adblock-betafish/alias/storage/tab-session.js
var tab_session = __webpack_require__(440);
;// CONCATENATED MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/versions.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */

function parseVersionComponent(comp)
{
  if (comp == "*")
    return Infinity;
  return parseInt(comp, 10) || 0;
}

/**
 * Compares two versions.
 *
 * @param {string} v1 The first version.
 * @param {string} v2 The second version.
 *
 * @returns {number} `-1` if `v1` is older than `v2`; `1` if `v1` is newer than
 *   `v2`; otherwise `0`.
 *
 * @package
 */
function compareVersions(v1, v2)
{
  let regexp = /^(.*?)([a-z].*)?$/i;
  let [, head1, tail1] = regexp.exec(v1);
  let [, head2, tail2] = regexp.exec(v2);
  let components1 = head1.split(".");
  let components2 = head2.split(".");

  for (let i = 0; i < components1.length ||
                  i < components2.length; i++)
  {
    let result = parseVersionComponent(components1[i]) -
                 parseVersionComponent(components2[i]) || 0;

    if (result < 0)
      return -1;
    else if (result > 0)
      return 1;
  }

  // Compare version suffix (e.g. 0.1alpha < 0.1b1 < 01.b2 < 0.1).
  // However, note that this is a simple string comparision, meaning: b10 < b2
  if (tail1 == tail2)
    return 0;
  if (!tail1 || tail2 && tail1 > tail2)
    return 1;
  return -1;
}

;// CONCATENATED MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/devtools.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module devtools */










const reloadStateByPage = new tab_session/* TabSessionStorage */.H("devtools:reloadState");

async function onBlockableItem(emit, blockableItem)
{
  const {filter} = blockableItem;

  let subscriptions = [];
  if (filter)
  {
    subscriptions = await ewe_api.subscriptions.getForFilter(filter.text);
    subscriptions = subscriptions
      .filter(subscription => subscription.enabled)
      .map(types/* toPlainSubscription */.LC);
  }

  emit(
    (0,types/* toPlainBlockableItem */.Q1)(blockableItem),
    (filter) ? (0,types/* toPlainFilter */.ot)(filter) : null,
    subscriptions
  );
}

async function onPageFrame(emit, details)
{
  const {tabId} = details;
  const reloadState = await reloadStateByPage.get(tabId);

  // Clear the devtools panel and reload the inspected tab without caching
  // when a new request is issued. However, make sure that we don't end up
  // in an infinite recursion if we already triggered a reload.
  if (reloadState === "reloading")
  {
    await reloadStateByPage.delete(tabId);
    return;
  }

  emit("requests", "reset");

  // We can't repeat the request if it isn't a GET request. The browser would
  // prompt the user to confirm reloading the page, and POST requests are
  // known to cause issues on many websites if repeated.
  if (details.method === "GET")
    await reloadStateByPage.set(tabId, "needsReload");
}

async function onPageLoad(page)
{
  const reloadState = await reloadStateByPage.get(page.id);

  // Reloading the tab is the only way that allows bypassing all caches, in
  // order to see all requests in the devtools panel. Reloading must not be
  // performed before the tab changes to "loading", otherwise it will load the
  // previous URL.
  if (reloadState === "needsReload")
  {
    await reloadStateByPage.set(page.id, "reloading");
    browser.tabs.reload(page.id, {bypassCache: true});
  }
}

/**
 * Returns true if our devtools panel is supported by the browser.
 *
 * @event "devtools.supported"
 * @returns {boolean}
 */
port/* port.on */.N.on("devtools.supported", (message, sender) =>
  info_chrome_js.platform == "chromium" ||
  info_chrome_js.application == "firefox" &&
  compareVersions(info_chrome_js.applicationVersion, "54") >= 0
);

(0,events/* installHandler */.a)("requests", null, (emit, action, targetTabId) =>
{
  switch (action)
  {
    case "hits":
      const blockableItemsOptions = {
        filterType: "all",
        includeElementHiding: true,
        includeUnmatched: true,
        tabId: targetTabId
      };
      const localOnBlockableItem = onBlockableItem.bind(null, emit);

      ewe_api.reporting.onBlockableItem.addListener(
        localOnBlockableItem,
        blockableItemsOptions
      );
      return () =>
      {
        ewe_api.reporting.onBlockableItem.removeListener(
          localOnBlockableItem,
          blockableItemsOptions
        );
      };
    case "reset":
      const localOnPageFrame = onPageFrame.bind(null, emit);
      const localOnPageLoad = onPageLoad.bind(null, emit);

      browser.webRequest.onBeforeRequest.addListener(
        localOnPageFrame,
        {
          urls: ["http://*/*", "https://*/*"],
          types: ["main_frame"],
          tabId: targetTabId
        }
      );
      ext.pages.onLoading.addListener(localOnPageLoad);

      return () =>
      {
        browser.webRequest.onBeforeRequest.removeListener(localOnPageFrame);
        ext.pages.onLoading.removeListener(localOnPageLoad);
      };
  }
});


/***/ }),

/***/ 9876:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "v": () => (/* binding */ EventEmitter)
/* harmony export */ });
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module */

/**
 * Registers and emits named events.
 */
class EventEmitter
{
  constructor()
  {
    this._listeners = new Map();
  }

  /**
   * Adds a listener for the specified event name.
   *
   * @param {string}   name
   * @param {function} listener
   */
  on(name, listener)
  {
    let listeners = this._listeners.get(name);
    if (listeners)
      listeners.push(listener);
    else
      this._listeners.set(name, [listener]);
  }

  /**
   * Removes a listener for the specified event name.
   *
   * @param {string}   name
   * @param {function} listener
   */
  off(name, listener)
  {
    let listeners = this._listeners.get(name);
    if (listeners)
    {
      if (listeners.length > 1)
      {
        let idx = listeners.indexOf(listener);
        if (idx != -1)
          listeners.splice(idx, 1);
      }
      else if (listeners[0] === listener)
      {
        // We must use strict equality above for compatibility with
        // Array.prototype.indexOf
        this._listeners.delete(name);
      }
    }
  }

  /**
   * Returns a copy of the array of listeners for the specified event.
   *
   * @param {string} name
   *
   * @returns {Array.<function>}
   */
  listeners(name)
  {
    let listeners = this._listeners.size > 0 ? this._listeners.get(name) : null;
    return listeners ? listeners.slice() : [];
  }

  /**
   * Checks whether there are any listeners for the specified event.
   *
   * @param {string} [name] The name of the event. If omitted, checks whether
   *   there are any listeners for any event.
   *
   * @returns {boolean}
   */
  hasListeners(name)
  {
    return this._listeners.size > 0 &&
           (typeof name == "undefined" || this._listeners.has(name));
  }

  /**
   * Calls all previously added listeners for the given event name.
   *
   * @param {string} name
   * @param {...*}   [args]
   */
  emit(name, ...args)
  {
    let listeners = this._listeners.size > 0 ? this._listeners.get(name) : null;
    if (listeners)
    {
      for (let listener of listeners.slice())
        listener(...args);
    }
  }
}


/***/ }),

/***/ 8240:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";

// EXPORTS
__webpack_require__.d(__webpack_exports__, {
  "KJ": () => (/* binding */ addFilter)
});

// UNUSED EXPORTS: askConfirmSubscription, initDisabledFilterCounters

// EXTERNAL MODULE: ./vendor/webext-sdk/dist/ewe-api.js
var ewe_api = __webpack_require__(209);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/events.js
var events = __webpack_require__(5094);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/port.js
var messaging_port = __webpack_require__(6960);
// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/events.js
var lib_events = __webpack_require__(9876);
// EXTERNAL MODULE: ./adblock-betafish/alias/prefs.js
var prefs = __webpack_require__(4428);
// EXTERNAL MODULE: ./vendor/adblockplusui/src/core/scheduled-event-emitter/background/scheduled-event-emitter.ts + 1 modules
var scheduled_event_emitter = __webpack_require__(7650);
// EXTERNAL MODULE: ./vendor/adblockplusui/src/core/scheduled-event-emitter/background/scheduled-event-emitter.types.ts
var scheduled_event_emitter_types = __webpack_require__(1784);
;// CONCATENATED MODULE: ./vendor/adblockplusui/src/premium/background/license.ts
var __awaiter = (undefined && undefined.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};






const global = typeof window !== "undefined" ? window : self;
class TemporaryLicenseCheckError extends Error {
}
const emitter = new lib_events/* EventEmitter */.v();
const licenseCheckPeriod = (/* unused pure expression or super */ null && (24 * 60 * 60 * 1000));
let licenseCheckTimeoutId = null;
const licenseCheckRetryDelay = (/* unused pure expression or super */ null && (60 * 1000));
const licenseCheckRetryEventName = "premium.license.check.retry";
function activateLicense(oldLicense, newLicense) {
    Prefs.set("premium_license", newLicense);
    scheduledEmitter.removeSchedule(licenseCheckRetryEventName);
    if (oldLicense.status === "active") {
        emitter.emit("updated");
    }
    else {
        scheduleNextLicenseCheck(null);
        emitter.emit("activated");
    }
}
function checkLicense(retryCount = 0) {
    return __awaiter(this, void 0, void 0, function* () {
        if (retryCount >= 3) {
            scheduledEmitter.removeSchedule(licenseCheckRetryEventName);
            if (retryCount > 3) {
                return;
            }
        }
        const userId = Prefs.get("premium_user_id");
        if (!userId) {
            return;
        }
        try {
            if (!navigator.onLine) {
                throw new TemporaryLicenseCheckError("No network connection");
            }
            const requestData = {
                cmd: "license_check",
                u: userId,
                v: "1"
            };
            const requestUrl = Prefs.get("premium_license_check_url");
            const response = yield fetch(requestUrl, {
                method: "POST",
                cache: "no-cache",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify(requestData)
            });
            if (!response.ok) {
                const { status } = response;
                if (status >= 400 && status <= 499) {
                    throw new Error(`Request failed (code: ${status})`);
                }
                if (status >= 500 && status <= 599) {
                    throw new TemporaryLicenseCheckError(`Received error response (code: ${status})`);
                }
                console.error(`Received unexpected response (code: ${status})`);
                return;
            }
            const oldLicense = Prefs.get("premium_license");
            const newLicense = (yield response.json());
            if (newLicense.lv !== 1) {
                throw new Error(`Invalid license version: ${newLicense.lv}`);
            }
            if (oldLicense.status === "active" && newLicense.status === "expired") {
                throw new Error("Expired license");
            }
            if (newLicense.status !== "active") {
                throw new Error(`Unknown license status: ${newLicense.status}`);
            }
            if (!newLicense.code) {
                if (!oldLicense.code) {
                    throw new Error("Undefined license code");
                }
                newLicense.code = oldLicense.code;
            }
            activateLicense(oldLicense, newLicense);
        }
        catch (ex) {
            if (ex instanceof TemporaryLicenseCheckError) {
                console.warn(`Premium license check failed (retries: ${retryCount})`, ex);
                if (retryCount > 0) {
                    return;
                }
                scheduledEmitter.setSchedule(licenseCheckRetryEventName, licenseCheckRetryDelay, ScheduleType.interval);
                return;
            }
            console.error("Premium license check failed", ex);
            deactivateLicense();
        }
    });
}
function deactivateLicense() {
    Prefs.reset("premium_license");
    Prefs.reset("premium_license_nextcheck");
    Prefs.reset("premium_user_id");
    scheduledEmitter.removeSchedule(licenseCheckRetryEventName);
    if (licenseCheckTimeoutId !== null) {
        global.clearTimeout(licenseCheckTimeoutId);
    }
    emitter.emit("deactivated");
}
function getPremiumState() {
    return { isActive: hasActiveLicense() };
}
function hasActiveLicense() {
    const license = Prefs.get("premium_license");
    return license.status === "active";
}
function initialize() {
    initializeMessaging();
    initializeLicenseChecks();
}
function scheduleNextLicenseCheck(nextTimestamp) {
    if (!nextTimestamp) {
        nextTimestamp = Date.now() + licenseCheckPeriod;
        Prefs.set("premium_license_nextcheck", nextTimestamp);
    }
    licenseCheckTimeoutId = global.setTimeout(() => {
        checkLicense();
        scheduleNextLicenseCheck(null);
    }, nextTimestamp - Date.now());
}
function initializeLicenseChecks() {
    scheduledEmitter.setListener(licenseCheckRetryEventName, (info) => {
        checkLicense(info.callCount);
    });
    const nextCheckTimestamp = Prefs.get("premium_license_nextcheck");
    if (!nextCheckTimestamp) {
        return;
    }
    scheduleNextLicenseCheck(nextCheckTimestamp);
}
function initializeMessaging() {
    port.on("premium.activate", (msg) => __awaiter(this, void 0, void 0, function* () {
        if (!msg.userId) {
            return false;
        }
        Prefs.set("premium_user_id", msg.userId);
        yield checkLicense();
        return true;
    }));
    port.on("premium.get", () => getPremiumState());
    installHandler("premium", "changed", (emit) => {
        const onChanged = () => emit(getPremiumState());
        emitter.on("activated", onChanged);
        emitter.on("deactivated", onChanged);
        return () => {
            emitter.off("activated", onChanged);
            emitter.off("deactivated", onChanged);
        };
    });
    ext.addTrustedMessageTypes(Prefs.get("premium_license_activation_origin"), [
        "premium.activate"
    ]);
}

;// CONCATENATED MODULE: ./vendor/adblockplusui/src/premium/background/index.ts



// EXTERNAL MODULE: ./adblock-betafish/alias/storage/session.js
var session = __webpack_require__(4051);
;// CONCATENATED MODULE: ./adblock-betafish/alias/options.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */
/*
 * Same as the original source vendor\adblockplusui\lib\pages\options.js
 * except:
 *  - updated the paths to imported modules
 *  - the 'findOptionsPage' function will correctly find the AdBlock Options page
 *    when a hash is present in the URL.
 *  - use import / export instead of require
 * /

/** @module options */







/**
 * Key to store/retrieve an optional message to send to the options page after
 * it opens.
 */
const optionsMessageKey = "optionsMessage";

let optionsPort = null;

// Firefox won't let us query for moz-extension:// pages, though
// starting with Firefox 56 an extension can query for its own URLs:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1271354
const optionsUrl = browser.runtime.getURL(
  browser.runtime.getManifest().options_ui.page
);

const options_session = new session/* SessionStorage */.x("options");

async function onMessage(message, port) {
  if (message.type != "app.listen")
    return;

  const optionsMessage = await options_session.get(optionsMessageKey);

  if (!optionsMessage)
    return;

  await options_session.delete(optionsMessageKey);

  port.postMessage(optionsMessage);
}

async function onConnect(port) {
  if (!ext.isTrustedSender(port.sender)) {
    return;
  }

  if (port.name != "ui") {
    return;
  }

  if (!port.sender.tab || !port.sender.tab.url.startsWith(optionsUrl)) {
    return;
  }

  optionsPort = port;
  optionsPort.onDisconnect.addListener(() => {
    optionsPort = null;
  });
  optionsPort.onMessage.addListener(onMessage);
}
browser.runtime.onConnect.addListener(onConnect);

/**
 * Opens the options page, or switches to its existing tab.
 * @param {Object} [message] - Message to send to options page
 */
async function showOptions(message) {
  await options_session.delete(optionsMessageKey);

  // If the options page is already open, focus its tab manually to avoid
  // potentially opening it again, due to browser.runtime.openOptionsPage()
  // behaving differently across browsers
  if (optionsPort) {
    // Firefox for Android doesn't support browser.windows
    if ("windows" in browser) {
      await browser.windows.update(
        optionsPort.sender.tab.windowId,
        { focused: true }
      );
    }

    await browser.tabs.update(optionsPort.sender.tab.id, { active: true });

    // Send message after focusing options page
    if (message) {
      optionsPort.postMessage(message);
    }
  }
  else {
    // Send message after initializing options page
    if (message) {
      await options_session.set(optionsMessageKey, message);
    }

    await browser.runtime.openOptionsPage();
  }
}


// We need to clear the popup URL on Firefox for Android in order for the
// options page to open instead of the bubble. Unfortunately there's a bug[1]
// which prevents us from doing that, so we must avoid setting the URL on
// Firefox from the manifest at all, instead setting it here only for
// non-mobile.
// [1] - https://bugzilla.mozilla.org/show_bug.cgi?id=1414613
Promise.all([browser.action.getPopup({}),
browser.runtime.getPlatformInfo()]).then(
  ([popup, platformInfo]) => {
    if (!popup && platformInfo.os != "android")
      browser.action.setPopup({ popup: "popup.html" });
  }
);

// On Firefox for Android, open the options page directly when the browser
// action is clicked.
browser.action.onClicked.addListener(async () => {
  const [tab] = await browser.tabs.query({ active: true });
  const currentPage = new ext.Page(tab);

  let message = null;
  if (/^https?:$/.test(currentPage.url.protocol)) {
    const isAllowlisted = await ewe_api.filters.isResourceAllowlisted(
      currentPage.url,
      "document",
      currentPage.id
    );
    message = {
      type: "app.respond",
      action: "showPageOptions",
      args: [
        {
          host: currentPage.url.hostname.replace(/^www\./, ""),
          allowlisted: isAllowlisted
        }
      ]
    };
  }

  await showOptions(message);
});

/**
 * Opens the options page in a new tab and waits for it to load, or switches to
 * the existing tab if the options page is already open.
 *
 * @event "options.open"
 */
messaging_port/* port.on */.N.on("options.open", async (message, sender) => {
  await showOptions();
});

// EXTERNAL MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/messaging/types.js
var types = __webpack_require__(6684);
;// CONCATENATED MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/requestBlocker.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module requestBlocker */



let filterTypes = new Set(function*()
{
  for (let type of ewe_api.reporting.contentTypesMap.values())
    yield type.toUpperCase();

  yield "SNIPPET";
}());

;// CONCATENATED MODULE: ./vendor/adblockplusui/adblockpluschrome/lib/filterConfiguration.js
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */










const disabledFilterCounters = new Map();
const eventEmitter = new lib_events/* EventEmitter */.v();

async function addFilter(filterText, origin)
{
  const data = {created: Date.now()};
  if (origin)
    data.origin = origin;

  try
  {
    await ewe_api.filters.add([filterText], data);
    await ewe_api.filters.enable([filterText]);
  }
  catch (ex)
  {
    // If we add an existing filter again, we ignore the resulting error to
    // avoid showing unnecessary error messages to the user
    if (ex.type !== "storage_duplicate_filters")
      return ex;
  }

  return null;
}

async function addSubscription(details)
{
  try
  {
    await ewe_api.subscriptions.add(details.url, details);
    await ewe_api.subscriptions.sync(details.url);
  }
  catch (ex)
  {
    return false;
  }

  return true;
}

/**
 * Asks user to confirm the subscription details before it is added.
 * @param {Object} details
 */
async function askConfirmSubscription(details)
{
  await showOptions({
    type: "app.respond",
    action: "addSubscription",
    args: [{
      homepage: details.homepage || null,
      title: details.title || null,
      url: details.url
    }]
  });
}

function parseFilter(text)
{
  let filterText = text.trim() || null;
  let error = null;

  if (filterText)
  {
    if (filterText[0] == "[")
    {
      error = {type: "unexpected_filter_list_header"};
    }
    else
    {
      let filterError = ewe_api.filters.validate(filterText);
      if (filterError)
        error = (0,types/* toPlainFilterError */.U_)(filterError);
    }
  }

  return [filterText, error];
}

/**
 * Attempts to add the given filter, or returns an error.
 *
 * @event "filters.add"
 * @property {string} [origin] - Where the filter originated from
 * @property {string} text - The filter text to add
 * @returns {FilterError[]}
 */
messaging_port/* port.on */.N.on("filters.add", (message, sender) =>
{
  return filtersAdd(message.text, message.origin);
});

/**
 * Returns a serialized version of all filters in special subscriptions.
 *
 * @event "filters.get"
 * @returns {object[]}
 */
messaging_port/* port.on */.N.on("filters.get", async(message, sender) =>
{
  let filters = await ewe_api.filters.getUserFilters();
  return filters.map(types/* toPlainFilter */.ot);
});

/**
 * Returns the available filter types, e.g. "FONT", "WEBSOCKET", etc.
 *
 * @event "filters.getTypes"
 * @returns {string[]}
 */
messaging_port/* port.on */.N.on("filters.getTypes", (message, sender) => Array.from(filterTypes));

/**
 * Import the given block of filter text as custom user filters.
 *
 * @event "filters.importRaw"
 * @property {string} [origin]
 *   Where the filter originated from.
 * @property {string} text
 *   The filters to add.
 * @returns {string[]} errors
 */
messaging_port/* port.on */.N.on("filters.importRaw", async(message, sender) =>
{
  let [filterTexts, errors] = filtersValidate(message.text);

  if (errors.length == 0)
  {
    for (const filterText of filterTexts)
    {
      const error = await addFilter(filterText, message.origin);
      if (error)
        errors.push(error);
    }
  }

  return errors;
});

/**
 * Remove the given filter.
 *
 * @event "filters.remove"
 * @property {string} text
 *   The text of the filter to remove.
 * @property {string} [subscriptionUrl]
 *   The URL of the subscription to remove the filter from, defaults to all
 *   subscriptions.
 * @property {number} [index]
 *   The index of the filter in the given subscription to remove, defaults to
 *   all instances and ignored if subscriptionUrl isn't given.
 * @returns {string[]} errors
 */
messaging_port/* port.on */.N.on("filters.remove", (message, sender) => filtersRemove(message));

/**
 * Replaces one custom user filter with another.
 *
 * @event "filters.replace"
 * @property {string} new - The new filter text to add.
 * @property {string} old - The old filter text to remove.
 * @property {string} [origin] - Where the filter originated from.
 * @returns {string[]} errors
 */
messaging_port/* port.on */.N.on("filters.replace", async(message, sender) =>
{
  let errors = await filtersAdd(message.new, message.origin);
  if (errors.length)
    return errors;
  await filtersRemove({text: message.old});
  return [];
});

/**
 * Enabled or disables the given filter.
 *
 * @event "filters.toggle"
 * @property {string} text - The filter text.
 * @property {boolean} disabled - True to disable the filter, false to enable.
 */
messaging_port/* port.on */.N.on("filters.toggle", async(message, sender) =>
{
  if (message.disabled)
    await ewe_api.filters.disable([message.text]);
  else
    await ewe_api.filters.enable([message.text]);
});

/**
 * Validates the filters inside the given block of filter text.
 *
 * @event "filters.validate"
 * @property {string} text - The filters to validate
 * @returns {string[]} errors
 */
messaging_port/* port.on */.N.on("filters.validate", (message, sender) =>
{
  let [, errors] = filtersValidate(message.text);
  return errors;
});

/**
 * Adds a subscription, either in the background or with the user's
 * confirmation.
 *
 * @event "subscriptions.add"
 * @property {string} url
 *   The subscription's URL.
 * @property {boolean} confirm
 *   If true the user will first be asked to confirm the subscription's details
 *   before it is added.
 * @property {string} [title]
 *   The subscription's title.
 * @property {string} [homepage]
 *   The subscription's homepage.
 * @returns {?boolean}
 *   true if the subscription was added, false if the URL is invalid,
 *   null if the "confirm" property was set
 */
messaging_port/* port.on */.N.on("subscriptions.add", async(message, sender) =>
{
  if (message.confirm)
  {
    askConfirmSubscription({
      homepage: message.homepage,
      title: message.title,
      url: message.url
    });
    return null;
  }

  return addSubscription(message);
});

ewe_api.reporting.onSubscribeLinkClicked.addListener(message =>
{
  askConfirmSubscription({
    title: message.title,
    url: message.url
  });
});

/**
 * Enables all filters from the given subscription.
 *
 * @event "subscriptions.enableAllFilters"
 * @property {string} url
 *   The subscription's URL.
 */
messaging_port/* port.on */.N.on("subscriptions.enableAllFilters", async(message, sender) =>
{
  const filters = await ewe_api.subscriptions.getFilters(message.url);
  const filterTexts = filters.map(filter => filter.text);
  await ewe_api.filters.enable(filterTexts);
});

/**
 * Returns a serialized version of all downloadable subscriptions which meet
 * the given criteria. Optionally include the disabled filters for those
 * subscriptions.
 *
 * @event "subscriptions.get"
 * @property {boolean} ignoreDisabled
 *   Skip disabled subscriptions if true.
 * @property {boolean} disabledFilters
 *   Include a subscription's disabled filters if true.
 * @returns {object[]} subscriptions
 */
messaging_port/* port.on */.N.on("subscriptions.get", async(message, sender) =>
{
  let subscriptions = [];
  for (let s of await ewe_api.subscriptions.getDownloadable())
  {
    if (message.ignoreDisabled && !s.enabled)
      continue;

    let subscription = (0,types/* toPlainSubscription */.LC)(s);
    if (message.disabledFilters)
    {
      let filters = await ewe_api.subscriptions.getFilters(s.url) || [];
      subscription.disabledFilters = filters
        .filter(f => f.enabled === false)
        .map(f => f.text);
    }
    subscriptions.push(subscription);
  }
  return subscriptions;
});

/**
 * Returns the amount of disabled filters contained in a subscription.
 *
 * @event "subscriptions.getDisabledFilterCount"
 * @property {string} url - The subscription's URL.
 */
messaging_port/* port.on */.N.on("subscriptions.getDisabledFilterCount", (message, sender) =>
{
  return disabledFilterCounters.get(message.url) || 0;
});

/**
 * Returns a list of serialised recommended subscriptions for the user.
 *
 * @event "subscriptions.getRecommendations"
 * @returns {object[]} recommendedSubscriptions
 */
messaging_port/* port.on */.N.on("subscriptions.getRecommendations", async(message, sender) =>
{
  const recommendations = await ewe_api.subscriptions.getRecommendations();
  return Array.from(recommendations, types/* toPlainRecommendation */.N);
});

/**
 * Remove the given subscription if it exists.
 *
 * @event "subscriptions.remove"
 * @property {string} url - The subscription's URL.
 */
messaging_port/* port.on */.N.on("subscriptions.remove", async(message, sender) =>
{
  await ewe_api.subscriptions.remove(message.url);
});

/**
 * Toggles a subscription by either enabling/disabling, or by adding/removing
 * it.
 *
 * @event "subscriptions.toggle"
 * @property {string} url
 *   The subscription's URL.
 * @property {boolean} keepInstalled
 *   If true enable/disable the subscription, otherwise add/remove.
 * @returns {boolean}
 *   true if the subscription was toggled successfully,
 *   false if it's a new subscription with an invalid URL
 */
messaging_port/* port.on */.N.on("subscriptions.toggle", async(message, sender) =>
{
  if (await ewe_api.subscriptions.has(message.url))
  {
    let subscription;
    for (let s of await ewe_api.subscriptions.getDownloadable())
    {
      if (s.url == message.url)
      {
        subscription = s;
        break;
      }
    }

    if (subscription)
    {
      if (!subscription.enabled || message.keepInstalled)
      {
        if (subscription.enabled)
          await ewe_api.subscriptions.disable(message.url);
        else
          await ewe_api.subscriptions.enable(message.url);
      }
      else
      {
        await ewe_api.subscriptions.remove(subscription.url);
      }
      return true;
    }
  }

  return addSubscription(message);
});

/**
 * Trigger either the given subscription, or all subscriptions, to update.
 *
 * @event "subscriptions.update"
 * @property {string} [url]
 *   The subscription to update, if not specified all subscriptions will be
 *   updated.
 */
messaging_port/* port.on */.N.on("subscriptions.update", async(message, sender) =>
{
  await ewe_api.subscriptions.sync(message.url);
});

async function filtersAdd(text, origin)
{
  let [filterText, error] = parseFilter(text);

  if (!error && filterText)
    error = await addFilter(filterText, origin);

  return (error) ? [error] : [];
}

function filtersValidate(text)
{
  let filterTexts = [];
  let errors = [];

  let lines = text.split("\n");
  for (let i = 0; i < lines.length; i++)
  {
    let [filterText, error] = parseFilter(lines[i]);

    if (error)
    {
      // We don't treat filter headers like invalid filters,
      // instead we simply ignore them and don't show any errors
      // in order to allow pasting complete filter lists.
      // If there are no filters, we do treat it as an invalid filter
      // to inform users about it and to give them a chance to edit it.
      if (error.type === "unexpected_filter_list_header" &&
          lines.length > 1)
        continue;

      if (lines.length > 1)
        error.lineno = i + 1;

      errors.push(error);
    }
    else if (filterText)
    {
      filterTexts.push(filterText);
    }
  }

  return [filterTexts, errors];
}

async function filtersRemove(message)
{
  await ewe_api.filters.remove([message.text]);
  // in order to behave, from consumer perspective, like any other
  // method that could produce errors, return an Array, even if empty
  return [];
}

async function initDisabledFilterCounters()
{
  for (const subscription of await ewe.subscriptions.getDownloadable())
  {
    let count = 0;

    for (const filter of await ewe.subscriptions.getFilters(subscription.url))
    {
      if (filter.enabled === false)
        count++;
    }

    if (count > 0)
    {
      disabledFilterCounters.set(subscription.url, count);
      // Core doesn't expose the subscription's disabled filters state
      // and to avoid adding new "loaded" events and behavior around it,
      // we emit a "filtersDisabled" event to trigger UI changes
      eventEmitter.emit(
        "filtersDisabled",
        subscription,
        true,
        true
      );
    }
  }
}

async function updateCounters(filterText, enabled)
{
  for (const subscription of await ewe_api.subscriptions.getForFilter(filterText))
  {
    const oldCount = disabledFilterCounters.get(subscription.url) || 0;
    const newCount = (enabled) ? oldCount - 1 : oldCount + 1;

    if (newCount === 0)
      disabledFilterCounters.delete(subscription.url);
    else
      disabledFilterCounters.set(subscription.url, newCount);

    if (oldCount === 0 || newCount === 0)
    {
      eventEmitter.emit(
        "filtersDisabled",
        subscription,
        newCount > 0,
        oldCount > 0
      );
    }
  }
}

ewe_api.filters.onChanged.addListener(async(filter, property) =>
{
  if (property !== "enabled")
    return;

  await updateCounters(filter.text, filter.enabled);
});

ewe_api.subscriptions.onRemoved.addListener(subscription =>
{
  disabledFilterCounters.delete(subscription.url);
});

emitter.on("deactivated", async() =>
{
  const recommendations = await ewe_api.subscriptions.getRecommendations();
  for (const recommendation of recommendations)
  {
    if (recommendation.type !== "annoyances")
      continue;

    if (!(await ewe_api.subscriptions.has(recommendation.url)))
      break;

    await ewe_api.subscriptions.remove(recommendation.url);
    break;
  }
});

(0,events/* installHandler */.a)("filters", "added", emit =>
{
  const onAdded = filter => emit((0,types/* toPlainFilter */.ot)(filter));
  ewe_api.filters.onAdded.addListener(onAdded);
  return () => ewe_api.filters.onAdded.removeListener(onAdded);
});

(0,events/* installHandler */.a)("filters", "changed", emit =>
{
  const onChanged = (filter, property) => emit((0,types/* toPlainFilter */.ot)(filter), property);
  ewe_api.filters.onChanged.addListener(onChanged);
  return () => ewe_api.filters.onChanged.removeListener(onChanged);
});

(0,events/* installHandler */.a)("filters", "removed", emit =>
{
  const onRemoved = filter => emit((0,types/* toPlainFilter */.ot)(filter));
  ewe_api.filters.onRemoved.addListener(onRemoved);
  return () => ewe_api.filters.onRemoved.removeListener(onRemoved);
});

(0,events/* installHandler */.a)("subscriptions", "added", emit =>
{
  const onAdded = subscription => emit((0,types/* toPlainSubscription */.LC)(subscription));
  ewe_api.subscriptions.onAdded.addListener(onAdded);
  return () => ewe_api.subscriptions.onAdded.removeListener(onAdded);
});

(0,events/* installHandler */.a)("subscriptions", "changed", emit =>
{
  const onChanged = (subscription, property) =>
  {
    emit((0,types/* toPlainSubscription */.LC)(subscription), property);
  };
  ewe_api.subscriptions.onChanged.addListener(onChanged);
  return () => ewe_api.subscriptions.onChanged.removeListener(onChanged);
});

(0,events/* installHandler */.a)("subscriptions", "filtersDisabled", emit =>
{
  const onFiltersDisabled = (subscription, hadFilters, hasFilters) =>
  {
    emit((0,types/* toPlainSubscription */.LC)(subscription), hadFilters, hasFilters);
  };
  eventEmitter.on("filtersDisabled", onFiltersDisabled);
  return () => eventEmitter.off("filtersDisabled", onFiltersDisabled);
});

(0,events/* installHandler */.a)("subscriptions", "removed", emit =>
{
  const onRemoved = subscription => emit((0,types/* toPlainSubscription */.LC)(subscription));
  ewe_api.subscriptions.onRemoved.addListener(onRemoved);
  return () => ewe_api.subscriptions.onRemoved.removeListener(onRemoved);
});


/***/ }),

/***/ 7526:
/***/ ((__unused_webpack___webpack_module__, __unused_webpack___webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony import */ var info__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7269);
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(209);
/* harmony import */ var _messaging_port_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6960);
/* harmony import */ var _prefs_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4428);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */

/** @module messageResponder */







function forward(type, message, sender)
{
  return _messaging_port_js__WEBPACK_IMPORTED_MODULE_2__/* .port._onMessage */ .N._onMessage(Object.assign({}, message, {type}), sender);
}

/**
 * @deprecated Please send the "filters.getTypes" message instead.
 *
 * @event "types.get"
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_2__/* .port.on */ .N.on("types.get",
        (message, sender) => forward("filters.getTypes", message, sender));

/**
 * @deprecated Please send the "options.open" message instead.
 *
 * @event "app.open"
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_2__/* .port.on */ .N.on("app.open", (message, sender) =>
{
  if (message.what == "options")
    return forward("options.open", message, sender);
});

/**
 * @deprecated Please send the "subscriptions.getInitIssues",
 *             "prefs.getDocLink", "subscriptions.getRecommendations",
 *             "devtools.supported" or "info.get" messages, or call the
 *             browser.tabs.getCurrent(), browser.i18n.getUILanguage(),
 *             browser.i18n.getMessage("@@bidi_dir") APIs instead.
 *
 * @event "app.get"
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_2__/* .port.on */ .N.on("app.get", async(message, sender) =>
{
  if (message.what == "localeInfo")
  {
    return {
      locale: browser.i18n.getUILanguage(),
      bidiDir: browser.i18n.getMessage("@@bidi_dir")
    };
  }

  if (message.what == "acceptableAdsUrl")
    return _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.subscriptions.ACCEPTABLE_ADS_URL;

  if (message.what == "acceptableAdsPrivacyUrl")
    return _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_1__.subscriptions.ACCEPTABLE_ADS_PRIVACY_URL;

  if (message.what == "senderId")
    return sender.page.id;

  if (message.what == "ctalink")
  {
    const ctaLinkNameToPrefsMap = new Map([
      ["premium-manage", "premium_manage_page_url"],
      ["premium-upgrade", "premium_upgrade_page_url"]
    ]);

    const {link: ctaLinkName, queryParams} = message;
    const prefsUrlKey = ctaLinkNameToPrefsMap.get(ctaLinkName);
    let url = _prefs_js__WEBPACK_IMPORTED_MODULE_3__/* .Prefs */ .B[prefsUrlKey];

    const linkPlaceholders = [
      ["LANG", () => browser.i18n.getUILanguage().replace("-", "_")],
      ["ADDON_NAME", () => info__WEBPACK_IMPORTED_MODULE_0__.addonName],
      ["ADDON_VERSION", () => info__WEBPACK_IMPORTED_MODULE_0__.addonVersion],
      ["APPLICATION_NAME", () => info__WEBPACK_IMPORTED_MODULE_0__.application],
      ["APPLICATION_VERSION", () => info__WEBPACK_IMPORTED_MODULE_0__.applicationVersion],
      ["PLATFORM_NAME", () => info__WEBPACK_IMPORTED_MODULE_0__.platform],
      ["PLATFORM_VERSION", () => info__WEBPACK_IMPORTED_MODULE_0__.platformVersion],
      ["LICENSE_CODE", () => _prefs_js__WEBPACK_IMPORTED_MODULE_3__/* .Prefs.get */ .B.get("premium_license").code],
      ["SOURCE", () => queryParams.source]
    ];

    for (const [key, getValue] of linkPlaceholders)
      url = url.replace(`%${key}%`, encodeURIComponent(getValue()));

    return url;
  }

  if (message.what == "doclink")
    return forward("prefs.getDocLink", message, sender);

  if (message.what == "recommendations")
    return forward("subscriptions.getRecommendations", message, sender);

  if (message.what == "features")
  {
    let devToolsPanel = await forward("devtools.supported", message, sender);
    return {devToolsPanel};
  }

  if (message.what == "os")
  {
    let platformInfo = await browser.runtime.getPlatformInfo();
    return platformInfo.os;
  }

  return info__WEBPACK_IMPORTED_MODULE_0__[message.what];
});

/**
 * @typedef {object} infoGetResult
 * @property {string} addonName
 *   The extension's name, e.g. "adblockpluschrome".
 * @property {string} addonVersion
 *   The extension's version, e.g. "3.6.3".
 * @property {string} application
 *   The browser's name, e.g. "chrome".
 * @property {string} applicationVersion
 *   The browser's version, e.g. "77.0.3865.90".
 * @property {string} platform
 *   The browser platform, e.g. "chromium".
 * @property {string} platformVersion
 *   The browser platform's version, e.g. "77.0.3865.90".
 */

/**
 * Returns the browser platform information.
 *
 * @event "info.get"
 * @returns {infoGetResult}
 */
_messaging_port_js__WEBPACK_IMPORTED_MODULE_2__/* .port.on */ .N.on("info.get", (message, sender) => info__WEBPACK_IMPORTED_MODULE_0__);


/***/ }),

/***/ 5094:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "a": () => (/* binding */ installHandler)
/* harmony export */ });
/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9876);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



const cleanupByTabId = new Map();
const eventEmitter = new _events_js__WEBPACK_IMPORTED_MODULE_0__/* .EventEmitter */ .v();
const handlerByName = new Map();
const handlerTemplateByType = new Map();

/**
 * Installs a handler for lazily adding/removing event listeners depending on
 * whether someone is actively listening via the Messaging API.
 *
 * @param {string} type
 *   type of events to allow listening to
 * @param {string} [action]
 *   specific event to allow listening to
 *   null if handler applies to all events for the given type
 * @param {Function} install
 *   callback function for adding event listeners
 *   will receive emit, action, targetTabId as arguments
 *   expected to return callback function for removing event listeners
 */
function installHandler(type, action, install)
{
  const handler = {install, uninstall: null};

  // Handlers that can be used for arbitrary actions should be used as
  // templates, from which we can create handlers later
  if (!action)
  {
    handlerTemplateByType.set(type, handler);
    return;
  }

  handlerByName.set(`${type}.${action}`, handler);
}

function listen(type, actions, uiPort, targetTabId = null)
{
  const cleanups = [];

  for (const action of actions)
  {
    let name = `${type}.${action}`;
    if (targetTabId !== null)
      name = `${name}:${targetTabId}`;

    // Add message response listener
    const onResponse = (...args) =>
    {
      uiPort.postMessage({type: `${type}.respond`, action, args});
    };
    eventEmitter.on(name, onResponse);

    // Install event handler
    let handler = handlerByName.get(name);
    // If there's no handler for the given action, we should check
    // whether there's a generic handler for the type and create one from that
    if (!handler)
    {
      const template = handlerTemplateByType.get(type);
      if (template)
      {
        handler = Object.assign({}, template);
        handlerByName.set(name, handler);
      }
    }
    if (handler && !handler.uninstall)
    {
      const emit = eventEmitter.emit.bind(eventEmitter, name);
      handler.uninstall = handler.install(emit, action, targetTabId);
    }

    cleanups.push(() =>
    {
      eventEmitter.off(name, onResponse);

      // Uninstall event handler, if it's no longer needed
      if (!eventEmitter.hasListeners(name))
      {
        const actionHandler = handlerByName.get(name);
        if (actionHandler && actionHandler.uninstall)
        {
          actionHandler.uninstall();
          handler.uninstall = null;
        }
      }
    });
  }

  const cleanupAll = () =>
  {
    for (const cleanup of cleanups)
      cleanup();
  };

  // Stop listening when port disconnects (e.g. page is closed),
  // or when target tab is closed
  uiPort.onDisconnect.addListener(cleanupAll);
  if (targetTabId !== null)
    cleanupByTabId.set(targetTabId, cleanupAll);
}

function onTabRemoved(tabId)
{
  const cleanup = cleanupByTabId.get(tabId);
  if (!cleanup)
    return;

  cleanup();
  cleanupByTabId.delete(tabId);
}
browser.tabs.onRemoved.addListener(onTabRemoved);

function onConnect(uiPort)
{
  if (!ext.isTrustedSender(uiPort.sender))
    return;

  if (uiPort.name !== "ui")
    return;

  uiPort.onMessage.addListener(message =>
  {
    const [type, action] = message.type.split(".", 2);

    // For now we're only using long-lived connections
    // for handling "*.listen" messages
    // https://issues.adblockplus.org/ticket/6440/
    if (action !== "listen")
      return;

    listen(type, message.filter, uiPort, message.tabId);
  });
}
browser.runtime.onConnect.addListener(onConnect);


/***/ }),

/***/ 6960:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "N": () => (/* binding */ port)
/* harmony export */ });
/* harmony import */ var _events_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(9876);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



/**
 * Communication port wrapping ext.onMessage to receive messages.
 *
 * @constructor
 */
class Port
{
  constructor()
  {
    this._eventEmitter = new _events_js__WEBPACK_IMPORTED_MODULE_0__/* .EventEmitter */ .v();
    this._onMessage = this._onMessage.bind(this);
    ext.onMessage.addListener(this._onMessage);
  }

  async _onMessage(message, sender)
  {
    let callbacks = this._eventEmitter.listeners(message.type);

    try
    {
      let responses = callbacks.map(callback => callback(message, sender));
      return ext.getMessageResponse(responses);
    }
    catch (err)
    {
      console.error(err);
    }
  }

  /**
   * Function to be called when a particular message is received.
   *
   * @callback Port~messageCallback
   * @param {object} message
   * @param {object} sender
   * @return The callback can return undefined (no response),
   *         a value (response to be sent to sender immediately)
   *         or a promise (asynchronous response).
   */

  /**
   * Adds a callback for the specified message.
   *
   * The return value of the callback (if not undefined) is sent as response.
   * @param {string}   name
   * @param {Port~messageCallback} callback
   */
  on(name, callback)
  {
    this._eventEmitter.on(name, callback);
  }

  /**
   * Removes a callback for the specified message.
   *
   * @param {string}   name
   * @param {Port~messageCallback} callback
   */
  off(name, callback)
  {
    this._eventEmitter.off(name, callback);
  }

  /**
   * Disables the port and makes it stop listening to incoming messages.
   */
  disconnect()
  {
    ext.onMessage.removeListener(this._onMessage);
  }
}

/**
 * The default port to receive messages.
 *
 * @type {Port}
 */
let port = new Port();


/***/ }),

/***/ 6684:
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {

"use strict";
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */   "LC": () => (/* binding */ toPlainSubscription),
/* harmony export */   "N": () => (/* binding */ toPlainRecommendation),
/* harmony export */   "Q1": () => (/* binding */ toPlainBlockableItem),
/* harmony export */   "U_": () => (/* binding */ toPlainFilterError),
/* harmony export */   "ot": () => (/* binding */ toPlainFilter)
/* harmony export */ });
/* harmony import */ var _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(209);
/*
 * This file is part of Adblock Plus <https://adblockplus.org/>,
 * Copyright (C) 2006-present eyeo GmbH
 *
 * Adblock Plus is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation.
 *
 * Adblock Plus is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Adblock Plus.  If not, see <http://www.gnu.org/licenses/>.
 */



const requestMethods = new Set([
  "allowing",
  "header",
  "request"
]);

function toPlainBlockableItem({filter, matchInfo, request})
{
  let isFrame = !requestMethods.has(matchInfo.method);

  let type;
  if (matchInfo.method == "request")
    type = _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.reporting.contentTypesMap.get(request.type);
  else if (matchInfo.method == "allowing")
    type = matchInfo.allowingReason;
  // Show matching method when it had an effect on the request
  else if (filter)
    type = matchInfo.method;
  else
    type = _vendor_webext_sdk_dist_ewe_api_js__WEBPACK_IMPORTED_MODULE_0__.reporting.contentTypesMap.get(request.type);

  if (!type)
    type = "other";

  return {
    docDomain: matchInfo.docDomain,
    isFrame,
    rewrittenUrl: matchInfo.rewrittenUrl,
    type: type.toUpperCase(),
    url: request.url
  };
}

function toPlainFilter(filter)
{
  let obj = toPlainObject(
    ["csp", "enabled", "selector", "slow", "text", "type"],
    filter
  );

  // For the time being, we are renaming the enabled property to
  // make the UI compatible with EWE without having to rename it
  // in the UI code itself just yet
  // For the same reason, we're not adding the property for comment filters
  if (obj.enabled !== null)
    obj.disabled = !obj.enabled;
  delete obj.enabled;

  return obj;
}

let toPlainFilterError = toPlainObject.bind(null, [
  "lineno", "option", "reason", "type"
]);

function toPlainObject(keys, obj)
{
  let result = {};
  for (let key of keys)
  {
    if (key in obj)
      result[key] = obj[key];
  }
  return result;
}

function toPlainRecommendation(recommendation)
{
  // The recommendation URL always refers to the one for Manifest v3,
  // so we need to overwrite it for Manifest v2
  if (browser.runtime.getManifest().manifest_version === 2)
    recommendation.url = recommendation.mv2URL;

  return toPlainObject(
    ["languages", "title", "type", "url"],
    recommendation
  );
}

function toPlainSubscription(subscription)
{
  let obj = toPlainObject(
    [
      "downloadable", "downloadStatus", "enabled", "homepage", "version",
      "lastDownload", "lastSuccess", "softExpiration", "expires", "title",
      "url", "downloading"
    ],
    subscription
  );

  // For the time being, we are renaming the enabled property to
  // make the UI compatible with EWE without having to rename it
  // in the UI code itself just yet
  obj.disabled = !obj.enabled;
  delete obj.enabled;

  return obj;
}


/***/ })

/******/ 	});
/************************************************************************/
/******/ 	// The module cache
/******/ 	var __webpack_module_cache__ = {};
/******/ 	
/******/ 	// The require function
/******/ 	function __webpack_require__(moduleId) {
/******/ 		// Check if module is in cache
/******/ 		var cachedModule = __webpack_module_cache__[moduleId];
/******/ 		if (cachedModule !== undefined) {
/******/ 			return cachedModule.exports;
/******/ 		}
/******/ 		// Create a new module (and put it into the cache)
/******/ 		var module = __webpack_module_cache__[moduleId] = {
/******/ 			// no module.id needed
/******/ 			// no module.loaded needed
/******/ 			exports: {}
/******/ 		};
/******/ 	
/******/ 		// Execute the module function
/******/ 		__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/ 	
/******/ 		// Return the exports of the module
/******/ 		return module.exports;
/******/ 	}
/******/ 	
/************************************************************************/
/******/ 	/* webpack/runtime/compat get default export */
/******/ 	(() => {
/******/ 		// getDefaultExport function for compatibility with non-harmony modules
/******/ 		__webpack_require__.n = (module) => {
/******/ 			var getter = module && module.__esModule ?
/******/ 				() => (module['default']) :
/******/ 				() => (module);
/******/ 			__webpack_require__.d(getter, { a: getter });
/******/ 			return getter;
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/define property getters */
/******/ 	(() => {
/******/ 		// define getter functions for harmony exports
/******/ 		__webpack_require__.d = (exports, definition) => {
/******/ 			for(var key in definition) {
/******/ 				if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ 					Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ 				}
/******/ 			}
/******/ 		};
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/hasOwnProperty shorthand */
/******/ 	(() => {
/******/ 		__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ 	})();
/******/ 	
/******/ 	/* webpack/runtime/make namespace object */
/******/ 	(() => {
/******/ 		// define __esModule on exports
/******/ 		__webpack_require__.r = (exports) => {
/******/ 			if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ 				Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ 			}
/******/ 			Object.defineProperty(exports, '__esModule', { value: true });
/******/ 		};
/******/ 	})();
/******/ 	
/************************************************************************/
/******/ 	
/******/ 	// startup
/******/ 	// Load entry module and return exports
/******/ 	__webpack_require__(3890);
/******/ 	// This entry module is referenced by other modules so it can't be inlined
/******/ 	__webpack_require__(7330);
/******/ 	__webpack_require__(4921);
/******/ 	__webpack_require__(9685);
/******/ 	__webpack_require__(704);
/******/ 	__webpack_require__(7590);
/******/ 	__webpack_require__(7526);
/******/ 	__webpack_require__(8240);
/******/ 	__webpack_require__(1940);
/******/ 	__webpack_require__(228);
/******/ 	__webpack_require__(1478);
/******/ 	__webpack_require__(965);
/******/ 	__webpack_require__(6392);
/******/ 	__webpack_require__(211);
/******/ 	__webpack_require__(3398);
/******/ 	__webpack_require__(9667);
/******/ 	__webpack_require__(1926);
/******/ 	__webpack_require__(4214);
/******/ 	__webpack_require__(9769);
/******/ 	__webpack_require__(3473);
/******/ 	__webpack_require__(4983);
/******/ 	__webpack_require__(6798);
/******/ 	__webpack_require__(9164);
/******/ 	__webpack_require__(4245);
/******/ 	__webpack_require__(6141);
/******/ 	var __webpack_exports__ = __webpack_require__(4716);
/******/ 	
/******/ })()
;