@browserless.io/browserless 2.0.0-beta-4 → 2.0.0-beta-6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. package/LICENSE +2 -0
  2. package/README.md +11 -11
  3. package/bin/browserless.js +155 -11
  4. package/bin/scaffold/README.md +415 -0
  5. package/bin/scaffold/package.json +21 -0
  6. package/bin/scaffold/src/hello-world.http.ts +25 -0
  7. package/bin/scaffold/tsconfig.json +4 -0
  8. package/build/browserless.js +18 -15
  9. package/build/browsers/index.d.ts +2 -18
  10. package/build/browsers/index.js +43 -14
  11. package/build/http.d.ts +3 -3
  12. package/build/http.js +3 -3
  13. package/build/router.js +2 -4
  14. package/build/routes/chromium/http/content-post.body.json +8 -8
  15. package/build/routes/chromium/http/content-post.d.ts +15 -3
  16. package/build/routes/chromium/http/content-post.js +14 -15
  17. package/build/routes/chromium/http/download-post.d.ts +16 -3
  18. package/build/routes/chromium/http/download-post.js +17 -22
  19. package/build/routes/chromium/http/function-post.d.ts +16 -3
  20. package/build/routes/chromium/http/function-post.js +17 -22
  21. package/build/routes/chromium/http/pdf-post.body.json +8 -8
  22. package/build/routes/chromium/http/pdf-post.d.ts +15 -3
  23. package/build/routes/chromium/http/pdf-post.js +19 -15
  24. package/build/routes/chromium/http/performance.d.ts +15 -3
  25. package/build/routes/chromium/http/performance.js +15 -23
  26. package/build/routes/chromium/http/scrape-post.body.json +8 -8
  27. package/build/routes/chromium/http/scrape-post.d.ts +15 -3
  28. package/build/routes/chromium/http/scrape-post.js +15 -16
  29. package/build/routes/chromium/http/screenshot-post.body.json +8 -8
  30. package/build/routes/chromium/http/screenshot-post.d.ts +15 -3
  31. package/build/routes/chromium/http/screenshot-post.js +18 -15
  32. package/build/routes/chromium/tests/websocket.spec.js +20 -1
  33. package/build/routes/chromium/utils/function/handler.js +2 -2
  34. package/build/routes/chromium/ws/browser.d.ts +13 -3
  35. package/build/routes/chromium/ws/browser.js +10 -11
  36. package/build/routes/chromium/ws/cdp-chromium.d.ts +13 -3
  37. package/build/routes/chromium/ws/cdp-chromium.js +10 -11
  38. package/build/routes/chromium/ws/page.d.ts +13 -3
  39. package/build/routes/chromium/ws/page.js +10 -11
  40. package/build/routes/chromium/ws/playwright-chromium.d.ts +13 -3
  41. package/build/routes/chromium/ws/playwright-chromium.js +11 -12
  42. package/build/routes/firefox/ws/playwright-firefox.d.ts +13 -3
  43. package/build/routes/firefox/ws/playwright-firefox.js +11 -12
  44. package/build/routes/management/http/config-get.d.ts +15 -3
  45. package/build/routes/management/http/config-get.js +15 -20
  46. package/build/routes/management/http/metrics-get.d.ts +15 -3
  47. package/build/routes/management/http/metrics-get.js +16 -21
  48. package/build/routes/management/http/metrics-total-get.d.ts +15 -3
  49. package/build/routes/management/http/metrics-total-get.js +16 -21
  50. package/build/routes/management/http/sessions-get.d.ts +15 -3
  51. package/build/routes/management/http/sessions-get.js +16 -20
  52. package/build/routes/management/http/static-get.d.ts +15 -3
  53. package/build/routes/management/http/static-get.js +15 -20
  54. package/build/routes/webkit/ws/playwright-webkit.d.ts +13 -3
  55. package/build/routes/webkit/ws/playwright-webkit.js +11 -12
  56. package/build/server.js +0 -1
  57. package/build/types.d.ts +48 -38
  58. package/build/types.js +135 -0
  59. package/extensions/ublock/1p-filters.html +0 -1
  60. package/extensions/ublock/3p-filters.html +0 -2
  61. package/extensions/ublock/_locales/bg/messages.json +6 -6
  62. package/extensions/ublock/_locales/br_FR/messages.json +14 -14
  63. package/extensions/ublock/_locales/bs/messages.json +8 -8
  64. package/extensions/ublock/_locales/ca/messages.json +1 -1
  65. package/extensions/ublock/_locales/da/messages.json +5 -5
  66. package/extensions/ublock/_locales/fa/messages.json +1 -1
  67. package/extensions/ublock/_locales/fi/messages.json +6 -6
  68. package/extensions/ublock/_locales/hr/messages.json +4 -4
  69. package/extensions/ublock/_locales/nb/messages.json +1 -1
  70. package/extensions/ublock/_locales/no/messages.json +1 -1
  71. package/extensions/ublock/_locales/ro/messages.json +2 -2
  72. package/extensions/ublock/_locales/ru/messages.json +1 -1
  73. package/extensions/ublock/_locales/sk/messages.json +1 -1
  74. package/extensions/ublock/_locales/sv/messages.json +2 -2
  75. package/extensions/ublock/_locales/te/messages.json +17 -17
  76. package/extensions/ublock/_locales/vi/messages.json +12 -12
  77. package/extensions/ublock/_locales/zh_TW/messages.json +13 -13
  78. package/extensions/ublock/assets/assets.json +3 -3
  79. package/extensions/ublock/assets/resources/scriptlets.js +218 -97
  80. package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +3010 -2056
  81. package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +624 -433
  82. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +93 -24
  83. package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +7 -15
  84. package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +795 -777
  85. package/extensions/ublock/assets/ublock/badware.min.txt +138 -72
  86. package/extensions/ublock/assets/ublock/filters.min.txt +1929 -2735
  87. package/extensions/ublock/assets/ublock/privacy.min.txt +57 -26
  88. package/extensions/ublock/assets/ublock/quick-fixes.min.txt +125 -74
  89. package/extensions/ublock/assets/ublock/unbreak.min.txt +46 -53
  90. package/extensions/ublock/css/codemirror.css +8 -7
  91. package/extensions/ublock/css/dom-inspector.css +40 -0
  92. package/extensions/ublock/css/logger-ui-inspector.css +7 -1
  93. package/extensions/ublock/css/logger-ui.css +12 -5
  94. package/extensions/ublock/css/popup-fenix.css +1 -1
  95. package/extensions/ublock/devtools.html +1 -0
  96. package/extensions/ublock/js/1p-filters.js +4 -3
  97. package/extensions/ublock/js/3p-filters.js +25 -31
  98. package/extensions/ublock/js/about.js +1 -1
  99. package/extensions/ublock/js/advanced-settings.js +1 -1
  100. package/extensions/ublock/js/asset-viewer.js +1 -1
  101. package/extensions/ublock/js/assets.js +74 -44
  102. package/extensions/ublock/js/background.js +9 -3
  103. package/extensions/ublock/js/base64-custom.js +1 -1
  104. package/extensions/ublock/js/benchmarks.js +1 -1
  105. package/extensions/ublock/js/biditrie.js +1 -1
  106. package/extensions/ublock/js/broadcast.js +75 -0
  107. package/extensions/ublock/js/cachestorage.js +68 -45
  108. package/extensions/ublock/js/click2load.js +1 -1
  109. package/extensions/ublock/js/cloud-ui.js +1 -1
  110. package/extensions/ublock/js/code-viewer.js +1 -1
  111. package/extensions/ublock/js/codemirror/search-thread.js +1 -1
  112. package/extensions/ublock/js/codemirror/search.js +1 -1
  113. package/extensions/ublock/js/codemirror/ubo-dynamic-filtering.js +1 -1
  114. package/extensions/ublock/js/codemirror/ubo-static-filtering.js +98 -24
  115. package/extensions/ublock/js/commands.js +1 -1
  116. package/extensions/ublock/js/console.js +1 -1
  117. package/extensions/ublock/js/contentscript-extra.js +1 -1
  118. package/extensions/ublock/js/contentscript.js +1 -3
  119. package/extensions/ublock/js/contextmenu.js +1 -1
  120. package/extensions/ublock/js/cosmetic-filtering.js +4 -4
  121. package/extensions/ublock/js/dashboard-common.js +1 -1
  122. package/extensions/ublock/js/dashboard.js +1 -1
  123. package/extensions/ublock/js/devtools.js +23 -15
  124. package/extensions/ublock/js/diff-updater.js +3 -3
  125. package/extensions/ublock/js/document-blocked.js +1 -1
  126. package/extensions/ublock/js/dom-inspector.js +68 -0
  127. package/extensions/ublock/js/dom.js +1 -1
  128. package/extensions/ublock/js/dyna-rules.js +1 -1
  129. package/extensions/ublock/js/dynamic-net-filtering.js +1 -1
  130. package/extensions/ublock/js/epicker-ui.js +35 -59
  131. package/extensions/ublock/js/fa-icons.js +1 -1
  132. package/extensions/ublock/js/filtering-context.js +1 -1
  133. package/extensions/ublock/js/filtering-engines.js +1 -1
  134. package/extensions/ublock/js/hnswitches.js +1 -1
  135. package/extensions/ublock/js/hntrie.js +1 -1
  136. package/extensions/ublock/js/html-filtering.js +1 -1
  137. package/extensions/ublock/js/httpheader-filtering.js +1 -1
  138. package/extensions/ublock/js/i18n.js +1 -1
  139. package/extensions/ublock/js/is-webrtc-supported.js +1 -1
  140. package/extensions/ublock/js/logger-ui-inspector.js +203 -145
  141. package/extensions/ublock/js/logger-ui.js +21 -5
  142. package/extensions/ublock/js/logger.js +6 -2
  143. package/extensions/ublock/js/lz4.js +2 -2
  144. package/extensions/ublock/js/messaging.js +266 -166
  145. package/extensions/ublock/js/mrucache.js +58 -0
  146. package/extensions/ublock/js/pagestore.js +1 -1
  147. package/extensions/ublock/js/popup-fenix.js +2 -1
  148. package/extensions/ublock/js/redirect-engine.js +1 -1
  149. package/extensions/ublock/js/redirect-resources.js +1 -12
  150. package/extensions/ublock/js/reverselookup-worker.js +1 -1
  151. package/extensions/ublock/js/reverselookup.js +1 -1
  152. package/extensions/ublock/js/scriptlet-filtering-core.js +300 -0
  153. package/extensions/ublock/js/scriptlet-filtering.js +122 -350
  154. package/extensions/ublock/js/scriptlets/cosmetic-logger.js +36 -47
  155. package/extensions/ublock/js/scriptlets/cosmetic-off.js +1 -1
  156. package/extensions/ublock/js/scriptlets/cosmetic-on.js +1 -1
  157. package/extensions/ublock/js/scriptlets/cosmetic-report.js +1 -1
  158. package/extensions/ublock/js/scriptlets/dom-inspector.js +341 -323
  159. package/extensions/ublock/js/scriptlets/dom-survey-elements.js +1 -1
  160. package/extensions/ublock/js/scriptlets/dom-survey-scripts.js +1 -1
  161. package/extensions/ublock/js/scriptlets/epicker.js +80 -89
  162. package/extensions/ublock/js/scriptlets/load-3p-css.js +1 -1
  163. package/extensions/ublock/js/scriptlets/load-large-media-all.js +1 -1
  164. package/extensions/ublock/js/scriptlets/load-large-media-interactive.js +1 -1
  165. package/extensions/ublock/js/scriptlets/noscript-spoof.js +1 -1
  166. package/extensions/ublock/js/scriptlets/should-inject-contentscript.js +1 -1
  167. package/extensions/ublock/js/scriptlets/subscriber.js +1 -1
  168. package/extensions/ublock/js/scriptlets/updater.js +20 -3
  169. package/extensions/ublock/js/settings.js +1 -1
  170. package/extensions/ublock/js/start.js +19 -20
  171. package/extensions/ublock/js/static-dnr-filtering.js +1 -1
  172. package/extensions/ublock/js/static-ext-filtering-db.js +1 -1
  173. package/extensions/ublock/js/static-ext-filtering.js +1 -1
  174. package/extensions/ublock/js/static-filtering-io.js +1 -1
  175. package/extensions/ublock/js/static-filtering-parser.js +5 -3
  176. package/extensions/ublock/js/static-net-filtering.js +57 -37
  177. package/extensions/ublock/js/storage.js +49 -29
  178. package/extensions/ublock/js/support.js +4 -4
  179. package/extensions/ublock/js/tab.js +1 -1
  180. package/extensions/ublock/js/tasks.js +1 -1
  181. package/extensions/ublock/js/text-encode.js +1 -1
  182. package/extensions/ublock/js/text-utils.js +1 -1
  183. package/extensions/ublock/js/theme.js +1 -1
  184. package/extensions/ublock/js/traffic.js +2 -1
  185. package/extensions/ublock/js/ublock.js +15 -11
  186. package/extensions/ublock/js/uri-utils.js +1 -1
  187. package/extensions/ublock/js/url-net-filtering.js +1 -1
  188. package/extensions/ublock/js/utils.js +1 -73
  189. package/extensions/ublock/js/vapi-background-ext.js +1 -1
  190. package/extensions/ublock/js/vapi-background.js +92 -83
  191. package/extensions/ublock/js/vapi-client.js +4 -33
  192. package/extensions/ublock/js/vapi-common.js +16 -30
  193. package/extensions/ublock/js/vapi.js +1 -1
  194. package/extensions/ublock/js/wasm/biditrie.wat +1 -1
  195. package/extensions/ublock/js/wasm/hntrie.wat +1 -1
  196. package/extensions/ublock/js/webext.js +1 -1
  197. package/extensions/ublock/js/whitelist.js +1 -1
  198. package/extensions/ublock/logger-ui.html +2 -2
  199. package/extensions/ublock/manifest.json +1 -1
  200. package/extensions/ublock/support.html +0 -1
  201. package/extensions/ublock/web_accessible_resources/dom-inspector.html +25 -0
  202. package/extensions/ublock/web_accessible_resources/epicker-ui.html +0 -1
  203. package/extensions/ublock/web_accessible_resources/googletagservices_gpt.js +1 -0
  204. package/package.json +10 -20
  205. package/scripts/build-open-api.js +7 -4
  206. package/src/browserless.ts +42 -18
  207. package/src/browsers/index.ts +48 -20
  208. package/src/http.ts +3 -3
  209. package/src/router.ts +2 -6
  210. package/src/routes/chromium/http/content-post.ts +13 -16
  211. package/src/routes/chromium/http/download-post.ts +16 -27
  212. package/src/routes/chromium/http/function-post.ts +16 -25
  213. package/src/routes/chromium/http/pdf-post.ts +19 -15
  214. package/src/routes/chromium/http/performance.ts +14 -26
  215. package/src/routes/chromium/http/scrape-post.ts +14 -16
  216. package/src/routes/chromium/http/screenshot-post.ts +18 -15
  217. package/src/routes/chromium/tests/websocket.spec.ts +28 -1
  218. package/src/routes/chromium/utils/function/handler.ts +2 -1
  219. package/src/routes/chromium/ws/browser.ts +10 -12
  220. package/src/routes/chromium/ws/cdp-chromium.ts +10 -12
  221. package/src/routes/chromium/ws/page.ts +10 -12
  222. package/src/routes/chromium/ws/playwright-chromium.ts +10 -12
  223. package/src/routes/firefox/ws/playwright-firefox.ts +10 -12
  224. package/src/routes/management/http/config-get.ts +14 -23
  225. package/src/routes/management/http/metrics-get.ts +15 -24
  226. package/src/routes/management/http/metrics-total-get.ts +15 -26
  227. package/src/routes/management/http/sessions-get.ts +15 -23
  228. package/src/routes/management/http/static-get.ts +14 -22
  229. package/src/routes/webkit/ws/playwright-webkit.ts +10 -12
  230. package/src/server.ts +0 -1
  231. package/src/types.ts +59 -45
  232. package/static/docs/browserless-logo-inline.svg +1 -0
  233. package/static/docs/index.html +27 -0
  234. package/static/docs/swagger.json +33 -33
  235. package/static/function/client.js +626 -78
  236. package/extensions/ublock/js/vapi-client-extra.js +0 -312
  237. package/extensions/ublock/web_accessible_resources/addthis_widget.js +0 -39
  238. package/extensions/ublock/web_accessible_resources/ligatus_angular-tag.js +0 -29
  239. package/extensions/ublock/web_accessible_resources/monkeybroker.js +0 -43
  240. package/extensions/ublock/web_accessible_resources/mxpnl_mixpanel.js +0 -51
