1
0

single-file-frames.js 56 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392
  1. (function (global, factory) {
  2. typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
  3. typeof define === 'function' && define.amd ? define(['exports'], factory) :
  4. (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.singlefile = {}));
  5. })(this, (function (exports) { 'use strict';
  6. /*
  7. * Copyright 2010-2022 Gildas Lormeau
  8. * contact : gildas.lormeau <at> gmail.com
  9. *
  10. * This file is part of SingleFile.
  11. *
  12. * The code in this file is free software: you can redistribute it and/or
  13. * modify it under the terms of the GNU Affero General Public License
  14. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  15. * of the License, or (at your option) any later version.
  16. *
  17. * The code in this file is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  20. * General Public License for more details.
  21. *
  22. * As additional permission under GNU AGPL version 3 section 7, you may
  23. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  24. * AGPL normally required by section 4, provided you include this license
  25. * notice and a URL through which recipients can access the Corresponding
  26. * Source.
  27. */
  28. /* global globalThis, window */
  29. const LOAD_DEFERRED_IMAGES_START_EVENT = "single-file-load-deferred-images-start";
  30. const LOAD_DEFERRED_IMAGES_END_EVENT = "single-file-load-deferred-images-end";
  31. const LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_START_EVENT = "single-file-load-deferred-images-keep-zoom-level-start";
  32. const LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_END_EVENT = "single-file-load-deferred-images-keep-zoom-level-end";
  33. const BLOCK_COOKIES_START_EVENT = "single-file-block-cookies-start";
  34. const BLOCK_COOKIES_END_EVENT = "single-file-block-cookies-end";
  35. const DISPATCH_SCROLL_START_EVENT = "single-file-dispatch-scroll-event-start";
  36. const DISPATCH_SCROLL_END_EVENT = "single-file-dispatch-scroll-event-end";
  37. const BLOCK_STORAGE_START_EVENT = "single-file-block-storage-start";
  38. const BLOCK_STORAGE_END_EVENT = "single-file-block-storage-end";
  39. const LOAD_IMAGE_EVENT = "single-file-load-image";
  40. const IMAGE_LOADED_EVENT = "single-file-image-loaded";
  41. const NEW_FONT_FACE_EVENT = "single-file-new-font-face";
  42. const DELETE_FONT_EVENT = "single-file-delete-font";
  43. const CLEAR_FONTS_EVENT = "single-file-clear-fonts";
  44. const FONT_FACE_PROPERTY_NAME = "_singleFile_fontFaces";
  45. const CustomEvent$1 = globalThis.CustomEvent;
  46. const document$2 = globalThis.document;
  47. const Document = globalThis.Document;
  48. const JSON$2 = globalThis.JSON;
  49. const MutationObserver$2 = globalThis.MutationObserver;
  50. let fontFaces;
  51. if (window[FONT_FACE_PROPERTY_NAME]) {
  52. fontFaces = window[FONT_FACE_PROPERTY_NAME];
  53. } else {
  54. fontFaces = window[FONT_FACE_PROPERTY_NAME] = new Map();
  55. }
  56. init$1();
  57. new MutationObserver$2(init$1).observe(document$2, { childList: true });
  58. function init$1() {
  59. if (document$2 instanceof Document) {
  60. document$2.addEventListener(NEW_FONT_FACE_EVENT, event => {
  61. const detail = event.detail;
  62. const key = Object.assign({}, detail);
  63. delete key.src;
  64. fontFaces.set(JSON$2.stringify(key), detail);
  65. });
  66. document$2.addEventListener(DELETE_FONT_EVENT, event => {
  67. const detail = event.detail;
  68. const key = Object.assign({}, detail);
  69. delete key.src;
  70. fontFaces.delete(JSON$2.stringify(key));
  71. });
  72. document$2.addEventListener(CLEAR_FONTS_EVENT, () => fontFaces = new Map());
  73. }
  74. }
  75. function getFontsData$1() {
  76. return Array.from(fontFaces.values());
  77. }
  78. function loadDeferredImagesStart(options) {
  79. if (options.loadDeferredImagesBlockCookies) {
  80. document$2.dispatchEvent(new CustomEvent$1(BLOCK_COOKIES_START_EVENT));
  81. }
  82. if (options.loadDeferredImagesBlockStorage) {
  83. document$2.dispatchEvent(new CustomEvent$1(BLOCK_STORAGE_START_EVENT));
  84. }
  85. if (options.loadDeferredImagesDispatchScrollEvent) {
  86. document$2.dispatchEvent(new CustomEvent$1(DISPATCH_SCROLL_START_EVENT));
  87. }
  88. if (options.loadDeferredImagesKeepZoomLevel) {
  89. document$2.dispatchEvent(new CustomEvent$1(LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_START_EVENT));
  90. } else {
  91. document$2.dispatchEvent(new CustomEvent$1(LOAD_DEFERRED_IMAGES_START_EVENT));
  92. }
  93. }
  94. function loadDeferredImagesEnd(options) {
  95. if (options.loadDeferredImagesBlockCookies) {
  96. document$2.dispatchEvent(new CustomEvent$1(BLOCK_COOKIES_END_EVENT));
  97. }
  98. if (options.loadDeferredImagesBlockStorage) {
  99. document$2.dispatchEvent(new CustomEvent$1(BLOCK_STORAGE_END_EVENT));
  100. }
  101. if (options.loadDeferredImagesDispatchScrollEvent) {
  102. document$2.dispatchEvent(new CustomEvent$1(DISPATCH_SCROLL_END_EVENT));
  103. }
  104. if (options.loadDeferredImagesKeepZoomLevel) {
  105. document$2.dispatchEvent(new CustomEvent$1(LOAD_DEFERRED_IMAGES_KEEP_ZOOM_LEVEL_END_EVENT));
  106. } else {
  107. document$2.dispatchEvent(new CustomEvent$1(LOAD_DEFERRED_IMAGES_END_EVENT));
  108. }
  109. }
  110. /*
  111. * The MIT License (MIT)
  112. *
  113. * Author: Gildas Lormeau
  114. *
  115. * Permission is hereby granted, free of charge, to any person obtaining a copy
  116. * of this software and associated documentation files (the "Software"), to deal
  117. * in the Software without restriction, including without limitation the rights
  118. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  119. * copies of the Software, and to permit persons to whom the Software is
  120. * furnished to do so, subject to the following conditions:
  121. *
  122. * The above copyright notice and this permission notice shall be included in all
  123. * copies or substantial portions of the Software.
  124. *
  125. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  126. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  127. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  128. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  129. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  130. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  131. * SOFTWARE.
  132. */
  133. // derived from https://github.com/postcss/postcss-selector-parser/blob/master/src/util/unesc.js
  134. /*
  135. * The MIT License (MIT)
  136. * Copyright (c) Ben Briggs <beneb.info@gmail.com> (http://beneb.info)
  137. *
  138. * Permission is hereby granted, free of charge, to any person obtaining a copy
  139. * of this software and associated documentation files (the "Software"), to deal
  140. * in the Software without restriction, including without limitation the rights
  141. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  142. * copies of the Software, and to permit persons to whom the Software is
  143. * furnished to do so, subject to the following conditions:
  144. *
  145. * The above copyright notice and this permission notice shall be included in
  146. * all copies or substantial portions of the Software.
  147. *
  148. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  149. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  150. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  151. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  152. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  153. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  154. * THE SOFTWARE.
  155. */
  156. const whitespace = "[\\x20\\t\\r\\n\\f]";
  157. const unescapeRegExp = new RegExp("\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig");
  158. function process$1(str) {
  159. return str.replace(unescapeRegExp, (_, escaped, escapedWhitespace) => {
  160. const high = "0x" + escaped - 0x10000;
  161. // NaN means non-codepoint
  162. // Workaround erroneous numeric interpretation of +"0x"
  163. // eslint-disable-next-line no-self-compare
  164. return high !== high || escapedWhitespace
  165. ? escaped
  166. : high < 0
  167. ? // BMP codepoint
  168. String.fromCharCode(high + 0x10000)
  169. : // Supplemental Plane codepoint (surrogate pair)
  170. String.fromCharCode((high >> 10) | 0xd800, (high & 0x3ff) | 0xdc00);
  171. });
  172. }
  173. const SINGLE_FILE_PREFIX = "single-file-";
  174. const WAIT_FOR_USERSCRIPT_PROPERTY_NAME = "_singleFile_waitForUserScript";
  175. const MESSAGE_PREFIX = "__frameTree__::";
  176. /*
  177. * Copyright 2010-2022 Gildas Lormeau
  178. * contact : gildas.lormeau <at> gmail.com
  179. *
  180. * This file is part of SingleFile.
  181. *
  182. * The code in this file is free software: you can redistribute it and/or
  183. * modify it under the terms of the GNU Affero General Public License
  184. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  185. * of the License, or (at your option) any later version.
  186. *
  187. * The code in this file is distributed in the hope that it will be useful,
  188. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  189. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  190. * General Public License for more details.
  191. *
  192. * As additional permission under GNU AGPL version 3 section 7, you may
  193. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  194. * AGPL normally required by section 4, provided you include this license
  195. * notice and a URL through which recipients can access the Corresponding
  196. * Source.
  197. */
  198. const INFOBAR_TAGNAME$1 = "single-file-infobar";
  199. /*
  200. * Copyright 2010-2022 Gildas Lormeau
  201. * contact : gildas.lormeau <at> gmail.com
  202. *
  203. * This file is part of SingleFile.
  204. *
  205. * The code in this file is free software: you can redistribute it and/or
  206. * modify it under the terms of the GNU Affero General Public License
  207. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  208. * of the License, or (at your option) any later version.
  209. *
  210. * The code in this file is distributed in the hope that it will be useful,
  211. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  212. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  213. * General Public License for more details.
  214. *
  215. * As additional permission under GNU AGPL version 3 section 7, you may
  216. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  217. * AGPL normally required by section 4, provided you include this license
  218. * notice and a URL through which recipients can access the Corresponding
  219. * Source.
  220. */
  221. const ON_BEFORE_CAPTURE_EVENT_NAME = SINGLE_FILE_PREFIX + "on-before-capture";
  222. const ON_AFTER_CAPTURE_EVENT_NAME = SINGLE_FILE_PREFIX + "on-after-capture";
  223. const GET_ADOPTED_STYLESHEETS_REQUEST_EVENT = SINGLE_FILE_PREFIX + "request-get-adopted-stylesheets";
  224. const GET_ADOPTED_STYLESHEETS_RESPONSE_EVENT = SINGLE_FILE_PREFIX + "response-get-adopted-stylesheets";
  225. const UNREGISTER_GET_ADOPTED_STYLESHEETS_REQUEST_EVENT = SINGLE_FILE_PREFIX + "unregister-request-get-adopted-stylesheets";
  226. const REMOVED_CONTENT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "removed-content";
  227. const HIDDEN_CONTENT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "hidden-content";
  228. const KEPT_CONTENT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "kept-content";
  229. const HIDDEN_FRAME_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "hidden-frame";
  230. const PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "preserved-space-element";
  231. const SHADOW_ROOT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "shadow-root-element";
  232. const WIN_ID_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "win-id";
  233. const IMAGE_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "image";
  234. const POSTER_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "poster";
  235. const VIDEO_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "video";
  236. const CANVAS_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "canvas";
  237. const STYLE_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "movable-style";
  238. const INPUT_VALUE_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "input-value";
  239. const LAZY_SRC_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "lazy-loaded-src";
  240. const STYLESHEET_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "stylesheet";
  241. const DISABLED_NOSCRIPT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "disabled-noscript";
  242. const INVALID_ELEMENT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "invalid-element";
  243. const ASYNC_SCRIPT_ATTRIBUTE_NAME = "data-" + SINGLE_FILE_PREFIX + "async-script";
  244. const FLOW_ELEMENTS_SELECTOR = "*:not(base):not(link):not(meta):not(noscript):not(script):not(style):not(template):not(title)";
  245. const KEPT_TAG_NAMES = ["NOSCRIPT", "DISABLED-NOSCRIPT", "META", "LINK", "STYLE", "TITLE", "TEMPLATE", "SOURCE", "OBJECT", "SCRIPT", "HEAD", "BODY"];
  246. const IGNORED_TAG_NAMES = ["SCRIPT", "NOSCRIPT", "META", "LINK", "TEMPLATE"];
  247. const REGEXP_SIMPLE_QUOTES_STRING = /^'(.*?)'$/;
  248. const REGEXP_DOUBLE_QUOTES_STRING = /^"(.*?)"$/;
  249. const FONT_WEIGHTS = {
  250. regular: "400",
  251. normal: "400",
  252. bold: "700",
  253. bolder: "700",
  254. lighter: "100"
  255. };
  256. const SINGLE_FILE_UI_ELEMENT_CLASS = "single-file-ui-element";
  257. const INFOBAR_TAGNAME = INFOBAR_TAGNAME$1;
  258. const EMPTY_RESOURCE = "data:,";
  259. const JSON$1 = globalThis.JSON;
  260. const CustomEvent = globalThis.CustomEvent;
  261. function initDoc(doc) {
  262. doc.querySelectorAll("meta[http-equiv=refresh]").forEach(element => {
  263. element.removeAttribute("http-equiv");
  264. element.setAttribute("disabled-http-equiv", "refresh");
  265. });
  266. }
  267. function preProcessDoc(doc, win, options) {
  268. doc.querySelectorAll("noscript:not([" + DISABLED_NOSCRIPT_ATTRIBUTE_NAME + "])").forEach(element => {
  269. element.setAttribute(DISABLED_NOSCRIPT_ATTRIBUTE_NAME, element.textContent);
  270. element.textContent = "";
  271. });
  272. initDoc(doc);
  273. if (doc.head) {
  274. doc.head.querySelectorAll(FLOW_ELEMENTS_SELECTOR).forEach(element => element.hidden = true);
  275. }
  276. doc.querySelectorAll("svg foreignObject").forEach(element => {
  277. const flowElements = element.querySelectorAll("html > head > " + FLOW_ELEMENTS_SELECTOR + ", html > body > " + FLOW_ELEMENTS_SELECTOR);
  278. if (flowElements.length) {
  279. Array.from(element.childNodes).forEach(node => node.remove());
  280. flowElements.forEach(flowElement => element.appendChild(flowElement));
  281. }
  282. });
  283. const invalidElements = new Map();
  284. let elementsInfo;
  285. if (win && doc.documentElement) {
  286. doc.querySelectorAll("button button, a a").forEach(element => {
  287. const placeHolderElement = doc.createElement("template");
  288. placeHolderElement.setAttribute(INVALID_ELEMENT_ATTRIBUTE_NAME, "");
  289. placeHolderElement.content.appendChild(element.cloneNode(true));
  290. invalidElements.set(element, placeHolderElement);
  291. element.replaceWith(placeHolderElement);
  292. });
  293. elementsInfo = getElementsInfo(win, doc, doc.documentElement, options);
  294. if (options.moveStylesInHead) {
  295. doc.querySelectorAll("body style, body ~ style").forEach(element => {
  296. const computedStyle = getComputedStyle(win, element);
  297. if (computedStyle && testHiddenElement(element, computedStyle)) {
  298. element.setAttribute(STYLE_ATTRIBUTE_NAME, "");
  299. elementsInfo.markedElements.push(element);
  300. }
  301. });
  302. }
  303. } else {
  304. elementsInfo = {
  305. canvases: [],
  306. images: [],
  307. posters: [],
  308. videos: [],
  309. usedFonts: [],
  310. shadowRoots: [],
  311. markedElements: []
  312. };
  313. }
  314. return {
  315. canvases: elementsInfo.canvases,
  316. fonts: getFontsData(),
  317. stylesheets: getStylesheetsData(doc),
  318. images: elementsInfo.images,
  319. posters: elementsInfo.posters,
  320. videos: elementsInfo.videos,
  321. usedFonts: Array.from(elementsInfo.usedFonts.values()),
  322. shadowRoots: elementsInfo.shadowRoots,
  323. referrer: doc.referrer,
  324. markedElements: elementsInfo.markedElements,
  325. invalidElements,
  326. scrollPosition: { x: win.scrollX, y: win.scrollY },
  327. adoptedStyleSheets: getStylesheetsContent(doc.adoptedStyleSheets)
  328. };
  329. }
  330. function getElementsInfo(win, doc, element, options, data = { usedFonts: new Map(), canvases: [], images: [], posters: [], videos: [], shadowRoots: [], markedElements: [] }, ascendantHidden) {
  331. if (element.childNodes) {
  332. const elements = Array.from(element.childNodes).filter(node => (node instanceof win.HTMLElement) || (node instanceof win.SVGElement) || (node instanceof globalThis.HTMLElement) || (node instanceof globalThis.SVGElement));
  333. elements.forEach(element => {
  334. let elementHidden, elementKept, computedStyle;
  335. if (!options.autoSaveExternalSave && (options.removeHiddenElements || options.removeUnusedFonts || options.compressHTML)) {
  336. computedStyle = getComputedStyle(win, element);
  337. if ((element instanceof win.HTMLElement) || (element instanceof globalThis.HTMLElement)) {
  338. if (options.removeHiddenElements) {
  339. elementKept = ((ascendantHidden || element.closest("html > head")) && KEPT_TAG_NAMES.includes(element.tagName.toUpperCase())) || element.closest("details");
  340. if (!elementKept) {
  341. elementHidden = ascendantHidden || testHiddenElement(element, computedStyle);
  342. if (elementHidden && !IGNORED_TAG_NAMES.includes(element.tagName.toUpperCase())) {
  343. element.setAttribute(HIDDEN_CONTENT_ATTRIBUTE_NAME, "");
  344. data.markedElements.push(element);
  345. }
  346. }
  347. }
  348. }
  349. if (!elementHidden) {
  350. if (options.compressHTML && computedStyle) {
  351. const whiteSpace = computedStyle.getPropertyValue("white-space");
  352. if (whiteSpace && whiteSpace.startsWith("pre")) {
  353. element.setAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME, "");
  354. data.markedElements.push(element);
  355. }
  356. }
  357. if (options.removeUnusedFonts) {
  358. getUsedFont(computedStyle, options, data.usedFonts);
  359. getUsedFont(getComputedStyle(win, element, ":first-letter"), options, data.usedFonts);
  360. getUsedFont(getComputedStyle(win, element, ":before"), options, data.usedFonts);
  361. getUsedFont(getComputedStyle(win, element, ":after"), options, data.usedFonts);
  362. }
  363. }
  364. }
  365. getResourcesInfo(win, doc, element, options, data, elementHidden, computedStyle);
  366. const shadowRoot = !((element instanceof win.SVGElement) || (element instanceof globalThis.SVGElement)) && getShadowRoot(element);
  367. if (shadowRoot && !element.classList.contains(SINGLE_FILE_UI_ELEMENT_CLASS) && element.tagName.toLowerCase() != INFOBAR_TAGNAME) {
  368. const shadowRootInfo = {};
  369. element.setAttribute(SHADOW_ROOT_ATTRIBUTE_NAME, data.shadowRoots.length);
  370. data.markedElements.push(element);
  371. data.shadowRoots.push(shadowRootInfo);
  372. try {
  373. if (shadowRoot.adoptedStyleSheets) {
  374. if (shadowRoot.adoptedStyleSheets.length) {
  375. shadowRootInfo.adoptedStyleSheets = getStylesheetsContent(shadowRoot.adoptedStyleSheets);
  376. } else if (shadowRoot.adoptedStyleSheets.length === undefined) {
  377. const listener = event => shadowRootInfo.adoptedStyleSheets = event.detail.adoptedStyleSheets;
  378. shadowRoot.addEventListener(GET_ADOPTED_STYLESHEETS_RESPONSE_EVENT, listener);
  379. shadowRoot.dispatchEvent(new CustomEvent(GET_ADOPTED_STYLESHEETS_REQUEST_EVENT, { bubbles: true }));
  380. if (!shadowRootInfo.adoptedStyleSheets) {
  381. element.dispatchEvent(new CustomEvent(GET_ADOPTED_STYLESHEETS_REQUEST_EVENT, { bubbles: true }));
  382. }
  383. shadowRoot.removeEventListener(GET_ADOPTED_STYLESHEETS_RESPONSE_EVENT, listener);
  384. }
  385. }
  386. } catch (error) {
  387. // ignored
  388. }
  389. getElementsInfo(win, doc, shadowRoot, options, data, elementHidden);
  390. shadowRootInfo.content = shadowRoot.innerHTML;
  391. shadowRootInfo.mode = shadowRoot.mode;
  392. try {
  393. if (shadowRoot.adoptedStyleSheets && shadowRoot.adoptedStyleSheets.length === undefined) {
  394. shadowRoot.dispatchEvent(new CustomEvent(UNREGISTER_GET_ADOPTED_STYLESHEETS_REQUEST_EVENT, { bubbles: true }));
  395. }
  396. } catch (error) {
  397. // ignored
  398. }
  399. }
  400. getElementsInfo(win, doc, element, options, data, elementHidden);
  401. if (!options.autoSaveExternalSave && options.removeHiddenElements && ascendantHidden) {
  402. if (elementKept || element.getAttribute(KEPT_CONTENT_ATTRIBUTE_NAME) == "") {
  403. if (element.parentElement) {
  404. element.parentElement.setAttribute(KEPT_CONTENT_ATTRIBUTE_NAME, "");
  405. data.markedElements.push(element.parentElement);
  406. }
  407. } else if (elementHidden) {
  408. element.setAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME, "");
  409. data.markedElements.push(element);
  410. }
  411. }
  412. });
  413. }
  414. return data;
  415. }
  416. function getStylesheetsContent(styleSheets) {
  417. return styleSheets ? Array.from(styleSheets).map(stylesheet => Array.from(stylesheet.cssRules).map(cssRule => cssRule.cssText).join("\n")) : [];
  418. }
  419. function getResourcesInfo(win, doc, element, options, data, elementHidden, computedStyle) {
  420. const tagName = element.tagName && element.tagName.toUpperCase();
  421. if (tagName == "CANVAS") {
  422. try {
  423. data.canvases.push({
  424. dataURI: element.toDataURL("image/png", ""),
  425. backgroundColor: computedStyle.getPropertyValue("background-color")
  426. });
  427. element.setAttribute(CANVAS_ATTRIBUTE_NAME, data.canvases.length - 1);
  428. data.markedElements.push(element);
  429. } catch (error) {
  430. // ignored
  431. }
  432. }
  433. if (tagName == "IMG") {
  434. const imageData = {
  435. currentSrc: elementHidden ?
  436. EMPTY_RESOURCE :
  437. (options.loadDeferredImages && element.getAttribute(LAZY_SRC_ATTRIBUTE_NAME)) || element.currentSrc
  438. };
  439. data.images.push(imageData);
  440. element.setAttribute(IMAGE_ATTRIBUTE_NAME, data.images.length - 1);
  441. data.markedElements.push(element);
  442. element.removeAttribute(LAZY_SRC_ATTRIBUTE_NAME);
  443. computedStyle = computedStyle || getComputedStyle(win, element);
  444. if (computedStyle) {
  445. imageData.size = getSize(win, element, computedStyle);
  446. const boxShadow = computedStyle.getPropertyValue("box-shadow");
  447. const backgroundImage = computedStyle.getPropertyValue("background-image");
  448. if ((!boxShadow || boxShadow == "none") &&
  449. (!backgroundImage || backgroundImage == "none") &&
  450. (imageData.size.pxWidth > 1 || imageData.size.pxHeight > 1)) {
  451. imageData.replaceable = true;
  452. imageData.backgroundColor = computedStyle.getPropertyValue("background-color");
  453. imageData.objectFit = computedStyle.getPropertyValue("object-fit");
  454. imageData.boxSizing = computedStyle.getPropertyValue("box-sizing");
  455. imageData.objectPosition = computedStyle.getPropertyValue("object-position");
  456. }
  457. }
  458. }
  459. if (tagName == "VIDEO") {
  460. const src = element.currentSrc;
  461. if (src && !src.startsWith("blob:") && !src.startsWith("data:")) {
  462. const computedStyle = getComputedStyle(win, element.parentNode);
  463. data.videos.push({
  464. positionParent: computedStyle && computedStyle.getPropertyValue("position"),
  465. src,
  466. size: {
  467. pxWidth: element.clientWidth,
  468. pxHeight: element.clientHeight
  469. },
  470. currentTime: element.currentTime
  471. });
  472. element.setAttribute(VIDEO_ATTRIBUTE_NAME, data.videos.length - 1);
  473. }
  474. if (!element.getAttribute("poster")) {
  475. const canvasElement = doc.createElement("canvas");
  476. const context = canvasElement.getContext("2d");
  477. canvasElement.width = element.clientWidth;
  478. canvasElement.height = element.clientHeight;
  479. try {
  480. context.drawImage(element, 0, 0, canvasElement.width, canvasElement.height);
  481. data.posters.push(canvasElement.toDataURL("image/png", ""));
  482. element.setAttribute(POSTER_ATTRIBUTE_NAME, data.posters.length - 1);
  483. data.markedElements.push(element);
  484. } catch (error) {
  485. // ignored
  486. }
  487. }
  488. }
  489. if (tagName == "IFRAME") {
  490. if (elementHidden && options.removeHiddenElements) {
  491. element.setAttribute(HIDDEN_FRAME_ATTRIBUTE_NAME, "");
  492. data.markedElements.push(element);
  493. }
  494. }
  495. if (tagName == "INPUT") {
  496. if (element.type != "password") {
  497. element.setAttribute(INPUT_VALUE_ATTRIBUTE_NAME, element.value);
  498. data.markedElements.push(element);
  499. }
  500. if (element.type == "radio" || element.type == "checkbox") {
  501. element.setAttribute(INPUT_VALUE_ATTRIBUTE_NAME, element.checked);
  502. data.markedElements.push(element);
  503. }
  504. }
  505. if (tagName == "TEXTAREA") {
  506. element.setAttribute(INPUT_VALUE_ATTRIBUTE_NAME, element.value);
  507. data.markedElements.push(element);
  508. }
  509. if (tagName == "SELECT") {
  510. element.querySelectorAll("option").forEach(option => {
  511. if (option.selected) {
  512. option.setAttribute(INPUT_VALUE_ATTRIBUTE_NAME, "");
  513. data.markedElements.push(option);
  514. }
  515. });
  516. }
  517. if (tagName == "SCRIPT") {
  518. if (element.async && element.getAttribute("async") != "" && element.getAttribute("async") != "async") {
  519. element.setAttribute(ASYNC_SCRIPT_ATTRIBUTE_NAME, "");
  520. data.markedElements.push(element);
  521. }
  522. element.textContent = element.textContent.replace(/<\/script>/gi, "<\\/script>");
  523. }
  524. }
  525. function getUsedFont(computedStyle, options, usedFonts) {
  526. if (computedStyle) {
  527. const fontStyle = computedStyle.getPropertyValue("font-style") || "normal";
  528. computedStyle.getPropertyValue("font-family").split(",").forEach(fontFamilyName => {
  529. fontFamilyName = normalizeFontFamily(fontFamilyName);
  530. if (!options.loadedFonts || options.loadedFonts.find(font => normalizeFontFamily(font.family) == fontFamilyName && font.style == fontStyle)) {
  531. const fontWeight = getFontWeight(computedStyle.getPropertyValue("font-weight"));
  532. const fontVariant = computedStyle.getPropertyValue("font-variant") || "normal";
  533. const value = [fontFamilyName, fontWeight, fontStyle, fontVariant];
  534. usedFonts.set(JSON$1.stringify(value), [fontFamilyName, fontWeight, fontStyle, fontVariant]);
  535. }
  536. });
  537. }
  538. }
  539. function getShadowRoot(element) {
  540. const chrome = globalThis.chrome;
  541. if (element.openOrClosedShadowRoot) {
  542. return element.openOrClosedShadowRoot;
  543. } else if (chrome && chrome.dom && chrome.dom.openOrClosedShadowRoot) {
  544. try {
  545. return chrome.dom.openOrClosedShadowRoot(element);
  546. } catch (error) {
  547. return element.shadowRoot;
  548. }
  549. } else {
  550. return element.shadowRoot;
  551. }
  552. }
  553. function normalizeFontFamily(fontFamilyName = "") {
  554. return removeQuotes(process$1(fontFamilyName.trim())).toLowerCase();
  555. }
  556. function testHiddenElement(element, computedStyle) {
  557. let hidden = false;
  558. if (computedStyle) {
  559. const display = computedStyle.getPropertyValue("display");
  560. const opacity = computedStyle.getPropertyValue("opacity");
  561. const visibility = computedStyle.getPropertyValue("visibility");
  562. hidden = display == "none";
  563. if (!hidden && (opacity == "0" || visibility == "hidden") && element.getBoundingClientRect) {
  564. const boundingRect = element.getBoundingClientRect();
  565. hidden = !boundingRect.width && !boundingRect.height;
  566. }
  567. }
  568. return Boolean(hidden);
  569. }
  570. function postProcessDoc(doc, markedElements, invalidElements) {
  571. doc.querySelectorAll("[" + DISABLED_NOSCRIPT_ATTRIBUTE_NAME + "]").forEach(element => {
  572. element.textContent = element.getAttribute(DISABLED_NOSCRIPT_ATTRIBUTE_NAME);
  573. element.removeAttribute(DISABLED_NOSCRIPT_ATTRIBUTE_NAME);
  574. });
  575. doc.querySelectorAll("meta[disabled-http-equiv]").forEach(element => {
  576. element.setAttribute("http-equiv", element.getAttribute("disabled-http-equiv"));
  577. element.removeAttribute("disabled-http-equiv");
  578. });
  579. if (doc.head) {
  580. doc.head.querySelectorAll("*:not(base):not(link):not(meta):not(noscript):not(script):not(style):not(template):not(title)").forEach(element => element.removeAttribute("hidden"));
  581. }
  582. if (!markedElements) {
  583. const singleFileAttributes = [REMOVED_CONTENT_ATTRIBUTE_NAME, HIDDEN_FRAME_ATTRIBUTE_NAME, HIDDEN_CONTENT_ATTRIBUTE_NAME, PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME, IMAGE_ATTRIBUTE_NAME, POSTER_ATTRIBUTE_NAME, VIDEO_ATTRIBUTE_NAME, CANVAS_ATTRIBUTE_NAME, INPUT_VALUE_ATTRIBUTE_NAME, SHADOW_ROOT_ATTRIBUTE_NAME, STYLESHEET_ATTRIBUTE_NAME, ASYNC_SCRIPT_ATTRIBUTE_NAME];
  584. markedElements = doc.querySelectorAll(singleFileAttributes.map(name => "[" + name + "]").join(","));
  585. }
  586. markedElements.forEach(element => {
  587. element.removeAttribute(REMOVED_CONTENT_ATTRIBUTE_NAME);
  588. element.removeAttribute(HIDDEN_CONTENT_ATTRIBUTE_NAME);
  589. element.removeAttribute(KEPT_CONTENT_ATTRIBUTE_NAME);
  590. element.removeAttribute(HIDDEN_FRAME_ATTRIBUTE_NAME);
  591. element.removeAttribute(PRESERVED_SPACE_ELEMENT_ATTRIBUTE_NAME);
  592. element.removeAttribute(IMAGE_ATTRIBUTE_NAME);
  593. element.removeAttribute(POSTER_ATTRIBUTE_NAME);
  594. element.removeAttribute(VIDEO_ATTRIBUTE_NAME);
  595. element.removeAttribute(CANVAS_ATTRIBUTE_NAME);
  596. element.removeAttribute(INPUT_VALUE_ATTRIBUTE_NAME);
  597. element.removeAttribute(SHADOW_ROOT_ATTRIBUTE_NAME);
  598. element.removeAttribute(STYLESHEET_ATTRIBUTE_NAME);
  599. element.removeAttribute(ASYNC_SCRIPT_ATTRIBUTE_NAME);
  600. element.removeAttribute(STYLE_ATTRIBUTE_NAME);
  601. });
  602. if (invalidElements) {
  603. invalidElements.forEach((placeholderElement, element) => placeholderElement.replaceWith(element));
  604. }
  605. }
  606. function getStylesheetsData(doc) {
  607. if (doc) {
  608. const contents = [];
  609. doc.querySelectorAll("style").forEach((styleElement, styleIndex) => {
  610. try {
  611. if (!styleElement.sheet.disabled) {
  612. const tempStyleElement = doc.createElement("style");
  613. tempStyleElement.textContent = styleElement.textContent;
  614. doc.body.appendChild(tempStyleElement);
  615. const stylesheet = tempStyleElement.sheet;
  616. tempStyleElement.remove();
  617. const textContentStylesheet = Array.from(stylesheet.cssRules).map(cssRule => cssRule.cssText).join("\n");
  618. const sheetStylesheet = Array.from(styleElement.sheet.cssRules).map(cssRule => cssRule.cssText).join("\n");
  619. if (!stylesheet || textContentStylesheet != sheetStylesheet) {
  620. styleElement.setAttribute(STYLESHEET_ATTRIBUTE_NAME, styleIndex);
  621. contents[styleIndex] = Array.from(styleElement.sheet.cssRules).map(cssRule => cssRule.cssText).join("\n");
  622. }
  623. }
  624. } catch (error) {
  625. // ignored
  626. }
  627. });
  628. return contents;
  629. }
  630. }
  631. function getSize(win, imageElement, computedStyle) {
  632. let pxWidth = imageElement.naturalWidth;
  633. let pxHeight = imageElement.naturalHeight;
  634. if (!pxWidth && !pxHeight) {
  635. const noStyleAttribute = imageElement.getAttribute("style") == null;
  636. computedStyle = computedStyle || getComputedStyle(win, imageElement);
  637. if (computedStyle) {
  638. let removeBorderWidth = false;
  639. if (computedStyle.getPropertyValue("box-sizing") == "content-box") {
  640. const boxSizingValue = imageElement.style.getPropertyValue("box-sizing");
  641. const boxSizingPriority = imageElement.style.getPropertyPriority("box-sizing");
  642. const clientWidth = imageElement.clientWidth;
  643. imageElement.style.setProperty("box-sizing", "border-box", "important");
  644. removeBorderWidth = imageElement.clientWidth != clientWidth;
  645. if (boxSizingValue) {
  646. imageElement.style.setProperty("box-sizing", boxSizingValue, boxSizingPriority);
  647. } else {
  648. imageElement.style.removeProperty("box-sizing");
  649. }
  650. }
  651. let paddingLeft, paddingRight, paddingTop, paddingBottom, borderLeft, borderRight, borderTop, borderBottom;
  652. paddingLeft = getWidth("padding-left", computedStyle);
  653. paddingRight = getWidth("padding-right", computedStyle);
  654. paddingTop = getWidth("padding-top", computedStyle);
  655. paddingBottom = getWidth("padding-bottom", computedStyle);
  656. if (removeBorderWidth) {
  657. borderLeft = getWidth("border-left-width", computedStyle);
  658. borderRight = getWidth("border-right-width", computedStyle);
  659. borderTop = getWidth("border-top-width", computedStyle);
  660. borderBottom = getWidth("border-bottom-width", computedStyle);
  661. } else {
  662. borderLeft = borderRight = borderTop = borderBottom = 0;
  663. }
  664. pxWidth = Math.max(0, imageElement.clientWidth - paddingLeft - paddingRight - borderLeft - borderRight);
  665. pxHeight = Math.max(0, imageElement.clientHeight - paddingTop - paddingBottom - borderTop - borderBottom);
  666. if (noStyleAttribute) {
  667. imageElement.removeAttribute("style");
  668. }
  669. }
  670. }
  671. return { pxWidth, pxHeight };
  672. }
  673. function getWidth(styleName, computedStyle) {
  674. if (computedStyle.getPropertyValue(styleName).endsWith("px")) {
  675. return parseFloat(computedStyle.getPropertyValue(styleName));
  676. }
  677. }
  678. function getFontsData() {
  679. return getFontsData$1();
  680. }
  681. function serialize(doc) {
  682. const docType = doc.doctype;
  683. let docTypeString = "";
  684. if (docType) {
  685. docTypeString = "<!DOCTYPE " + docType.nodeName;
  686. if (docType.publicId) {
  687. docTypeString += " PUBLIC \"" + docType.publicId + "\"";
  688. if (docType.systemId) {
  689. docTypeString += " \"" + docType.systemId + "\"";
  690. }
  691. } else if (docType.systemId) {
  692. docTypeString += " SYSTEM \"" + docType.systemId + "\"";
  693. } if (docType.internalSubset) {
  694. docTypeString += " [" + docType.internalSubset + "]";
  695. }
  696. docTypeString += "> ";
  697. }
  698. return docTypeString + doc.documentElement.outerHTML;
  699. }
  700. function removeQuotes(string) {
  701. if (string.match(REGEXP_SIMPLE_QUOTES_STRING)) {
  702. string = string.replace(REGEXP_SIMPLE_QUOTES_STRING, "$1");
  703. } else {
  704. string = string.replace(REGEXP_DOUBLE_QUOTES_STRING, "$1");
  705. }
  706. return string.trim();
  707. }
  708. function getFontWeight(weight) {
  709. return FONT_WEIGHTS[weight.toLowerCase().trim()] || weight;
  710. }
  711. function getComputedStyle(win, element, pseudoElement) {
  712. try {
  713. return win.getComputedStyle(element, pseudoElement);
  714. } catch (error) {
  715. // ignored
  716. }
  717. }
  718. /*
  719. * Copyright 2010-2022 Gildas Lormeau
  720. * contact : gildas.lormeau <at> gmail.com
  721. *
  722. * This file is part of SingleFile.
  723. *
  724. * The code in this file is free software: you can redistribute it and/or
  725. * modify it under the terms of the GNU Affero General Public License
  726. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  727. * of the License, or (at your option) any later version.
  728. *
  729. * The code in this file is distributed in the hope that it will be useful,
  730. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  731. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  732. * General Public License for more details.
  733. *
  734. * As additional permission under GNU AGPL version 3 section 7, you may
  735. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  736. * AGPL normally required by section 4, provided you include this license
  737. * notice and a URL through which recipients can access the Corresponding
  738. * Source.
  739. */
  740. const helper$1 = {
  741. LAZY_SRC_ATTRIBUTE_NAME,
  742. SINGLE_FILE_UI_ELEMENT_CLASS
  743. };
  744. const MAX_IDLE_TIMEOUT_CALLS = 10;
  745. const ATTRIBUTES_MUTATION_TYPE = "attributes";
  746. const browser$1 = globalThis.browser;
  747. const document$1 = globalThis.document;
  748. const MutationObserver$1 = globalThis.MutationObserver;
  749. const timeouts = new Map();
  750. let idleTimeoutCalls;
  751. if (browser$1 && browser$1.runtime && browser$1.runtime.onMessage && browser$1.runtime.onMessage.addListener) {
  752. browser$1.runtime.onMessage.addListener(message => {
  753. if (message.method == "singlefile.lazyTimeout.onTimeout") {
  754. const timeoutData = timeouts.get(message.type);
  755. if (timeoutData) {
  756. timeouts.delete(message.type);
  757. try {
  758. timeoutData.callback();
  759. } catch (error) {
  760. clearRegularTimeout(message.type);
  761. }
  762. }
  763. }
  764. });
  765. }
  766. async function process(options) {
  767. if (document$1.documentElement) {
  768. timeouts.clear();
  769. const bodyHeight = document$1.body ? Math.max(document$1.body.scrollHeight, document$1.documentElement.scrollHeight) : document$1.documentElement.scrollHeight;
  770. const bodyWidth = document$1.body ? Math.max(document$1.body.scrollWidth, document$1.documentElement.scrollWidth) : document$1.documentElement.scrollWidth;
  771. if (bodyHeight > globalThis.innerHeight || bodyWidth > globalThis.innerWidth) {
  772. const maxScrollY = Math.max(bodyHeight - (globalThis.innerHeight * 1.5), 0);
  773. const maxScrollX = Math.max(bodyWidth - (globalThis.innerWidth * 1.5), 0);
  774. if (globalThis.scrollY < maxScrollY || globalThis.scrollX < maxScrollX) {
  775. return triggerLazyLoading(options);
  776. }
  777. }
  778. }
  779. }
  780. function triggerLazyLoading(options) {
  781. idleTimeoutCalls = 0;
  782. return new Promise(async resolve => { // eslint-disable-line no-async-promise-executor
  783. let loadingImages;
  784. const pendingImages = new Set();
  785. const observer = new MutationObserver$1(async mutations => {
  786. mutations = mutations.filter(mutation => mutation.type == ATTRIBUTES_MUTATION_TYPE);
  787. if (mutations.length) {
  788. const updated = mutations.filter(mutation => {
  789. if (mutation.attributeName == "src") {
  790. mutation.target.setAttribute(helper$1.LAZY_SRC_ATTRIBUTE_NAME, mutation.target.src);
  791. mutation.target.addEventListener("load", onResourceLoad);
  792. }
  793. if (mutation.attributeName == "src" || mutation.attributeName == "srcset" ||
  794. (mutation.target.tagName && mutation.target.tagName.toUpperCase() == "SOURCE")) {
  795. return !mutation.target.classList || !mutation.target.classList.contains(helper$1.SINGLE_FILE_UI_ELEMENT_CLASS);
  796. }
  797. });
  798. if (updated.length) {
  799. loadingImages = true;
  800. await deferForceLazyLoadEnd(observer, options, cleanupAndResolve);
  801. if (!pendingImages.size) {
  802. await deferLazyLoadEnd(observer, options, cleanupAndResolve);
  803. }
  804. }
  805. }
  806. });
  807. await setIdleTimeout(options.loadDeferredImagesMaxIdleTime * 2);
  808. await deferForceLazyLoadEnd(observer, options, cleanupAndResolve);
  809. observer.observe(document$1, { subtree: true, childList: true, attributes: true });
  810. document$1.addEventListener(LOAD_IMAGE_EVENT, onImageLoadEvent);
  811. document$1.addEventListener(IMAGE_LOADED_EVENT, onImageLoadedEvent);
  812. loadDeferredImagesStart(options);
  813. async function setIdleTimeout(delay) {
  814. await setAsyncTimeout("idleTimeout", async () => {
  815. if (!loadingImages) {
  816. clearAsyncTimeout("loadTimeout");
  817. clearAsyncTimeout("maxTimeout");
  818. lazyLoadEnd(observer, options, cleanupAndResolve);
  819. } else if (idleTimeoutCalls < MAX_IDLE_TIMEOUT_CALLS) {
  820. idleTimeoutCalls++;
  821. clearAsyncTimeout("idleTimeout");
  822. await setIdleTimeout(Math.max(500, delay / 2));
  823. }
  824. }, delay, options.loadDeferredImagesNativeTimeout);
  825. }
  826. function onResourceLoad(event) {
  827. const element = event.target;
  828. element.removeAttribute(helper$1.LAZY_SRC_ATTRIBUTE_NAME);
  829. element.removeEventListener("load", onResourceLoad);
  830. }
  831. async function onImageLoadEvent(event) {
  832. loadingImages = true;
  833. await deferForceLazyLoadEnd(observer, options, cleanupAndResolve);
  834. await deferLazyLoadEnd(observer, options, cleanupAndResolve);
  835. if (event.detail) {
  836. pendingImages.add(event.detail);
  837. }
  838. }
  839. async function onImageLoadedEvent(event) {
  840. await deferForceLazyLoadEnd(observer, options, cleanupAndResolve);
  841. await deferLazyLoadEnd(observer, options, cleanupAndResolve);
  842. pendingImages.delete(event.detail);
  843. if (!pendingImages.size) {
  844. await deferLazyLoadEnd(observer, options, cleanupAndResolve);
  845. }
  846. }
  847. function cleanupAndResolve(value) {
  848. observer.disconnect();
  849. document$1.removeEventListener(LOAD_IMAGE_EVENT, onImageLoadEvent);
  850. document$1.removeEventListener(IMAGE_LOADED_EVENT, onImageLoadedEvent);
  851. resolve(value);
  852. }
  853. });
  854. }
  855. async function deferLazyLoadEnd(observer, options, resolve) {
  856. await setAsyncTimeout("loadTimeout", () => lazyLoadEnd(observer, options, resolve), options.loadDeferredImagesMaxIdleTime, options.loadDeferredImagesNativeTimeout);
  857. }
  858. async function deferForceLazyLoadEnd(observer, options, resolve) {
  859. await setAsyncTimeout("maxTimeout", async () => {
  860. await clearAsyncTimeout("loadTimeout");
  861. await lazyLoadEnd(observer, options, resolve);
  862. }, options.loadDeferredImagesMaxIdleTime * 10, options.loadDeferredImagesNativeTimeout);
  863. }
  864. async function lazyLoadEnd(observer, options, resolve) {
  865. await clearAsyncTimeout("idleTimeout");
  866. loadDeferredImagesEnd(options);
  867. await setAsyncTimeout("endTimeout", async () => {
  868. await clearAsyncTimeout("maxTimeout");
  869. resolve();
  870. }, options.loadDeferredImagesMaxIdleTime / 2, options.loadDeferredImagesNativeTimeout);
  871. observer.disconnect();
  872. }
  873. async function setAsyncTimeout(type, callback, delay, forceNativeTimeout) {
  874. if (browser$1 && browser$1.runtime && browser$1.runtime.sendMessage && !forceNativeTimeout) {
  875. if (!timeouts.get(type) || !timeouts.get(type).pending) {
  876. const timeoutData = { callback, pending: true };
  877. timeouts.set(type, timeoutData);
  878. try {
  879. await browser$1.runtime.sendMessage({ method: "singlefile.lazyTimeout.setTimeout", type, delay });
  880. } catch (error) {
  881. setRegularTimeout(type, callback, delay);
  882. }
  883. timeoutData.pending = false;
  884. }
  885. } else {
  886. setRegularTimeout(type, callback, delay);
  887. }
  888. }
  889. function setRegularTimeout(type, callback, delay) {
  890. const timeoutId = timeouts.get(type);
  891. if (timeoutId) {
  892. globalThis.clearTimeout(timeoutId);
  893. }
  894. timeouts.set(type, callback);
  895. globalThis.setTimeout(callback, delay);
  896. }
  897. async function clearAsyncTimeout(type) {
  898. if (browser$1 && browser$1.runtime && browser$1.runtime.sendMessage) {
  899. try {
  900. await browser$1.runtime.sendMessage({ method: "singlefile.lazyTimeout.clearTimeout", type });
  901. } catch (error) {
  902. clearRegularTimeout(type);
  903. }
  904. } else {
  905. clearRegularTimeout(type);
  906. }
  907. }
  908. function clearRegularTimeout(type) {
  909. const previousTimeoutId = timeouts.get(type);
  910. timeouts.delete(type);
  911. if (previousTimeoutId) {
  912. globalThis.clearTimeout(previousTimeoutId);
  913. }
  914. }
  915. /*
  916. * Copyright 2010-2022 Gildas Lormeau
  917. * contact : gildas.lormeau <at> gmail.com
  918. *
  919. * This file is part of SingleFile.
  920. *
  921. * The code in this file is free software: you can redistribute it and/or
  922. * modify it under the terms of the GNU Affero General Public License
  923. * (GNU AGPL) as published by the Free Software Foundation, either version 3
  924. * of the License, or (at your option) any later version.
  925. *
  926. * The code in this file is distributed in the hope that it will be useful,
  927. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  928. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero
  929. * General Public License for more details.
  930. *
  931. * As additional permission under GNU AGPL version 3 section 7, you may
  932. * distribute UNMODIFIED VERSIONS OF THIS file without the copy of the GNU
  933. * AGPL normally required by section 4, provided you include this license
  934. * notice and a URL through which recipients can access the Corresponding
  935. * Source.
  936. */
  937. const helper = {
  938. ON_BEFORE_CAPTURE_EVENT_NAME,
  939. ON_AFTER_CAPTURE_EVENT_NAME,
  940. WIN_ID_ATTRIBUTE_NAME,
  941. WAIT_FOR_USERSCRIPT_PROPERTY_NAME,
  942. preProcessDoc,
  943. serialize,
  944. postProcessDoc,
  945. getShadowRoot
  946. };
  947. const FRAMES_CSS_SELECTOR = "iframe, frame, object[type=\"text/html\"][data]";
  948. const ALL_ELEMENTS_CSS_SELECTOR = "*";
  949. const INIT_REQUEST_MESSAGE = "singlefile.frameTree.initRequest";
  950. const ACK_INIT_REQUEST_MESSAGE = "singlefile.frameTree.ackInitRequest";
  951. const CLEANUP_REQUEST_MESSAGE = "singlefile.frameTree.cleanupRequest";
  952. const INIT_RESPONSE_MESSAGE = "singlefile.frameTree.initResponse";
  953. const TARGET_ORIGIN = "*";
  954. const TIMEOUT_INIT_REQUEST_MESSAGE = 5000;
  955. const TIMEOUT_INIT_RESPONSE_MESSAGE = 10000;
  956. const TOP_WINDOW_ID = "0";
  957. const WINDOW_ID_SEPARATOR = ".";
  958. const TOP_WINDOW = globalThis.window == globalThis.top;
  959. const browser = globalThis.browser;
  960. const top = globalThis.top;
  961. const MessageChannel = globalThis.MessageChannel;
  962. const document = globalThis.document;
  963. const JSON = globalThis.JSON;
  964. const MutationObserver = globalThis.MutationObserver;
  965. let sessions = globalThis.sessions;
  966. if (!sessions) {
  967. sessions = globalThis.sessions = new Map();
  968. }
  969. let windowId;
  970. if (TOP_WINDOW) {
  971. windowId = TOP_WINDOW_ID;
  972. if (browser && browser.runtime && browser.runtime.onMessage && browser.runtime.onMessage.addListener) {
  973. browser.runtime.onMessage.addListener(message => {
  974. if (message.method == INIT_RESPONSE_MESSAGE) {
  975. initResponse(message);
  976. return Promise.resolve({});
  977. } else if (message.method == ACK_INIT_REQUEST_MESSAGE) {
  978. clearFrameTimeout("requestTimeouts", message.sessionId, message.windowId);
  979. createFrameResponseTimeout(message.sessionId, message.windowId);
  980. return Promise.resolve({});
  981. }
  982. });
  983. }
  984. }
  985. init();
  986. new MutationObserver(init).observe(document, { childList: true });
  987. function init() {
  988. globalThis.addEventListener("message", async event => {
  989. if (typeof event.data == "string" && event.data.startsWith(MESSAGE_PREFIX)) {
  990. event.preventDefault();
  991. event.stopPropagation();
  992. const message = JSON.parse(event.data.substring(MESSAGE_PREFIX.length));
  993. if (message.method == INIT_REQUEST_MESSAGE) {
  994. if (event.source) {
  995. sendMessage(event.source, { method: ACK_INIT_REQUEST_MESSAGE, windowId: message.windowId, sessionId: message.sessionId });
  996. }
  997. if (!TOP_WINDOW) {
  998. globalThis.stop();
  999. if (message.options.loadDeferredImages) {
  1000. process(message.options);
  1001. }
  1002. await initRequestAsync(message);
  1003. }
  1004. } else if (message.method == ACK_INIT_REQUEST_MESSAGE) {
  1005. clearFrameTimeout("requestTimeouts", message.sessionId, message.windowId);
  1006. createFrameResponseTimeout(message.sessionId, message.windowId);
  1007. } else if (message.method == CLEANUP_REQUEST_MESSAGE) {
  1008. cleanupRequest(message);
  1009. } else if (message.method == INIT_RESPONSE_MESSAGE && sessions.get(message.sessionId)) {
  1010. const port = event.ports[0];
  1011. port.onmessage = event => initResponse(event.data);
  1012. }
  1013. }
  1014. }, true);
  1015. }
  1016. function getAsync(options) {
  1017. const sessionId = getNewSessionId();
  1018. options = JSON.parse(JSON.stringify(options));
  1019. return new Promise(resolve => {
  1020. sessions.set(sessionId, {
  1021. frames: [],
  1022. requestTimeouts: {},
  1023. responseTimeouts: {},
  1024. resolve: frames => {
  1025. frames.sessionId = sessionId;
  1026. resolve(frames);
  1027. }
  1028. });
  1029. initRequestAsync({ windowId, sessionId, options });
  1030. });
  1031. }
  1032. function getSync(options) {
  1033. const sessionId = getNewSessionId();
  1034. options = JSON.parse(JSON.stringify(options));
  1035. sessions.set(sessionId, {
  1036. frames: [],
  1037. requestTimeouts: {},
  1038. responseTimeouts: {}
  1039. });
  1040. initRequestSync({ windowId, sessionId, options });
  1041. const frames = sessions.get(sessionId).frames;
  1042. frames.sessionId = sessionId;
  1043. return frames;
  1044. }
  1045. function cleanup(sessionId) {
  1046. sessions.delete(sessionId);
  1047. cleanupRequest({ windowId, sessionId, options: { sessionId } });
  1048. }
  1049. function getNewSessionId() {
  1050. return globalThis.crypto.getRandomValues(new Uint32Array(32)).join("");
  1051. }
  1052. function initRequestSync(message) {
  1053. const sessionId = message.sessionId;
  1054. const waitForUserScript = globalThis[helper.WAIT_FOR_USERSCRIPT_PROPERTY_NAME];
  1055. delete globalThis._singleFile_cleaningUp;
  1056. if (!TOP_WINDOW) {
  1057. windowId = globalThis.frameId = message.windowId;
  1058. }
  1059. processFrames(document, message.options, windowId, sessionId);
  1060. if (!TOP_WINDOW) {
  1061. if (message.options.userScriptEnabled && waitForUserScript) {
  1062. waitForUserScript(helper.ON_BEFORE_CAPTURE_EVENT_NAME);
  1063. }
  1064. sendInitResponse({ frames: [getFrameData(document, globalThis, windowId, message.options, message.scrolling)], sessionId, requestedFrameId: document.documentElement.dataset.requestedFrameId && windowId });
  1065. if (message.options.userScriptEnabled && waitForUserScript) {
  1066. waitForUserScript(helper.ON_AFTER_CAPTURE_EVENT_NAME);
  1067. }
  1068. delete document.documentElement.dataset.requestedFrameId;
  1069. }
  1070. }
  1071. async function initRequestAsync(message) {
  1072. const sessionId = message.sessionId;
  1073. const waitForUserScript = globalThis[helper.WAIT_FOR_USERSCRIPT_PROPERTY_NAME];
  1074. delete globalThis._singleFile_cleaningUp;
  1075. if (!TOP_WINDOW) {
  1076. windowId = globalThis.frameId = message.windowId;
  1077. }
  1078. processFrames(document, message.options, windowId, sessionId);
  1079. if (!TOP_WINDOW) {
  1080. if (message.options.userScriptEnabled && waitForUserScript) {
  1081. await waitForUserScript(helper.ON_BEFORE_CAPTURE_EVENT_NAME);
  1082. }
  1083. sendInitResponse({ frames: [getFrameData(document, globalThis, windowId, message.options, message.scrolling)], sessionId, requestedFrameId: document.documentElement.dataset.requestedFrameId && windowId });
  1084. if (message.options.userScriptEnabled && waitForUserScript) {
  1085. await waitForUserScript(helper.ON_AFTER_CAPTURE_EVENT_NAME);
  1086. }
  1087. delete document.documentElement.dataset.requestedFrameId;
  1088. }
  1089. }
  1090. function cleanupRequest(message) {
  1091. if (!globalThis._singleFile_cleaningUp) {
  1092. globalThis._singleFile_cleaningUp = true;
  1093. const sessionId = message.sessionId;
  1094. cleanupFrames(getFrames(document), message.windowId, sessionId);
  1095. }
  1096. }
  1097. function initResponse(message) {
  1098. message.frames.forEach(frameData => clearFrameTimeout("responseTimeouts", message.sessionId, frameData.windowId));
  1099. const windowData = sessions.get(message.sessionId);
  1100. if (windowData) {
  1101. if (message.requestedFrameId) {
  1102. windowData.requestedFrameId = message.requestedFrameId;
  1103. }
  1104. message.frames.forEach(messageFrameData => {
  1105. let frameData = windowData.frames.find(frameData => messageFrameData.windowId == frameData.windowId);
  1106. if (!frameData) {
  1107. frameData = { windowId: messageFrameData.windowId };
  1108. windowData.frames.push(frameData);
  1109. }
  1110. if (!frameData.processed) {
  1111. frameData.content = messageFrameData.content;
  1112. frameData.baseURI = messageFrameData.baseURI;
  1113. frameData.title = messageFrameData.title;
  1114. frameData.url = messageFrameData.url;
  1115. frameData.canvases = messageFrameData.canvases;
  1116. frameData.fonts = messageFrameData.fonts;
  1117. frameData.stylesheets = messageFrameData.stylesheets;
  1118. frameData.images = messageFrameData.images;
  1119. frameData.posters = messageFrameData.posters;
  1120. frameData.videos = messageFrameData.videos;
  1121. frameData.usedFonts = messageFrameData.usedFonts;
  1122. frameData.shadowRoots = messageFrameData.shadowRoots;
  1123. frameData.processed = messageFrameData.processed;
  1124. frameData.scrollPosition = messageFrameData.scrollPosition;
  1125. frameData.scrolling = messageFrameData.scrolling;
  1126. frameData.adoptedStyleSheets = messageFrameData.adoptedStyleSheets;
  1127. }
  1128. });
  1129. const remainingFrames = windowData.frames.filter(frameData => !frameData.processed).length;
  1130. if (!remainingFrames) {
  1131. windowData.frames = windowData.frames.sort((frame1, frame2) => frame2.windowId.split(WINDOW_ID_SEPARATOR).length - frame1.windowId.split(WINDOW_ID_SEPARATOR).length);
  1132. if (windowData.resolve) {
  1133. if (windowData.requestedFrameId) {
  1134. windowData.frames.forEach(frameData => {
  1135. if (frameData.windowId == windowData.requestedFrameId) {
  1136. frameData.requestedFrame = true;
  1137. }
  1138. });
  1139. }
  1140. windowData.resolve(windowData.frames);
  1141. }
  1142. }
  1143. }
  1144. }
  1145. function processFrames(doc, options, parentWindowId, sessionId) {
  1146. const frameElements = getFrames(doc);
  1147. processFramesAsync(doc, frameElements, options, parentWindowId, sessionId);
  1148. if (frameElements.length) {
  1149. processFramesSync(doc, frameElements, options, parentWindowId, sessionId);
  1150. }
  1151. }
  1152. function processFramesAsync(doc, frameElements, options, parentWindowId, sessionId) {
  1153. const frames = [];
  1154. let requestTimeouts;
  1155. if (sessions.get(sessionId)) {
  1156. requestTimeouts = sessions.get(sessionId).requestTimeouts;
  1157. } else {
  1158. requestTimeouts = {};
  1159. sessions.set(sessionId, { requestTimeouts });
  1160. }
  1161. frameElements.forEach((frameElement, frameIndex) => {
  1162. const windowId = parentWindowId + WINDOW_ID_SEPARATOR + frameIndex;
  1163. frameElement.setAttribute(helper.WIN_ID_ATTRIBUTE_NAME, windowId);
  1164. frames.push({ windowId });
  1165. });
  1166. sendInitResponse({ frames, sessionId, requestedFrameId: doc.documentElement.dataset.requestedFrameId && parentWindowId });
  1167. frameElements.forEach((frameElement, frameIndex) => {
  1168. const windowId = parentWindowId + WINDOW_ID_SEPARATOR + frameIndex;
  1169. try {
  1170. sendMessage(frameElement.contentWindow, { method: INIT_REQUEST_MESSAGE, windowId, sessionId, options, scrolling: frameElement.scrolling });
  1171. } catch (error) {
  1172. // ignored
  1173. }
  1174. requestTimeouts[windowId] = globalThis.setTimeout(() => sendInitResponse({ frames: [{ windowId, processed: true }], sessionId }), TIMEOUT_INIT_REQUEST_MESSAGE);
  1175. });
  1176. delete doc.documentElement.dataset.requestedFrameId;
  1177. }
  1178. function processFramesSync(doc, frameElements, options, parentWindowId, sessionId) {
  1179. const frames = [];
  1180. frameElements.forEach((frameElement, frameIndex) => {
  1181. const windowId = parentWindowId + WINDOW_ID_SEPARATOR + frameIndex;
  1182. let frameDoc;
  1183. try {
  1184. frameDoc = frameElement.contentDocument;
  1185. } catch (error) {
  1186. // ignored
  1187. }
  1188. if (frameDoc) {
  1189. try {
  1190. const frameWindow = frameElement.contentWindow;
  1191. frameWindow.stop();
  1192. clearFrameTimeout("requestTimeouts", sessionId, windowId);
  1193. processFrames(frameDoc, options, windowId, sessionId);
  1194. frames.push(getFrameData(frameDoc, frameWindow, windowId, options, frameElement.scrolling));
  1195. } catch (error) {
  1196. frames.push({ windowId, processed: true });
  1197. }
  1198. }
  1199. });
  1200. sendInitResponse({ frames, sessionId, requestedFrameId: doc.documentElement.dataset.requestedFrameId && parentWindowId });
  1201. delete doc.documentElement.dataset.requestedFrameId;
  1202. }
  1203. function clearFrameTimeout(type, sessionId, windowId) {
  1204. const session = sessions.get(sessionId);
  1205. if (session && session[type]) {
  1206. const timeout = session[type][windowId];
  1207. if (timeout) {
  1208. globalThis.clearTimeout(timeout);
  1209. delete session[type][windowId];
  1210. }
  1211. }
  1212. }
  1213. function createFrameResponseTimeout(sessionId, windowId) {
  1214. const session = sessions.get(sessionId);
  1215. if (session && session.responseTimeouts) {
  1216. session.responseTimeouts[windowId] = globalThis.setTimeout(() => sendInitResponse({ frames: [{ windowId: windowId, processed: true }], sessionId: sessionId }), TIMEOUT_INIT_RESPONSE_MESSAGE);
  1217. }
  1218. }
  1219. function cleanupFrames(frameElements, parentWindowId, sessionId) {
  1220. frameElements.forEach((frameElement, frameIndex) => {
  1221. const windowId = parentWindowId + WINDOW_ID_SEPARATOR + frameIndex;
  1222. frameElement.removeAttribute(helper.WIN_ID_ATTRIBUTE_NAME);
  1223. try {
  1224. sendMessage(frameElement.contentWindow, { method: CLEANUP_REQUEST_MESSAGE, windowId, sessionId });
  1225. } catch (error) {
  1226. // ignored
  1227. }
  1228. });
  1229. frameElements.forEach((frameElement, frameIndex) => {
  1230. const windowId = parentWindowId + WINDOW_ID_SEPARATOR + frameIndex;
  1231. let frameDoc;
  1232. try {
  1233. frameDoc = frameElement.contentDocument;
  1234. } catch (error) {
  1235. // ignored
  1236. }
  1237. if (frameDoc) {
  1238. try {
  1239. cleanupFrames(getFrames(frameDoc), windowId, sessionId);
  1240. } catch (error) {
  1241. // ignored
  1242. }
  1243. }
  1244. });
  1245. }
  1246. function sendInitResponse(message) {
  1247. message.method = INIT_RESPONSE_MESSAGE;
  1248. try {
  1249. top.singlefile.processors.frameTree.initResponse(message);
  1250. } catch (error) {
  1251. sendMessage(top, message, true);
  1252. }
  1253. }
  1254. function sendMessage(targetWindow, message, useChannel) {
  1255. if (targetWindow == top && browser && browser.runtime && browser.runtime.sendMessage) {
  1256. browser.runtime.sendMessage(message);
  1257. } else {
  1258. if (useChannel) {
  1259. const channel = new MessageChannel();
  1260. targetWindow.postMessage(MESSAGE_PREFIX + JSON.stringify({ method: message.method, sessionId: message.sessionId }), TARGET_ORIGIN, [channel.port2]);
  1261. channel.port1.postMessage(message);
  1262. } else {
  1263. targetWindow.postMessage(MESSAGE_PREFIX + JSON.stringify(message), TARGET_ORIGIN);
  1264. }
  1265. }
  1266. }
  1267. function getFrameData(document, globalThis, windowId, options, scrolling) {
  1268. const docData = helper.preProcessDoc(document, globalThis, options);
  1269. const content = helper.serialize(document);
  1270. helper.postProcessDoc(document, docData.markedElements, docData.invalidElements);
  1271. const baseURI = document.baseURI.split("#")[0];
  1272. return {
  1273. windowId,
  1274. content,
  1275. baseURI,
  1276. url: document.documentURI,
  1277. title: document.title,
  1278. canvases: docData.canvases,
  1279. fonts: docData.fonts,
  1280. stylesheets: docData.stylesheets,
  1281. images: docData.images,
  1282. posters: docData.posters,
  1283. videos: docData.videos,
  1284. usedFonts: docData.usedFonts,
  1285. shadowRoots: docData.shadowRoots,
  1286. scrollPosition: docData.scrollPosition,
  1287. scrolling,
  1288. adoptedStyleSheets: docData.adoptedStyleSheets,
  1289. processed: true
  1290. };
  1291. }
  1292. function getFrames(document) {
  1293. let frames = Array.from(document.querySelectorAll(FRAMES_CSS_SELECTOR));
  1294. document.querySelectorAll(ALL_ELEMENTS_CSS_SELECTOR).forEach(element => {
  1295. const shadowRoot = helper.getShadowRoot(element);
  1296. if (shadowRoot) {
  1297. frames = frames.concat(...shadowRoot.querySelectorAll(FRAMES_CSS_SELECTOR));
  1298. }
  1299. });
  1300. return frames;
  1301. }
  1302. exports.TIMEOUT_INIT_REQUEST_MESSAGE = TIMEOUT_INIT_REQUEST_MESSAGE;
  1303. exports.cleanup = cleanup;
  1304. exports.getAsync = getAsync;
  1305. exports.getSync = getSync;
  1306. exports.initResponse = initResponse;
  1307. Object.defineProperty(exports, '__esModule', { value: true });
  1308. }));