@@ -140,7 +140,7 @@
140
140
  "description": "Tooltip for the no-popups per-site switch"
141
141
  },
142
142
  "popupTipNoPopups2": {
143
- "message": "點擊以停止阻擋此網站的所有彈出式視窗",
143
+ "message": "點擊後將不再封鎖此網站的所有彈出式廣告",
144
144
  "description": "Tooltip for the no-popups per-site switch"
145
145
  },
146
146
  "popupTipNoLargeMedia": {
@@ -172,11 +172,11 @@
172
172
  "description": "Tooltip for the no-remote-fonts per-site switch"
173
173
  },
174
174
  "popupTipNoRemoteFonts1": {
175
- "message": "點擊以封鎖此網站的遠端字體",
175
+ "message": "點擊以封鎖此網站的遠端字型",
176
176
  "description": "Tooltip for the no-remote-fonts per-site switch"
177
177
  },
178
178
  "popupTipNoRemoteFonts2": {
179
- "message": "點擊以停止封鎖此網站的遠端字體",
179
+ "message": "點擊以停止封鎖此網站的遠端字型",
180
180
  "description": "Tooltip for the no-remote-fonts per-site switch"
181
181
  },
182
182
  "popupTipNoScripting1": {
@@ -184,7 +184,7 @@
184
184
  "description": "Tooltip for the no-scripting per-site switch"
185
185
  },
186
186
  "popupTipNoScripting2": {
187
- "message": "點擊以使重新啟用此網站的 JavaScript ",
187
+ "message": "點擊以重新啟用此網站的 JavaScript ",
188
188
  "description": "Tooltip for the no-scripting per-site switch"
189
189
  },
190
190
  "popupNoPopups_v2": {
@@ -244,7 +244,7 @@
244
244
  "description": ""
245
245
  },
246
246
  "popup3pPassiveRulePrompt": {
247
- "message": "第三方 階層式樣式表 / 圖片",
247
+ "message": "第三方 CSS / 圖片",
248
248
  "description": ""
249
249
  },
250
250
  "popupInlineScriptRulePrompt": {
@@ -384,7 +384,7 @@
384
384
  "description": ""
385
385
  },
386
386
  "settingsNoRemoteFontsPrompt": {
387
- "message": "封鎖遠端字體",
387
+ "message": "封鎖遠端字型",
388
388
  "description": ""
389
389
  },
390
390
  "settingsNoScriptingPrompt": {
@@ -404,7 +404,7 @@
404
404
  "description": "Section for controlling advanced-user settings"
405
405
  },
406
406
  "settingsAdvancedSynopsis": {
407
- "message": "僅適合技術使用者使用的相關功能。",
407
+ "message": "僅適合技術使用者的功能",
408
408
  "description": "Description of section controlling advanced-user settings"
409
409
  },
410
410
  "settingsAdvancedUserSettings": {
@@ -468,7 +468,7 @@
468
468
  "description": "English: Apply changes"
469
469
  },
470
470
  "3pGroupDefault": {
471
- "message": "內建",
471
+ "message": "內置",
472
472
  "description": "Filter lists section name"
473
473
  },
474
474
  "3pGroupAds": {
@@ -516,7 +516,7 @@
516
516
  "description": "used as a tooltip for eye icon beside a list"
517
517
  },
518
518
  "3pLastUpdate": {
519
- "message": "最後更新:{{ago}}。\n點擊此處以要求更新。",
519
+ "message": "上次更新:{{ago}}。\n點擊此處以要求更新。",
520
520
  "description": "used as a tooltip for the clock icon beside a list"
521
521
  },
522
522
  "3pUpdating": {
@@ -924,7 +924,7 @@
924
924
  "description": "Second paragraph of 'Filter issues' section in Support pane"
925
925
  },
926
926
  "supportS3P3": {
927
- "message": "<b>小提示:</b>請確定您的過濾器清單已經更新至最新版本。我們主要用<span data-url=\"logger-ui.html#_\">記錄器</span>來分析過濾器相關問題。",
927
+ "message": "<b>小提示:</b>請確定您的過濾器清單已經更新至最新版本。我們主要用 <span data-url=\"logger-ui.html#_\">記錄器</span> 來分析過濾器相關問題。",
928
928
  "description": "Third paragraph of 'Filter issues' section in Support pane"
929
929
  },
930
930
  "supportS4H": {
@@ -952,7 +952,7 @@
952
952
  "description": "Header of 'Report a filter issue' section in Support pane"
953
953
  },
954
954
  "supportS6P1S1": {
955
- "message": "為了避免太多人發出重複的報告拖垮志工,請先確認是否已經有人回報過您打算報告的問題。",
955
+ "message": "請先確認是否已經有人回報過此問題,以免重複回報造成維護者的而外負擔。",
956
956
  "description": "A paragraph in the filter issue reporter section"
957
957
  },
958
958
  "supportS6P2S1": {
@@ -968,7 +968,7 @@
968
968
  "description": "Label for the URL of the page"
969
969
  },
970
970
  "supportS6Select1": {
971
- "message": "這張網頁…",
971
+ "message": "這個網頁…",
972
972
  "description": "Label for widget to select type of issue"
973
973
  },
974
974
  "supportS6Select1Option0": {
@@ -1020,7 +1020,7 @@
1020
1020
  "description": ""
1021
1021
  },
1022
1022
  "aboutCode": {
1023
- "message": "程式原始碼(GPLv3)",
1023
+ "message": "原始碼(GPLv3)",
1024
1024
  "description": "English: Source code (GPLv3)"
1025
1025
  },
1026
1026
  "aboutContributors": {
@@ -755,9 +755,9 @@
755
755
  "lang": "af fy nl",
756
756
  "contentURL": "https://easydutch-ubo.github.io/EasyDutch/EasyDutch.txt",
757
757
  "cdnURLs": [
758
- "https://easydutchcdn.pages.dev/EasyDutch.all.txt",
759
- "https://cdn.jsdelivr.net/gh/EasyDutch-uBO/EasyDutchCDN@main/EasyDutch.all.txt",
760
- "https://cdn.statically.io/gh/EasyDutch-uBO/EasyDutchCDN/main/EasyDutch.all.txt"
758
+ "https://easydutch-ubo.github.io/EasyDutch/EasyDutch.all.txt",
759
+ "https://cdn.jsdelivr.net/gh/EasyDutch-uBO/EasyDutch@gh-pages/EasyDutch.all.txt",
760
+ "https://cdn.statically.io/gh/EasyDutch-uBO/EasyDutch/gh-pages/EasyDutch.all.txt"
761
761
  ],
762
762
  "supportURL": "https://github.com/EasyDutch-uBO/EasyDutch/"
763
763
  },
@@ -1,6 +1,6 @@
1
1
  /*******************************************************************************
2
2
 
3
- uBlock Origin - a browser extension to block requests.
3
+ uBlock Origin - a comprehensive, efficient content blocker
4
4
  Copyright (C) 2019-present Raymond Hill
5
5
 
6
6
  This program is free software: you can redistribute it and/or modify
@@ -52,6 +52,8 @@ function safeSelf() {
52
52
  'Function_toStringFn': self.Function.prototype.toString,
53
53
  'Function_toString': thisArg => safe.Function_toStringFn.call(thisArg),
54
54
  'Math_floor': Math.floor,
55
+ 'Math_max': Math.max,
56
+ 'Math_min': Math.min,
55
57
  'Math_random': Math.random,
56
58
  'Object_defineProperty': Object.defineProperty.bind(Object),
57
59
  'RegExp': self.RegExp,
@@ -85,7 +87,6 @@ function safeSelf() {
85
87
  const match = /^\/(.+)\/([gimsu]*)$/.exec(pattern);
86
88
  if ( match !== null ) {
87
89
  return {
88
- pattern,
89
90
  re: new this.RegExp(
90
91
  match[1],
91
92
  match[2] || options.flags
@@ -93,18 +94,23 @@ function safeSelf() {
93
94
  expect,
94
95
  };
95
96
  }
96
- return {
97
- pattern,
98
- re: new this.RegExp(pattern.replace(
99
- /[.*+?^${}()|[\]\\]/g, '\\$&'),
100
- options.flags
101
- ),
102
- expect,
103
- };
97
+ if ( options.flags !== undefined ) {
98
+ return {
99
+ re: new this.RegExp(pattern.replace(
100
+ /[.*+?^${}()|[\]\\]/g, '\\$&'),
101
+ options.flags
102
+ ),
103
+ expect,
104
+ };
105
+ }
106
+ return { pattern, expect };
104
107
  },
105
108
  testPattern(details, haystack) {
106
109
  if ( details.matchAll ) { return true; }
107
- return this.RegExp_test.call(details.re, haystack) === details.expect;
110
+ if ( details.re ) {
111
+ return this.RegExp_test.call(details.re, haystack) === details.expect;
112
+ }
113
+ return haystack.includes(details.pattern) === details.expect;
108
114
  },
109
115
  patternToRegex(pattern, flags = undefined, verbatim = false) {
110
116
  if ( pattern === '' ) { return /^/; }
@@ -242,6 +248,73 @@ function runAtHtmlElementFn(fn) {
242
248
 
243
249
  /******************************************************************************/
244
250
 
251
+ // Reference:
252
+ // https://github.com/AdguardTeam/Scriptlets/blob/master/wiki/about-scriptlets.md#prevent-xhr
253
+
254
+ builtinScriptlets.push({
255
+ name: 'generate-content.fn',
256
+ fn: generateContentFn,
257
+ dependencies: [
258
+ 'safe-self.fn',
259
+ ],
260
+ });
261
+ function generateContentFn(directive) {
262
+ const safe = safeSelf();
263
+ const randomize = len => {
264
+ const chunks = [];
265
+ let textSize = 0;
266
+ do {
267
+ const s = safe.Math_random().toString(36).slice(2);
268
+ chunks.push(s);
269
+ textSize += s.length;
270
+ }
271
+ while ( textSize < len );
272
+ return chunks.join(' ').slice(0, len);
273
+ };
274
+ if ( directive === 'true' ) {
275
+ return Promise.resolve(randomize(10));
276
+ }
277
+ if ( directive === 'emptyObj' ) {
278
+ return Promise.resolve('{}');
279
+ }
280
+ if ( directive === 'emptyArr' ) {
281
+ return Promise.resolve('[]');
282
+ }
283
+ if ( directive === 'emptyStr' ) {
284
+ return Promise.resolve('');
285
+ }
286
+ if ( directive.startsWith('length:') ) {
287
+ const match = /^length:(\d+)(?:-(\d+))?$/.exec(directive);
288
+ if ( match ) {
289
+ const min = parseInt(match[1], 10);
290
+ const extent = safe.Math_max(parseInt(match[2], 10) || 0, min) - min;
291
+ const len = safe.Math_min(min + extent * safe.Math_random(), 500000);
292
+ return Promise.resolve(randomize(len | 0));
293
+ }
294
+ }
295
+ if ( directive.startsWith('war:') && scriptletGlobals.has('warOrigin') ) {
296
+ return new Promise(resolve => {
297
+ const warOrigin = scriptletGlobals.get('warOrigin');
298
+ const warName = directive.slice(4);
299
+ const fullpath = [ warOrigin, '/', warName ];
300
+ const warSecret = scriptletGlobals.get('warSecret');
301
+ if ( warSecret !== undefined ) {
302
+ fullpath.push('?secret=', warSecret);
303
+ }
304
+ const warXHR = new safe.XMLHttpRequest();
305
+ warXHR.responseType = 'text';
306
+ warXHR.onloadend = ev => {
307
+ resolve(ev.target.responseText || '');
308
+ };
309
+ warXHR.open('GET', fullpath.join(''));
310
+ warXHR.send();
311
+ });
312
+ }
313
+ return Promise.resolve('');
314
+ }
315
+
316
+ /******************************************************************************/
317
+
245
318
  builtinScriptlets.push({
246
319
  name: 'abort-current-script-core.fn',
247
320
  fn: abortCurrentScriptCore,
@@ -898,7 +971,7 @@ builtinScriptlets.push({
898
971
  });
899
972
  function matchesStackTrace(
900
973
  needleDetails,
901
- logLevel = 0
974
+ logLevel = ''
902
975
  ) {
903
976
  const safe = safeSelf();
904
977
  const exceptionToken = getExceptionToken();
@@ -929,11 +1002,12 @@ function matchesStackTrace(
929
1002
  }
930
1003
  lines[0] = `stackDepth:${lines.length-1}`;
931
1004
  const stack = lines.join('\t');
932
- const r = safe.testPattern(needleDetails, stack);
1005
+ const r = needleDetails.matchAll !== true &&
1006
+ safe.testPattern(needleDetails, stack);
933
1007
  if (
934
- logLevel === 1 ||
935
- logLevel === 2 && r ||
936
- logLevel === 3 && !r
1008
+ logLevel === 'all' ||
1009
+ logLevel === 'match' && r ||
1010
+ logLevel === 'nomatch' && !r
937
1011
  ) {
938
1012
  safe.uboLog(stack.replace(/\t/g, '\n'));
939
1013
  }
@@ -1331,6 +1405,7 @@ function abortOnStackTrace(
1331
1405
  const safe = safeSelf();
1332
1406
  const needleDetails = safe.initPattern(needle, { canNegate: true });
1333
1407
  const extraArgs = safe.getExtraArgs(Array.from(arguments), 2);
1408
+ if ( needle === '' ) { extraArgs.log = 'all'; }
1334
1409
  const makeProxy = function(owner, chain) {
1335
1410
  const pos = chain.indexOf('.');
1336
1411
  if ( pos === -1 ) {
@@ -1757,16 +1832,18 @@ builtinScriptlets.push({
1757
1832
  ],
1758
1833
  fn: noFetchIf,
1759
1834
  dependencies: [
1835
+ 'generate-content.fn',
1760
1836
  'safe-self.fn',
1761
1837
  ],
1762
1838
  });
1763
1839
  function noFetchIf(
1764
- arg1 = '',
1840
+ propsToMatch = '',
1841
+ responseBody = ''
1765
1842
  ) {
1766
- if ( typeof arg1 !== 'string' ) { return; }
1843
+ if ( typeof propsToMatch !== 'string' ) { return; }
1767
1844
  const safe = safeSelf();
1768
1845
  const needles = [];
1769
- for ( const condition of arg1.split(/\s+/) ) {
1846
+ for ( const condition of propsToMatch.split(/\s+/) ) {
1770
1847
  if ( condition === '' ) { continue; }
1771
1848
  const pos = condition.indexOf(':');
1772
1849
  let key, value;
@@ -1782,14 +1859,11 @@ function noFetchIf(
1782
1859
  const log = needles.length === 0 ? console.log.bind(console) : undefined;
1783
1860
  self.fetch = new Proxy(self.fetch, {
1784
1861
  apply: function(target, thisArg, args) {
1862
+ const details = args[0] instanceof self.Request
1863
+ ? args[0]
1864
+ : Object.assign({ url: args[0] }, args[1]);
1785
1865
  let proceed = true;
1786
1866
  try {
1787
- let details;
1788
- if ( args[0] instanceof self.Request ) {
1789
- details = args[0];
1790
- } else {
1791
- details = Object.assign({ url: args[0] }, args[1]);
1792
- }
1793
1867
  const props = new Map();
1794
1868
  for ( const prop in details ) {
1795
1869
  let v = details[prop];
@@ -1818,9 +1892,36 @@ function noFetchIf(
1818
1892
  }
1819
1893
  } catch(ex) {
1820
1894
  }
1821
- return proceed
1822
- ? Reflect.apply(target, thisArg, args)
1823
- : Promise.resolve(new Response());
1895
+ if ( proceed ) {
1896
+ return Reflect.apply(target, thisArg, args);
1897
+ }
1898
+ let responseType = '';
1899
+ if ( details.mode === undefined || details.mode === 'cors' ) {
1900
+ try {
1901
+ const desURL = new URL(details.url);
1902
+ responseType = desURL.origin !== document.location.origin
1903
+ ? 'cors'
1904
+ : 'basic';
1905
+ } catch(_) {
1906
+ }
1907
+ }
1908
+ return generateContentFn(responseBody).then(text => {
1909
+ const response = new Response(text, {
1910
+ statusText: 'OK',
1911
+ headers: {
1912
+ 'Content-Length': text.length,
1913
+ }
1914
+ });
1915
+ Object.defineProperty(response, 'url', {
1916
+ value: details.url
1917
+ });
1918
+ if ( responseType !== '' ) {
1919
+ Object.defineProperty(response, 'type', {
1920
+ value: responseType
1921
+ });
1922
+ }
1923
+ return response;
1924
+ });
1824
1925
  }
1825
1926
  });
1826
1927
  }
@@ -2259,6 +2360,7 @@ builtinScriptlets.push({
2259
2360
  ],
2260
2361
  fn: noXhrIf,
2261
2362
  dependencies: [
2363
+ 'generate-content.fn',
2262
2364
  'match-object-properties.fn',
2263
2365
  'parse-properties-to-match.fn',
2264
2366
  'safe-self.fn',
@@ -2269,40 +2371,14 @@ function noXhrIf(
2269
2371
  directive = ''
2270
2372
  ) {
2271
2373
  if ( typeof propsToMatch !== 'string' ) { return; }
2272
- const safe = safeSelf();
2273
2374
  const xhrInstances = new WeakMap();
2274
2375
  const propNeedles = parsePropertiesToMatch(propsToMatch, 'url');
2275
2376
  const log = propNeedles.size === 0 ? console.log.bind(console) : undefined;
2276
2377
  const warOrigin = scriptletGlobals.get('warOrigin');
2277
- const generateRandomString = len => {
2278
- let s = '';
2279
- do { s += safe.Math_random().toString(36).slice(2); }
2280
- while ( s.length < 10 );
2281
- return s.slice(0, len);
2282
- };
2283
- const generateContent = async directive => {
2284
- if ( directive === 'true' ) {
2285
- return generateRandomString(10);
2286
- }
2287
- if ( directive.startsWith('war:') ) {
2288
- if ( warOrigin === undefined ) { return ''; }
2289
- return new Promise(resolve => {
2290
- const warName = directive.slice(4);
2291
- const fullpath = [ warOrigin, '/', warName ];
2292
- const warSecret = scriptletGlobals.get('warSecret');
2293
- if ( warSecret !== undefined ) {
2294
- fullpath.push('?secret=', warSecret);
2295
- }
2296
- const warXHR = new safe.XMLHttpRequest();
2297
- warXHR.responseType = 'text';
2298
- warXHR.onloadend = ev => {
2299
- resolve(ev.target.responseText || '');
2300
- };
2301
- warXHR.open('GET', fullpath.join(''));
2302
- warXHR.send();
2303
- });
2304
- }
2305
- return '';
2378
+ const headers = {
2379
+ 'date': '',
2380
+ 'content-type': '',
2381
+ 'content-length': '',
2306
2382
  };
2307
2383
  self.XMLHttpRequest = class extends self.XMLHttpRequest {
2308
2384
  open(method, url, ...args) {
@@ -2310,6 +2386,7 @@ function noXhrIf(
2310
2386
  log(`uBO: xhr.open(${method}, ${url}, ${args.join(', ')})`);
2311
2387
  return super.open(method, url, ...args);
2312
2388
  }
2389
+ xhrInstances.delete(this);
2313
2390
  if ( warOrigin !== undefined && url.startsWith(warOrigin) ) {
2314
2391
  return super.open(method, url, ...args);
2315
2392
  }
@@ -2317,6 +2394,7 @@ function noXhrIf(
2317
2394
  if ( matchObjectProperties(propNeedles, haystack) ) {
2318
2395
  xhrInstances.set(this, haystack);
2319
2396
  }
2397
+ haystack.headers = Object.assign({}, headers);
2320
2398
  return super.open(method, url, ...args);
2321
2399
  }
2322
2400
  send(...args) {
@@ -2324,6 +2402,7 @@ function noXhrIf(
2324
2402
  if ( haystack === undefined ) {
2325
2403
  return super.send(...args);
2326
2404
  }
2405
+ haystack.headers['date'] = (new Date()).toUTCString();
2327
2406
  let promise = Promise.resolve({
2328
2407
  xhr: this,
2329
2408
  directive,
@@ -2338,53 +2417,81 @@ function noXhrIf(
2338
2417
  },
2339
2418
  });
2340
2419
  switch ( this.responseType ) {
2341
- case 'arraybuffer':
2342
- promise = promise.then(details => {
2343
- details.props.response.value = new ArrayBuffer(0);
2344
- return details;
2345
- });
2346
- break;
2347
- case 'blob':
2348
- promise = promise.then(details => {
2349
- details.props.response.value = new Blob([]);
2350
- return details;
2351
- });
2352
- break;
2353
- case 'document': {
2354
- promise = promise.then(details => {
2355
- const parser = new DOMParser();
2356
- const doc = parser.parseFromString('', 'text/html');
2357
- details.props.response.value = doc;
2358
- details.props.responseXML.value = doc;
2359
- return details;
2360
- });
2361
- break;
2362
- }
2363
- case 'json':
2364
- promise = promise.then(details => {
2365
- details.props.response.value = {};
2366
- details.props.responseText.value = '{}';
2420
+ case 'arraybuffer':
2421
+ promise = promise.then(details => {
2422
+ details.props.response.value = new ArrayBuffer(0);
2423
+ return details;
2424
+ });
2425
+ haystack.headers['content-type'] = 'application/octet-stream';
2426
+ break;
2427
+ case 'blob':
2428
+ promise = promise.then(details => {
2429
+ details.props.response.value = new Blob([]);
2430
+ return details;
2431
+ });
2432
+ haystack.headers['content-type'] = 'application/octet-stream';
2433
+ break;
2434
+ case 'document': {
2435
+ promise = promise.then(details => {
2436
+ const parser = new DOMParser();
2437
+ const doc = parser.parseFromString('', 'text/html');
2438
+ details.props.response.value = doc;
2439
+ details.props.responseXML.value = doc;
2440
+ return details;
2441
+ });
2442
+ haystack.headers['content-type'] = 'text/html';
2443
+ break;
2444
+ }
2445
+ case 'json':
2446
+ promise = promise.then(details => {
2447
+ details.props.response.value = {};
2448
+ details.props.responseText.value = '{}';
2449
+ return details;
2450
+ });
2451
+ haystack.headers['content-type'] = 'application/json';
2452
+ break;
2453
+ default:
2454
+ if ( directive === '' ) { break; }
2455
+ promise = promise.then(details => {
2456
+ return generateContentFn(details.directive).then(text => {
2457
+ details.props.response.value = text;
2458
+ details.props.responseText.value = text;
2367
2459
  return details;
2368
2460
  });
2369
- break;
2370
- default:
2371
- if ( directive === '' ) { break; }
2372
- promise = promise.then(details => {
2373
- return generateContent(details.directive).then(text => {
2374
- details.props.response.value = text;
2375
- details.props.responseText.value = text;
2376
- return details;
2377
- });
2378
- });
2379
- break;
2461
+ });
2462
+ haystack.headers['content-type'] = 'text/plain';
2463
+ break;
2380
2464
  }
2381
2465
  promise.then(details => {
2466
+ haystack.headers['content-length'] = `${details.props.response.value}`.length;
2382
2467
  Object.defineProperties(details.xhr, details.props);
2383
2468
  details.xhr.dispatchEvent(new Event('readystatechange'));
2384
2469
  details.xhr.dispatchEvent(new Event('load'));
2385
2470
  details.xhr.dispatchEvent(new Event('loadend'));
2386
2471
  });
2387
2472
  }
2473
+ getResponseHeader(headerName) {
2474
+ const haystack = xhrInstances.get(this);
2475
+ if ( haystack === undefined || this.readyState < this.HEADERS_RECEIVED ) {
2476
+ return super.getResponseHeader(headerName);
2477
+ }
2478
+ const value = haystack.headers[headerName.toLowerCase()];
2479
+ if ( value !== undefined && value !== '' ) { return value; }
2480
+ return null;
2481
+ }
2482
+ getAllResponseHeaders() {
2483
+ const haystack = xhrInstances.get(this);
2484
+ if ( haystack === undefined || this.readyState < this.HEADERS_RECEIVED ) {
2485
+ return super.getAllResponseHeaders();
2486
+ }
2487
+ const out = [];
2488
+ for ( const [ name, value ] of Object.entries(haystack.headers) ) {
2489
+ if ( !value ) { continue; }
2490
+ out.push(`${name}: ${value}`);
2491
+ }
2492
+ if ( out.length !== 0 ) { out.push(''); }
2493
+ return out.join('\r\n');
2494
+ }
2388
2495
  };
2389
2496
  }
2390
2497
 
@@ -2894,6 +3001,9 @@ function xmlPrune(
2894
3001
  type === '' && thisArg.responseXML instanceof XMLDocument
2895
3002
  ) {
2896
3003
  pruneFromDoc(thisArg.responseXML);
3004
+ const serializer = new XMLSerializer();
3005
+ const textout = serializer.serializeToString(thisArg.responseXML);
3006
+ Object.defineProperty(thisArg, 'responseText', { value: textout });
2897
3007
  return;
2898
3008
  }
2899
3009
  if (
@@ -4036,10 +4146,21 @@ function trustedClickElement(
4036
4146
  ? ((...args) => { safe.uboLog(...args); })
4037
4147
  : (( ) => { });
4038
4148
 
4149
+ const querySelectorEx = (selector, context = document) => {
4150
+ const pos = selector.indexOf(' >>> ');
4151
+ if ( pos === -1 ) { return context.querySelector(selector); }
4152
+ const outside = selector.slice(0, pos).trim();
4153
+ const inside = selector.slice(pos + 5).trim();
4154
+ const elem = context.querySelector(outside);
4155
+ if ( elem === null ) { return null; }
4156
+ const shadowRoot = elem.shadowRoot;
4157
+ return shadowRoot && querySelectorEx(inside, shadowRoot);
4158
+ };
4159
+
4039
4160
  const selectorList = selectors.split(/\s*,\s*/)
4040
4161
  .filter(s => {
4041
4162
  try {
4042
- void document.querySelector(s);
4163
+ void querySelectorEx(s);
4043
4164
  } catch(_) {
4044
4165
  return false;
4045
4166
  }
@@ -4113,7 +4234,7 @@ function trustedClickElement(
4113
4234
  if ( Date.now() < tnext ) { return next(); }
4114
4235
  const selector = selectorList.shift();
4115
4236
  if ( selector === undefined ) { return terminate(); }
4116
- const elem = document.querySelector(selector);
4237
+ const elem = querySelectorEx(selector);
4117
4238
  if ( elem === null ) {
4118
4239
  selectorList.unshift(selector);
4119
4240
  return next(true);