@browserless.io/browserless 2.0.0-beta-1

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 (875) hide show
  1. package/CHANGELOG.md +674 -0
  2. package/LICENSE +6 -0
  3. package/README.md +132 -0
  4. package/assets/logo.png +0 -0
  5. package/bin/browserless.js +227 -0
  6. package/browser.json +7 -0
  7. package/build/browserless.d.ts +33 -0
  8. package/build/browserless.js +146 -0
  9. package/build/browsers/cdp-chromium.d.ts +41 -0
  10. package/build/browsers/cdp-chromium.js +287 -0
  11. package/build/browsers/index.d.ts +26 -0
  12. package/build/browsers/index.js +183 -0
  13. package/build/browsers/playwright-chromium.d.ts +34 -0
  14. package/build/browsers/playwright-chromium.js +106 -0
  15. package/build/browsers/playwright-firefox.d.ts +34 -0
  16. package/build/browsers/playwright-firefox.js +101 -0
  17. package/build/browsers/playwright-webkit.d.ts +34 -0
  18. package/build/browsers/playwright-webkit.js +101 -0
  19. package/build/config.d.ts +138 -0
  20. package/build/config.js +349 -0
  21. package/build/constants.d.ts +4 -0
  22. package/build/constants.js +4 -0
  23. package/build/data/classes.json +1 -0
  24. package/build/data/selectors.json +1 -0
  25. package/build/exports.d.ts +20 -0
  26. package/build/exports.js +22 -0
  27. package/build/file-system.d.ts +24 -0
  28. package/build/file-system.js +46 -0
  29. package/build/hooks.d.ts +5 -0
  30. package/build/hooks.js +20 -0
  31. package/build/http.d.ts +175 -0
  32. package/build/http.js +104 -0
  33. package/build/index.d.ts +1 -0
  34. package/build/index.js +39 -0
  35. package/build/limiter.d.ts +24 -0
  36. package/build/limiter.js +147 -0
  37. package/build/limiter.spec.d.ts +1 -0
  38. package/build/limiter.spec.js +241 -0
  39. package/build/metrics.d.ts +24 -0
  40. package/build/metrics.js +86 -0
  41. package/build/metrics.spec.d.ts +1 -0
  42. package/build/metrics.spec.js +35 -0
  43. package/build/mime-types.d.ts +1 -0
  44. package/build/mime-types.js +328 -0
  45. package/build/monitoring.d.ts +13 -0
  46. package/build/monitoring.js +38 -0
  47. package/build/routes/chromium/http/content-post.body.json +514 -0
  48. package/build/routes/chromium/http/content-post.d.ts +34 -0
  49. package/build/routes/chromium/http/content-post.js +109 -0
  50. package/build/routes/chromium/http/content-post.query.json +183 -0
  51. package/build/routes/chromium/http/content-post.response.json +5 -0
  52. package/build/routes/chromium/http/download-post.body.json +32 -0
  53. package/build/routes/chromium/http/download-post.d.ts +16 -0
  54. package/build/routes/chromium/http/download-post.js +92 -0
  55. package/build/routes/chromium/http/download-post.query.json +120 -0
  56. package/build/routes/chromium/http/download-post.response.json +4 -0
  57. package/build/routes/chromium/http/function-post.body.json +32 -0
  58. package/build/routes/chromium/http/function-post.d.ts +18 -0
  59. package/build/routes/chromium/http/function-post.js +53 -0
  60. package/build/routes/chromium/http/function-post.query.json +120 -0
  61. package/build/routes/chromium/http/function-post.response.json +4 -0
  62. package/build/routes/chromium/http/pdf-post.body.json +654 -0
  63. package/build/routes/chromium/http/pdf-post.d.ts +35 -0
  64. package/build/routes/chromium/http/pdf-post.js +107 -0
  65. package/build/routes/chromium/http/pdf-post.query.json +120 -0
  66. package/build/routes/chromium/http/pdf-post.response.json +5 -0
  67. package/build/routes/chromium/http/performance.body.json +26 -0
  68. package/build/routes/chromium/http/performance.d.ts +17 -0
  69. package/build/routes/chromium/http/performance.js +30 -0
  70. package/build/routes/chromium/http/performance.query.json +120 -0
  71. package/build/routes/chromium/http/performance.response.json +7 -0
  72. package/build/routes/chromium/http/scrape-post.body.json +561 -0
  73. package/build/routes/chromium/http/scrape-post.d.ts +106 -0
  74. package/build/routes/chromium/http/scrape-post.js +205 -0
  75. package/build/routes/chromium/http/scrape-post.query.json +183 -0
  76. package/build/routes/chromium/http/scrape-post.response.json +325 -0
  77. package/build/routes/chromium/http/screenshot-post.body.json +604 -0
  78. package/build/routes/chromium/http/screenshot-post.d.ts +37 -0
  79. package/build/routes/chromium/http/screenshot-post.js +124 -0
  80. package/build/routes/chromium/http/screenshot-post.query.json +120 -0
  81. package/build/routes/chromium/http/screenshot-post.response.json +5 -0
  82. package/build/routes/chromium/tests/content.spec.d.ts +1 -0
  83. package/build/routes/chromium/tests/content.spec.js +285 -0
  84. package/build/routes/chromium/tests/download.spec.d.ts +1 -0
  85. package/build/routes/chromium/tests/download.spec.js +67 -0
  86. package/build/routes/chromium/tests/function.spec.d.ts +1 -0
  87. package/build/routes/chromium/tests/function.spec.js +245 -0
  88. package/build/routes/chromium/tests/pdf.spec.d.ts +1 -0
  89. package/build/routes/chromium/tests/pdf.spec.js +333 -0
  90. package/build/routes/chromium/tests/performance.spec.d.ts +1 -0
  91. package/build/routes/chromium/tests/performance.spec.js +124 -0
  92. package/build/routes/chromium/tests/scrape.spec.d.ts +1 -0
  93. package/build/routes/chromium/tests/scrape.spec.js +354 -0
  94. package/build/routes/chromium/tests/screenshot.spec.d.ts +1 -0
  95. package/build/routes/chromium/tests/screenshot.spec.js +339 -0
  96. package/build/routes/chromium/tests/websocket.spec.d.ts +1 -0
  97. package/build/routes/chromium/tests/websocket.spec.js +309 -0
  98. package/build/routes/chromium/utils/function/client.d.ts +26 -0
  99. package/build/routes/chromium/utils/function/client.js +66 -0
  100. package/build/routes/chromium/utils/function/handler.d.ts +18 -0
  101. package/build/routes/chromium/utils/function/handler.js +95 -0
  102. package/build/routes/chromium/utils/performance/child.d.ts +1 -0
  103. package/build/routes/chromium/utils/performance/child.js +29 -0
  104. package/build/routes/chromium/utils/performance/main.d.ts +3 -0
  105. package/build/routes/chromium/utils/performance/main.js +65 -0
  106. package/build/routes/chromium/utils/performance/types.d.ts +21 -0
  107. package/build/routes/chromium/utils/performance/types.js +1 -0
  108. package/build/routes/chromium/ws/browser.d.ts +6 -0
  109. package/build/routes/chromium/ws/browser.js +11 -0
  110. package/build/routes/chromium/ws/browser.query.json +120 -0
  111. package/build/routes/chromium/ws/cdp-chromium.d.ts +6 -0
  112. package/build/routes/chromium/ws/cdp-chromium.js +11 -0
  113. package/build/routes/chromium/ws/cdp-chromium.query.json +120 -0
  114. package/build/routes/chromium/ws/page.d.ts +6 -0
  115. package/build/routes/chromium/ws/page.js +11 -0
  116. package/build/routes/chromium/ws/page.query.json +120 -0
  117. package/build/routes/chromium/ws/playwright-chromium.d.ts +6 -0
  118. package/build/routes/chromium/ws/playwright-chromium.js +19 -0
  119. package/build/routes/chromium/ws/playwright-chromium.query.json +100 -0
  120. package/build/routes/firefox/tests/websocket.spec.d.ts +1 -0
  121. package/build/routes/firefox/tests/websocket.spec.js +104 -0
  122. package/build/routes/firefox/ws/playwright-firefox.d.ts +6 -0
  123. package/build/routes/firefox/ws/playwright-firefox.js +19 -0
  124. package/build/routes/firefox/ws/playwright-firefox.query.json +100 -0
  125. package/build/routes/management/http/config-get.d.ts +25 -0
  126. package/build/routes/management/http/config-get.js +43 -0
  127. package/build/routes/management/http/config-get.response.json +107 -0
  128. package/build/routes/management/http/metrics-get.d.ts +4 -0
  129. package/build/routes/management/http/metrics-get.js +24 -0
  130. package/build/routes/management/http/metrics-get.response.json +94 -0
  131. package/build/routes/management/http/metrics-total-get.d.ts +4 -0
  132. package/build/routes/management/http/metrics-total-get.js +60 -0
  133. package/build/routes/management/http/metrics-total-get.response.json +72 -0
  134. package/build/routes/management/http/sessions-get.d.ts +4 -0
  135. package/build/routes/management/http/sessions-get.js +21 -0
  136. package/build/routes/management/http/sessions-get.response.json +221 -0
  137. package/build/routes/management/http/static-get.d.ts +3 -0
  138. package/build/routes/management/http/static-get.js +67 -0
  139. package/build/routes/management/tests/management.spec.d.ts +1 -0
  140. package/build/routes/management/tests/management.spec.js +41 -0
  141. package/build/routes/webkit/tests/websocket.spec.d.ts +1 -0
  142. package/build/routes/webkit/tests/websocket.spec.js +104 -0
  143. package/build/routes/webkit/ws/playwright-webkit.d.ts +6 -0
  144. package/build/routes/webkit/ws/playwright-webkit.js +19 -0
  145. package/build/routes/webkit/ws/playwright-webkit.query.json +100 -0
  146. package/build/server.d.ts +38 -0
  147. package/build/server.js +365 -0
  148. package/build/shim.d.ts +9 -0
  149. package/build/shim.js +54 -0
  150. package/build/shim.spec.d.ts +1 -0
  151. package/build/shim.spec.js +114 -0
  152. package/build/types.d.ts +360 -0
  153. package/build/types.js +6 -0
  154. package/build/utils.d.ts +111 -0
  155. package/build/utils.js +570 -0
  156. package/build/webhooks.d.ts +11 -0
  157. package/build/webhooks.js +43 -0
  158. package/docker/base/.dockerignore +16 -0
  159. package/docker/base/Dockerfile +70 -0
  160. package/docker/chrome/.dockerignore +16 -0
  161. package/docker/chrome/Dockerfile +40 -0
  162. package/docker/firefox/.dockerignore +16 -0
  163. package/docker/firefox/Dockerfile +39 -0
  164. package/docker/multi/.dockerignore +16 -0
  165. package/docker/multi/Dockerfile +37 -0
  166. package/docker/sdk/.dockerignore +16 -0
  167. package/docker/sdk/Dockerfile +34 -0
  168. package/docker/webkit/.dockerignore +16 -0
  169. package/docker/webkit/Dockerfile +40 -0
  170. package/extensions/screencast/background.js +143 -0
  171. package/extensions/screencast/content_script.js +18 -0
  172. package/extensions/screencast/manifest.json +19 -0
  173. package/extensions/ublock/1p-filters.html +69 -0
  174. package/extensions/ublock/3p-filters.html +119 -0
  175. package/extensions/ublock/LICENSE.txt +674 -0
  176. package/extensions/ublock/_locales/ar/messages.json +1290 -0
  177. package/extensions/ublock/_locales/az/messages.json +1290 -0
  178. package/extensions/ublock/_locales/be/messages.json +1290 -0
  179. package/extensions/ublock/_locales/bg/messages.json +1290 -0
  180. package/extensions/ublock/_locales/bn/messages.json +1290 -0
  181. package/extensions/ublock/_locales/br_FR/messages.json +1290 -0
  182. package/extensions/ublock/_locales/bs/messages.json +1290 -0
  183. package/extensions/ublock/_locales/ca/messages.json +1290 -0
  184. package/extensions/ublock/_locales/cs/messages.json +1290 -0
  185. package/extensions/ublock/_locales/cv/messages.json +1290 -0
  186. package/extensions/ublock/_locales/da/messages.json +1290 -0
  187. package/extensions/ublock/_locales/de/messages.json +1290 -0
  188. package/extensions/ublock/_locales/el/messages.json +1290 -0
  189. package/extensions/ublock/_locales/en/messages.json +1292 -0
  190. package/extensions/ublock/_locales/en_GB/messages.json +1290 -0
  191. package/extensions/ublock/_locales/eo/messages.json +1290 -0
  192. package/extensions/ublock/_locales/es/messages.json +1290 -0
  193. package/extensions/ublock/_locales/et/messages.json +1290 -0
  194. package/extensions/ublock/_locales/eu/messages.json +1290 -0
  195. package/extensions/ublock/_locales/fa/messages.json +1290 -0
  196. package/extensions/ublock/_locales/fi/messages.json +1290 -0
  197. package/extensions/ublock/_locales/fil/messages.json +1290 -0
  198. package/extensions/ublock/_locales/fr/messages.json +1290 -0
  199. package/extensions/ublock/_locales/fy/messages.json +1290 -0
  200. package/extensions/ublock/_locales/gl/messages.json +1290 -0
  201. package/extensions/ublock/_locales/gu/messages.json +1290 -0
  202. package/extensions/ublock/_locales/he/messages.json +1290 -0
  203. package/extensions/ublock/_locales/hi/messages.json +1290 -0
  204. package/extensions/ublock/_locales/hr/messages.json +1290 -0
  205. package/extensions/ublock/_locales/hu/messages.json +1290 -0
  206. package/extensions/ublock/_locales/hy/messages.json +1290 -0
  207. package/extensions/ublock/_locales/id/messages.json +1290 -0
  208. package/extensions/ublock/_locales/it/messages.json +1290 -0
  209. package/extensions/ublock/_locales/ja/messages.json +1290 -0
  210. package/extensions/ublock/_locales/ka/messages.json +1290 -0
  211. package/extensions/ublock/_locales/kk/messages.json +1290 -0
  212. package/extensions/ublock/_locales/kn/messages.json +1290 -0
  213. package/extensions/ublock/_locales/ko/messages.json +1290 -0
  214. package/extensions/ublock/_locales/ku/messages.json +1290 -0
  215. package/extensions/ublock/_locales/lt/messages.json +1290 -0
  216. package/extensions/ublock/_locales/lv/messages.json +1290 -0
  217. package/extensions/ublock/_locales/mk/messages.json +1290 -0
  218. package/extensions/ublock/_locales/ml/messages.json +1290 -0
  219. package/extensions/ublock/_locales/mr/messages.json +1290 -0
  220. package/extensions/ublock/_locales/ms/messages.json +1290 -0
  221. package/extensions/ublock/_locales/nb/messages.json +1290 -0
  222. package/extensions/ublock/_locales/nl/messages.json +1290 -0
  223. package/extensions/ublock/_locales/no/messages.json +1290 -0
  224. package/extensions/ublock/_locales/oc/messages.json +1290 -0
  225. package/extensions/ublock/_locales/pa/messages.json +1290 -0
  226. package/extensions/ublock/_locales/pl/messages.json +1290 -0
  227. package/extensions/ublock/_locales/pt_BR/messages.json +1290 -0
  228. package/extensions/ublock/_locales/pt_PT/messages.json +1290 -0
  229. package/extensions/ublock/_locales/ro/messages.json +1290 -0
  230. package/extensions/ublock/_locales/ru/messages.json +1290 -0
  231. package/extensions/ublock/_locales/si/messages.json +1290 -0
  232. package/extensions/ublock/_locales/sk/messages.json +1290 -0
  233. package/extensions/ublock/_locales/sl/messages.json +1290 -0
  234. package/extensions/ublock/_locales/so/messages.json +1290 -0
  235. package/extensions/ublock/_locales/sq/messages.json +1290 -0
  236. package/extensions/ublock/_locales/sr/messages.json +1290 -0
  237. package/extensions/ublock/_locales/sv/messages.json +1290 -0
  238. package/extensions/ublock/_locales/sw/messages.json +1290 -0
  239. package/extensions/ublock/_locales/ta/messages.json +1290 -0
  240. package/extensions/ublock/_locales/te/messages.json +1290 -0
  241. package/extensions/ublock/_locales/th/messages.json +1290 -0
  242. package/extensions/ublock/_locales/tr/messages.json +1290 -0
  243. package/extensions/ublock/_locales/uk/messages.json +1290 -0
  244. package/extensions/ublock/_locales/ur/messages.json +1290 -0
  245. package/extensions/ublock/_locales/vi/messages.json +1290 -0
  246. package/extensions/ublock/_locales/zh_CN/messages.json +1290 -0
  247. package/extensions/ublock/_locales/zh_TW/messages.json +1290 -0
  248. package/extensions/ublock/about.html +63 -0
  249. package/extensions/ublock/advanced-settings.html +42 -0
  250. package/extensions/ublock/asset-viewer.html +50 -0
  251. package/extensions/ublock/assets/assets.json +903 -0
  252. package/extensions/ublock/assets/resources/scriptlets.js +4255 -0
  253. package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +65576 -0
  254. package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +33219 -0
  255. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/README.md +29 -0
  256. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +3732 -0
  257. package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +15431 -0
  258. package/extensions/ublock/assets/thirdparties/urlhaus-filter/LICENSE.md +42 -0
  259. package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +1970 -0
  260. package/extensions/ublock/assets/ublock/badlists.txt +77 -0
  261. package/extensions/ublock/assets/ublock/badware.min.txt +3033 -0
  262. package/extensions/ublock/assets/ublock/filters.min.txt +23419 -0
  263. package/extensions/ublock/assets/ublock/privacy.min.txt +575 -0
  264. package/extensions/ublock/assets/ublock/quick-fixes.min.txt +99 -0
  265. package/extensions/ublock/assets/ublock/unbreak.min.txt +2448 -0
  266. package/extensions/ublock/background.html +12 -0
  267. package/extensions/ublock/cloud-ui.html +23 -0
  268. package/extensions/ublock/code-viewer.html +53 -0
  269. package/extensions/ublock/css/1p-filters.css +26 -0
  270. package/extensions/ublock/css/3p-filters.css +250 -0
  271. package/extensions/ublock/css/about.css +3 -0
  272. package/extensions/ublock/css/advanced-settings.css +26 -0
  273. package/extensions/ublock/css/asset-viewer.css +79 -0
  274. package/extensions/ublock/css/click2load.css +53 -0
  275. package/extensions/ublock/css/cloud-ui.css +104 -0
  276. package/extensions/ublock/css/code-viewer.css +67 -0
  277. package/extensions/ublock/css/codemirror.css +326 -0
  278. package/extensions/ublock/css/common.css +347 -0
  279. package/extensions/ublock/css/dashboard-common.css +55 -0
  280. package/extensions/ublock/css/dashboard.css +115 -0
  281. package/extensions/ublock/css/devtools.css +22 -0
  282. package/extensions/ublock/css/document-blocked.css +146 -0
  283. package/extensions/ublock/css/dyna-rules.css +79 -0
  284. package/extensions/ublock/css/epicker-ui.css +270 -0
  285. package/extensions/ublock/css/fa-icons.css +149 -0
  286. package/extensions/ublock/css/fonts/Inter/Inter-Regular.woff2 +0 -0
  287. package/extensions/ublock/css/fonts/Inter/Inter-SemiBold.woff2 +0 -0
  288. package/extensions/ublock/css/fonts/Inter/LICENSE.txt +93 -0
  289. package/extensions/ublock/css/fonts/Metropolis/Metropolis-Regular.woff2 +0 -0
  290. package/extensions/ublock/css/fonts/Metropolis/Metropolis-SemiBold.woff2 +0 -0
  291. package/extensions/ublock/css/fonts/Metropolis/README.md +25 -0
  292. package/extensions/ublock/css/fonts/Metropolis/UNLICENSE +24 -0
  293. package/extensions/ublock/css/logger-ui-inspector.css +116 -0
  294. package/extensions/ublock/css/logger-ui.css +978 -0
  295. package/extensions/ublock/css/popup-fenix.css +778 -0
  296. package/extensions/ublock/css/settings.css +74 -0
  297. package/extensions/ublock/css/support.css +110 -0
  298. package/extensions/ublock/css/themes/default.css +526 -0
  299. package/extensions/ublock/css/whitelist.css +22 -0
  300. package/extensions/ublock/dashboard.html +47 -0
  301. package/extensions/ublock/devtools.html +58 -0
  302. package/extensions/ublock/document-blocked.html +64 -0
  303. package/extensions/ublock/dyna-rules.html +67 -0
  304. package/extensions/ublock/img/cloud.png +0 -0
  305. package/extensions/ublock/img/flags-of-the-world/README +9 -0
  306. package/extensions/ublock/img/flags-of-the-world/ad.png +0 -0
  307. package/extensions/ublock/img/flags-of-the-world/ae.png +0 -0
  308. package/extensions/ublock/img/flags-of-the-world/af.png +0 -0
  309. package/extensions/ublock/img/flags-of-the-world/ag.png +0 -0
  310. package/extensions/ublock/img/flags-of-the-world/ai.png +0 -0
  311. package/extensions/ublock/img/flags-of-the-world/al.png +0 -0
  312. package/extensions/ublock/img/flags-of-the-world/am.png +0 -0
  313. package/extensions/ublock/img/flags-of-the-world/ao.png +0 -0
  314. package/extensions/ublock/img/flags-of-the-world/aq.png +0 -0
  315. package/extensions/ublock/img/flags-of-the-world/ar.png +0 -0
  316. package/extensions/ublock/img/flags-of-the-world/as.png +0 -0
  317. package/extensions/ublock/img/flags-of-the-world/at.png +0 -0
  318. package/extensions/ublock/img/flags-of-the-world/au.png +0 -0
  319. package/extensions/ublock/img/flags-of-the-world/aw.png +0 -0
  320. package/extensions/ublock/img/flags-of-the-world/ax.png +0 -0
  321. package/extensions/ublock/img/flags-of-the-world/az.png +0 -0
  322. package/extensions/ublock/img/flags-of-the-world/ba.png +0 -0
  323. package/extensions/ublock/img/flags-of-the-world/bb.png +0 -0
  324. package/extensions/ublock/img/flags-of-the-world/bd.png +0 -0
  325. package/extensions/ublock/img/flags-of-the-world/be.png +0 -0
  326. package/extensions/ublock/img/flags-of-the-world/bf.png +0 -0
  327. package/extensions/ublock/img/flags-of-the-world/bg.png +0 -0
  328. package/extensions/ublock/img/flags-of-the-world/bh.png +0 -0
  329. package/extensions/ublock/img/flags-of-the-world/bi.png +0 -0
  330. package/extensions/ublock/img/flags-of-the-world/bj.png +0 -0
  331. package/extensions/ublock/img/flags-of-the-world/bl.png +0 -0
  332. package/extensions/ublock/img/flags-of-the-world/bm.png +0 -0
  333. package/extensions/ublock/img/flags-of-the-world/bn.png +0 -0
  334. package/extensions/ublock/img/flags-of-the-world/bo.png +0 -0
  335. package/extensions/ublock/img/flags-of-the-world/bq.png +0 -0
  336. package/extensions/ublock/img/flags-of-the-world/br.png +0 -0
  337. package/extensions/ublock/img/flags-of-the-world/bs.png +0 -0
  338. package/extensions/ublock/img/flags-of-the-world/bt.png +0 -0
  339. package/extensions/ublock/img/flags-of-the-world/bv.png +0 -0
  340. package/extensions/ublock/img/flags-of-the-world/bw.png +0 -0
  341. package/extensions/ublock/img/flags-of-the-world/by.png +0 -0
  342. package/extensions/ublock/img/flags-of-the-world/bz.png +0 -0
  343. package/extensions/ublock/img/flags-of-the-world/ca.png +0 -0
  344. package/extensions/ublock/img/flags-of-the-world/cc.png +0 -0
  345. package/extensions/ublock/img/flags-of-the-world/cd.png +0 -0
  346. package/extensions/ublock/img/flags-of-the-world/cf.png +0 -0
  347. package/extensions/ublock/img/flags-of-the-world/cg.png +0 -0
  348. package/extensions/ublock/img/flags-of-the-world/ch.png +0 -0
  349. package/extensions/ublock/img/flags-of-the-world/ci.png +0 -0
  350. package/extensions/ublock/img/flags-of-the-world/ck.png +0 -0
  351. package/extensions/ublock/img/flags-of-the-world/cl.png +0 -0
  352. package/extensions/ublock/img/flags-of-the-world/cm.png +0 -0
  353. package/extensions/ublock/img/flags-of-the-world/cn.png +0 -0
  354. package/extensions/ublock/img/flags-of-the-world/co.png +0 -0
  355. package/extensions/ublock/img/flags-of-the-world/cr.png +0 -0
  356. package/extensions/ublock/img/flags-of-the-world/cu.png +0 -0
  357. package/extensions/ublock/img/flags-of-the-world/cv.png +0 -0
  358. package/extensions/ublock/img/flags-of-the-world/cw.png +0 -0
  359. package/extensions/ublock/img/flags-of-the-world/cx.png +0 -0
  360. package/extensions/ublock/img/flags-of-the-world/cy.png +0 -0
  361. package/extensions/ublock/img/flags-of-the-world/cz.png +0 -0
  362. package/extensions/ublock/img/flags-of-the-world/de.png +0 -0
  363. package/extensions/ublock/img/flags-of-the-world/dj.png +0 -0
  364. package/extensions/ublock/img/flags-of-the-world/dk.png +0 -0
  365. package/extensions/ublock/img/flags-of-the-world/dm.png +0 -0
  366. package/extensions/ublock/img/flags-of-the-world/do.png +0 -0
  367. package/extensions/ublock/img/flags-of-the-world/dz.png +0 -0
  368. package/extensions/ublock/img/flags-of-the-world/ec.png +0 -0
  369. package/extensions/ublock/img/flags-of-the-world/ee.png +0 -0
  370. package/extensions/ublock/img/flags-of-the-world/eg.png +0 -0
  371. package/extensions/ublock/img/flags-of-the-world/eh.png +0 -0
  372. package/extensions/ublock/img/flags-of-the-world/er.png +0 -0
  373. package/extensions/ublock/img/flags-of-the-world/es.png +0 -0
  374. package/extensions/ublock/img/flags-of-the-world/et.png +0 -0
  375. package/extensions/ublock/img/flags-of-the-world/fi.png +0 -0
  376. package/extensions/ublock/img/flags-of-the-world/fj.png +0 -0
  377. package/extensions/ublock/img/flags-of-the-world/fk.png +0 -0
  378. package/extensions/ublock/img/flags-of-the-world/fm.png +0 -0
  379. package/extensions/ublock/img/flags-of-the-world/fo.png +0 -0
  380. package/extensions/ublock/img/flags-of-the-world/fr.png +0 -0
  381. package/extensions/ublock/img/flags-of-the-world/ga.png +0 -0
  382. package/extensions/ublock/img/flags-of-the-world/gb-eng.png +0 -0
  383. package/extensions/ublock/img/flags-of-the-world/gb-nir.png +0 -0
  384. package/extensions/ublock/img/flags-of-the-world/gb-sct.png +0 -0
  385. package/extensions/ublock/img/flags-of-the-world/gb-wls.png +0 -0
  386. package/extensions/ublock/img/flags-of-the-world/gb.png +0 -0
  387. package/extensions/ublock/img/flags-of-the-world/gd.png +0 -0
  388. package/extensions/ublock/img/flags-of-the-world/ge.png +0 -0
  389. package/extensions/ublock/img/flags-of-the-world/gf.png +0 -0
  390. package/extensions/ublock/img/flags-of-the-world/gg.png +0 -0
  391. package/extensions/ublock/img/flags-of-the-world/gh.png +0 -0
  392. package/extensions/ublock/img/flags-of-the-world/gi.png +0 -0
  393. package/extensions/ublock/img/flags-of-the-world/gl.png +0 -0
  394. package/extensions/ublock/img/flags-of-the-world/gm.png +0 -0
  395. package/extensions/ublock/img/flags-of-the-world/gn.png +0 -0
  396. package/extensions/ublock/img/flags-of-the-world/gp.png +0 -0
  397. package/extensions/ublock/img/flags-of-the-world/gq.png +0 -0
  398. package/extensions/ublock/img/flags-of-the-world/gr.png +0 -0
  399. package/extensions/ublock/img/flags-of-the-world/gs.png +0 -0
  400. package/extensions/ublock/img/flags-of-the-world/gt.png +0 -0
  401. package/extensions/ublock/img/flags-of-the-world/gu.png +0 -0
  402. package/extensions/ublock/img/flags-of-the-world/gw.png +0 -0
  403. package/extensions/ublock/img/flags-of-the-world/gy.png +0 -0
  404. package/extensions/ublock/img/flags-of-the-world/hk.png +0 -0
  405. package/extensions/ublock/img/flags-of-the-world/hm.png +0 -0
  406. package/extensions/ublock/img/flags-of-the-world/hn.png +0 -0
  407. package/extensions/ublock/img/flags-of-the-world/hr.png +0 -0
  408. package/extensions/ublock/img/flags-of-the-world/ht.png +0 -0
  409. package/extensions/ublock/img/flags-of-the-world/hu.png +0 -0
  410. package/extensions/ublock/img/flags-of-the-world/id.png +0 -0
  411. package/extensions/ublock/img/flags-of-the-world/ie.png +0 -0
  412. package/extensions/ublock/img/flags-of-the-world/il.png +0 -0
  413. package/extensions/ublock/img/flags-of-the-world/im.png +0 -0
  414. package/extensions/ublock/img/flags-of-the-world/in.png +0 -0
  415. package/extensions/ublock/img/flags-of-the-world/io.png +0 -0
  416. package/extensions/ublock/img/flags-of-the-world/iq.png +0 -0
  417. package/extensions/ublock/img/flags-of-the-world/ir.png +0 -0
  418. package/extensions/ublock/img/flags-of-the-world/is.png +0 -0
  419. package/extensions/ublock/img/flags-of-the-world/it.png +0 -0
  420. package/extensions/ublock/img/flags-of-the-world/je.png +0 -0
  421. package/extensions/ublock/img/flags-of-the-world/jm.png +0 -0
  422. package/extensions/ublock/img/flags-of-the-world/jo.png +0 -0
  423. package/extensions/ublock/img/flags-of-the-world/jp.png +0 -0
  424. package/extensions/ublock/img/flags-of-the-world/ke.png +0 -0
  425. package/extensions/ublock/img/flags-of-the-world/kg.png +0 -0
  426. package/extensions/ublock/img/flags-of-the-world/kh.png +0 -0
  427. package/extensions/ublock/img/flags-of-the-world/ki.png +0 -0
  428. package/extensions/ublock/img/flags-of-the-world/km.png +0 -0
  429. package/extensions/ublock/img/flags-of-the-world/kn.png +0 -0
  430. package/extensions/ublock/img/flags-of-the-world/kp.png +0 -0
  431. package/extensions/ublock/img/flags-of-the-world/kr.png +0 -0
  432. package/extensions/ublock/img/flags-of-the-world/kw.png +0 -0
  433. package/extensions/ublock/img/flags-of-the-world/ky.png +0 -0
  434. package/extensions/ublock/img/flags-of-the-world/kz.png +0 -0
  435. package/extensions/ublock/img/flags-of-the-world/la.png +0 -0
  436. package/extensions/ublock/img/flags-of-the-world/lb.png +0 -0
  437. package/extensions/ublock/img/flags-of-the-world/lc.png +0 -0
  438. package/extensions/ublock/img/flags-of-the-world/li.png +0 -0
  439. package/extensions/ublock/img/flags-of-the-world/lk.png +0 -0
  440. package/extensions/ublock/img/flags-of-the-world/lr.png +0 -0
  441. package/extensions/ublock/img/flags-of-the-world/ls.png +0 -0
  442. package/extensions/ublock/img/flags-of-the-world/lt.png +0 -0
  443. package/extensions/ublock/img/flags-of-the-world/lu.png +0 -0
  444. package/extensions/ublock/img/flags-of-the-world/lv.png +0 -0
  445. package/extensions/ublock/img/flags-of-the-world/ly.png +0 -0
  446. package/extensions/ublock/img/flags-of-the-world/ma.png +0 -0
  447. package/extensions/ublock/img/flags-of-the-world/mc.png +0 -0
  448. package/extensions/ublock/img/flags-of-the-world/md.png +0 -0
  449. package/extensions/ublock/img/flags-of-the-world/me.png +0 -0
  450. package/extensions/ublock/img/flags-of-the-world/mf.png +0 -0
  451. package/extensions/ublock/img/flags-of-the-world/mg.png +0 -0
  452. package/extensions/ublock/img/flags-of-the-world/mh.png +0 -0
  453. package/extensions/ublock/img/flags-of-the-world/mk.png +0 -0
  454. package/extensions/ublock/img/flags-of-the-world/ml.png +0 -0
  455. package/extensions/ublock/img/flags-of-the-world/mm.png +0 -0
  456. package/extensions/ublock/img/flags-of-the-world/mn.png +0 -0
  457. package/extensions/ublock/img/flags-of-the-world/mo.png +0 -0
  458. package/extensions/ublock/img/flags-of-the-world/mp.png +0 -0
  459. package/extensions/ublock/img/flags-of-the-world/mq.png +0 -0
  460. package/extensions/ublock/img/flags-of-the-world/mr.png +0 -0
  461. package/extensions/ublock/img/flags-of-the-world/ms.png +0 -0
  462. package/extensions/ublock/img/flags-of-the-world/mt.png +0 -0
  463. package/extensions/ublock/img/flags-of-the-world/mu.png +0 -0
  464. package/extensions/ublock/img/flags-of-the-world/mv.png +0 -0
  465. package/extensions/ublock/img/flags-of-the-world/mw.png +0 -0
  466. package/extensions/ublock/img/flags-of-the-world/mx.png +0 -0
  467. package/extensions/ublock/img/flags-of-the-world/my.png +0 -0
  468. package/extensions/ublock/img/flags-of-the-world/mz.png +0 -0
  469. package/extensions/ublock/img/flags-of-the-world/na.png +0 -0
  470. package/extensions/ublock/img/flags-of-the-world/nc.png +0 -0
  471. package/extensions/ublock/img/flags-of-the-world/ne.png +0 -0
  472. package/extensions/ublock/img/flags-of-the-world/nf.png +0 -0
  473. package/extensions/ublock/img/flags-of-the-world/ng.png +0 -0
  474. package/extensions/ublock/img/flags-of-the-world/ni.png +0 -0
  475. package/extensions/ublock/img/flags-of-the-world/nl.png +0 -0
  476. package/extensions/ublock/img/flags-of-the-world/no.png +0 -0
  477. package/extensions/ublock/img/flags-of-the-world/np.png +0 -0
  478. package/extensions/ublock/img/flags-of-the-world/nr.png +0 -0
  479. package/extensions/ublock/img/flags-of-the-world/nu.png +0 -0
  480. package/extensions/ublock/img/flags-of-the-world/nz.png +0 -0
  481. package/extensions/ublock/img/flags-of-the-world/om.png +0 -0
  482. package/extensions/ublock/img/flags-of-the-world/pa.png +0 -0
  483. package/extensions/ublock/img/flags-of-the-world/pe.png +0 -0
  484. package/extensions/ublock/img/flags-of-the-world/pf.png +0 -0
  485. package/extensions/ublock/img/flags-of-the-world/pg.png +0 -0
  486. package/extensions/ublock/img/flags-of-the-world/ph.png +0 -0
  487. package/extensions/ublock/img/flags-of-the-world/pk.png +0 -0
  488. package/extensions/ublock/img/flags-of-the-world/pl.png +0 -0
  489. package/extensions/ublock/img/flags-of-the-world/pm.png +0 -0
  490. package/extensions/ublock/img/flags-of-the-world/pn.png +0 -0
  491. package/extensions/ublock/img/flags-of-the-world/pr.png +0 -0
  492. package/extensions/ublock/img/flags-of-the-world/ps.png +0 -0
  493. package/extensions/ublock/img/flags-of-the-world/pt.png +0 -0
  494. package/extensions/ublock/img/flags-of-the-world/pw.png +0 -0
  495. package/extensions/ublock/img/flags-of-the-world/py.png +0 -0
  496. package/extensions/ublock/img/flags-of-the-world/qa.png +0 -0
  497. package/extensions/ublock/img/flags-of-the-world/re.png +0 -0
  498. package/extensions/ublock/img/flags-of-the-world/ro.png +0 -0
  499. package/extensions/ublock/img/flags-of-the-world/rs.png +0 -0
  500. package/extensions/ublock/img/flags-of-the-world/ru.png +0 -0
  501. package/extensions/ublock/img/flags-of-the-world/rw.png +0 -0
  502. package/extensions/ublock/img/flags-of-the-world/sa.png +0 -0
  503. package/extensions/ublock/img/flags-of-the-world/sb.png +0 -0
  504. package/extensions/ublock/img/flags-of-the-world/sc.png +0 -0
  505. package/extensions/ublock/img/flags-of-the-world/sd.png +0 -0
  506. package/extensions/ublock/img/flags-of-the-world/se.png +0 -0
  507. package/extensions/ublock/img/flags-of-the-world/sg.png +0 -0
  508. package/extensions/ublock/img/flags-of-the-world/sh.png +0 -0
  509. package/extensions/ublock/img/flags-of-the-world/si.png +0 -0
  510. package/extensions/ublock/img/flags-of-the-world/sj.png +0 -0
  511. package/extensions/ublock/img/flags-of-the-world/sk.png +0 -0
  512. package/extensions/ublock/img/flags-of-the-world/sl.png +0 -0
  513. package/extensions/ublock/img/flags-of-the-world/sm.png +0 -0
  514. package/extensions/ublock/img/flags-of-the-world/sn.png +0 -0
  515. package/extensions/ublock/img/flags-of-the-world/so.png +0 -0
  516. package/extensions/ublock/img/flags-of-the-world/sr.png +0 -0
  517. package/extensions/ublock/img/flags-of-the-world/ss.png +0 -0
  518. package/extensions/ublock/img/flags-of-the-world/st.png +0 -0
  519. package/extensions/ublock/img/flags-of-the-world/sv.png +0 -0
  520. package/extensions/ublock/img/flags-of-the-world/sx.png +0 -0
  521. package/extensions/ublock/img/flags-of-the-world/sy.png +0 -0
  522. package/extensions/ublock/img/flags-of-the-world/sz.png +0 -0
  523. package/extensions/ublock/img/flags-of-the-world/tc.png +0 -0
  524. package/extensions/ublock/img/flags-of-the-world/td.png +0 -0
  525. package/extensions/ublock/img/flags-of-the-world/tf.png +0 -0
  526. package/extensions/ublock/img/flags-of-the-world/tg.png +0 -0
  527. package/extensions/ublock/img/flags-of-the-world/th.png +0 -0
  528. package/extensions/ublock/img/flags-of-the-world/tj.png +0 -0
  529. package/extensions/ublock/img/flags-of-the-world/tk.png +0 -0
  530. package/extensions/ublock/img/flags-of-the-world/tl.png +0 -0
  531. package/extensions/ublock/img/flags-of-the-world/tm.png +0 -0
  532. package/extensions/ublock/img/flags-of-the-world/tn.png +0 -0
  533. package/extensions/ublock/img/flags-of-the-world/to.png +0 -0
  534. package/extensions/ublock/img/flags-of-the-world/tr.png +0 -0
  535. package/extensions/ublock/img/flags-of-the-world/tt.png +0 -0
  536. package/extensions/ublock/img/flags-of-the-world/tv.png +0 -0
  537. package/extensions/ublock/img/flags-of-the-world/tw.png +0 -0
  538. package/extensions/ublock/img/flags-of-the-world/tz.png +0 -0
  539. package/extensions/ublock/img/flags-of-the-world/ua.png +0 -0
  540. package/extensions/ublock/img/flags-of-the-world/ug.png +0 -0
  541. package/extensions/ublock/img/flags-of-the-world/um.png +0 -0
  542. package/extensions/ublock/img/flags-of-the-world/us.png +0 -0
  543. package/extensions/ublock/img/flags-of-the-world/uy.png +0 -0
  544. package/extensions/ublock/img/flags-of-the-world/uz.png +0 -0
  545. package/extensions/ublock/img/flags-of-the-world/va.png +0 -0
  546. package/extensions/ublock/img/flags-of-the-world/vc.png +0 -0
  547. package/extensions/ublock/img/flags-of-the-world/ve.png +0 -0
  548. package/extensions/ublock/img/flags-of-the-world/vg.png +0 -0
  549. package/extensions/ublock/img/flags-of-the-world/vi.png +0 -0
  550. package/extensions/ublock/img/flags-of-the-world/vn.png +0 -0
  551. package/extensions/ublock/img/flags-of-the-world/vu.png +0 -0
  552. package/extensions/ublock/img/flags-of-the-world/wf.png +0 -0
  553. package/extensions/ublock/img/flags-of-the-world/ws.png +0 -0
  554. package/extensions/ublock/img/flags-of-the-world/xk.png +0 -0
  555. package/extensions/ublock/img/flags-of-the-world/ye.png +0 -0
  556. package/extensions/ublock/img/flags-of-the-world/yt.png +0 -0
  557. package/extensions/ublock/img/flags-of-the-world/za.png +0 -0
  558. package/extensions/ublock/img/flags-of-the-world/zm.png +0 -0
  559. package/extensions/ublock/img/flags-of-the-world/zw.png +0 -0
  560. package/extensions/ublock/img/fontawesome/LICENSE.txt +25 -0
  561. package/extensions/ublock/img/fontawesome/fontawesome-defs.svg +79 -0
  562. package/extensions/ublock/img/help16.png +0 -0
  563. package/extensions/ublock/img/icon_128.png +0 -0
  564. package/extensions/ublock/img/icon_16-loading.png +0 -0
  565. package/extensions/ublock/img/icon_16-off.png +0 -0
  566. package/extensions/ublock/img/icon_16.png +0 -0
  567. package/extensions/ublock/img/icon_32-loading.png +0 -0
  568. package/extensions/ublock/img/icon_32-off.png +0 -0
  569. package/extensions/ublock/img/icon_32.png +0 -0
  570. package/extensions/ublock/img/icon_64-loading.png +0 -0
  571. package/extensions/ublock/img/icon_64-off.png +0 -0
  572. package/extensions/ublock/img/icon_64.png +0 -0
  573. package/extensions/ublock/img/material-design.svg +16 -0
  574. package/extensions/ublock/img/photon.svg +16 -0
  575. package/extensions/ublock/img/ublock-defs.svg +27 -0
  576. package/extensions/ublock/img/ublock.svg +44 -0
  577. package/extensions/ublock/is-webrtc-supported.html +9 -0
  578. package/extensions/ublock/js/1p-filters.js +336 -0
  579. package/extensions/ublock/js/3p-filters.js +867 -0
  580. package/extensions/ublock/js/about.js +34 -0
  581. package/extensions/ublock/js/advanced-settings.js +194 -0
  582. package/extensions/ublock/js/asset-viewer.js +112 -0
  583. package/extensions/ublock/js/assets.js +1448 -0
  584. package/extensions/ublock/js/background.js +404 -0
  585. package/extensions/ublock/js/base64-custom.js +246 -0
  586. package/extensions/ublock/js/benchmarks.js +421 -0
  587. package/extensions/ublock/js/biditrie.js +947 -0
  588. package/extensions/ublock/js/cachestorage.js +510 -0
  589. package/extensions/ublock/js/click2load.js +60 -0
  590. package/extensions/ublock/js/cloud-ui.js +238 -0
  591. package/extensions/ublock/js/code-viewer.js +311 -0
  592. package/extensions/ublock/js/codemirror/search-thread.js +199 -0
  593. package/extensions/ublock/js/codemirror/search.js +504 -0
  594. package/extensions/ublock/js/codemirror/ubo-dynamic-filtering.js +239 -0
  595. package/extensions/ublock/js/codemirror/ubo-static-filtering.js +1126 -0
  596. package/extensions/ublock/js/commands.js +181 -0
  597. package/extensions/ublock/js/console.js +59 -0
  598. package/extensions/ublock/js/contentscript-extra.js +662 -0
  599. package/extensions/ublock/js/contentscript.js +1366 -0
  600. package/extensions/ublock/js/contextmenu.js +270 -0
  601. package/extensions/ublock/js/cosmetic-filtering.js +983 -0
  602. package/extensions/ublock/js/dashboard-common.js +215 -0
  603. package/extensions/ublock/js/dashboard.js +166 -0
  604. package/extensions/ublock/js/devtools.js +184 -0
  605. package/extensions/ublock/js/diff-updater.js +288 -0
  606. package/extensions/ublock/js/document-blocked.js +230 -0
  607. package/extensions/ublock/js/dom.js +213 -0
  608. package/extensions/ublock/js/dyna-rules.js +678 -0
  609. package/extensions/ublock/js/dynamic-net-filtering.js +488 -0
  610. package/extensions/ublock/js/epicker-ui.js +924 -0
  611. package/extensions/ublock/js/fa-icons.js +129 -0
  612. package/extensions/ublock/js/filtering-context.js +461 -0
  613. package/extensions/ublock/js/filtering-engines.js +50 -0
  614. package/extensions/ublock/js/hnswitches.js +289 -0
  615. package/extensions/ublock/js/hntrie.js +780 -0
  616. package/extensions/ublock/js/html-filtering.js +465 -0
  617. package/extensions/ublock/js/httpheader-filtering.js +213 -0
  618. package/extensions/ublock/js/i18n.js +346 -0
  619. package/extensions/ublock/js/is-webrtc-supported.js +52 -0
  620. package/extensions/ublock/js/logger-ui-inspector.js +652 -0
  621. package/extensions/ublock/js/logger-ui.js +3028 -0
  622. package/extensions/ublock/js/logger.js +84 -0
  623. package/extensions/ublock/js/lz4.js +190 -0
  624. package/extensions/ublock/js/messaging.js +2095 -0
  625. package/extensions/ublock/js/pagestore.js +1140 -0
  626. package/extensions/ublock/js/popup-fenix.js +1529 -0
  627. package/extensions/ublock/js/redirect-engine.js +494 -0
  628. package/extensions/ublock/js/redirect-resources.js +193 -0
  629. package/extensions/ublock/js/reverselookup-worker.js +287 -0
  630. package/extensions/ublock/js/reverselookup.js +223 -0
  631. package/extensions/ublock/js/scriptlet-filtering.js +556 -0
  632. package/extensions/ublock/js/scriptlets/cosmetic-logger.js +376 -0
  633. package/extensions/ublock/js/scriptlets/cosmetic-off.js +48 -0
  634. package/extensions/ublock/js/scriptlets/cosmetic-on.js +48 -0
  635. package/extensions/ublock/js/scriptlets/cosmetic-report.js +142 -0
  636. package/extensions/ublock/js/scriptlets/dom-inspector.js +906 -0
  637. package/extensions/ublock/js/scriptlets/dom-survey-elements.js +72 -0
  638. package/extensions/ublock/js/scriptlets/dom-survey-scripts.js +126 -0
  639. package/extensions/ublock/js/scriptlets/epicker.js +1365 -0
  640. package/extensions/ublock/js/scriptlets/load-3p-css.js +67 -0
  641. package/extensions/ublock/js/scriptlets/load-large-media-all.js +62 -0
  642. package/extensions/ublock/js/scriptlets/load-large-media-interactive.js +299 -0
  643. package/extensions/ublock/js/scriptlets/noscript-spoof.js +89 -0
  644. package/extensions/ublock/js/scriptlets/should-inject-contentscript.js +40 -0
  645. package/extensions/ublock/js/scriptlets/subscriber.js +113 -0
  646. package/extensions/ublock/js/scriptlets/updater.js +101 -0
  647. package/extensions/ublock/js/settings.js +317 -0
  648. package/extensions/ublock/js/start.js +509 -0
  649. package/extensions/ublock/js/static-dnr-filtering.js +497 -0
  650. package/extensions/ublock/js/static-ext-filtering-db.js +171 -0
  651. package/extensions/ublock/js/static-ext-filtering.js +184 -0
  652. package/extensions/ublock/js/static-filtering-io.js +144 -0
  653. package/extensions/ublock/js/static-filtering-parser.js +4459 -0
  654. package/extensions/ublock/js/static-net-filtering.js +5631 -0
  655. package/extensions/ublock/js/storage.js +1683 -0
  656. package/extensions/ublock/js/support.js +335 -0
  657. package/extensions/ublock/js/tab.js +1178 -0
  658. package/extensions/ublock/js/tasks.js +42 -0
  659. package/extensions/ublock/js/text-encode.js +275 -0
  660. package/extensions/ublock/js/text-utils.js +107 -0
  661. package/extensions/ublock/js/theme.js +151 -0
  662. package/extensions/ublock/js/traffic.js +1260 -0
  663. package/extensions/ublock/js/ublock.js +696 -0
  664. package/extensions/ublock/js/uri-utils.js +175 -0
  665. package/extensions/ublock/js/url-net-filtering.js +336 -0
  666. package/extensions/ublock/js/utils.js +208 -0
  667. package/extensions/ublock/js/vapi-background-ext.js +254 -0
  668. package/extensions/ublock/js/vapi-background.js +1802 -0
  669. package/extensions/ublock/js/vapi-client-extra.js +312 -0
  670. package/extensions/ublock/js/vapi-client.js +280 -0
  671. package/extensions/ublock/js/vapi-common.js +308 -0
  672. package/extensions/ublock/js/vapi.js +89 -0
  673. package/extensions/ublock/js/wasm/README.md +24 -0
  674. package/extensions/ublock/js/wasm/biditrie.wasm +0 -0
  675. package/extensions/ublock/js/wasm/biditrie.wat +728 -0
  676. package/extensions/ublock/js/wasm/hntrie.wasm +0 -0
  677. package/extensions/ublock/js/wasm/hntrie.wat +724 -0
  678. package/extensions/ublock/js/webext.js +164 -0
  679. package/extensions/ublock/js/whitelist.js +258 -0
  680. package/extensions/ublock/lib/codemirror/LICENSE +21 -0
  681. package/extensions/ublock/lib/codemirror/README.md +47 -0
  682. package/extensions/ublock/lib/codemirror/addon/comment/comment.js +211 -0
  683. package/extensions/ublock/lib/codemirror/addon/display/panel.js +133 -0
  684. package/extensions/ublock/lib/codemirror/addon/edit/closebrackets.js +201 -0
  685. package/extensions/ublock/lib/codemirror/addon/edit/matchbrackets.js +160 -0
  686. package/extensions/ublock/lib/codemirror/addon/fold/foldcode.js +157 -0
  687. package/extensions/ublock/lib/codemirror/addon/fold/foldgutter.css +20 -0
  688. package/extensions/ublock/lib/codemirror/addon/fold/foldgutter.js +163 -0
  689. package/extensions/ublock/lib/codemirror/addon/hint/show-hint.css +36 -0
  690. package/extensions/ublock/lib/codemirror/addon/hint/show-hint.js +509 -0
  691. package/extensions/ublock/lib/codemirror/addon/merge/merge.css +119 -0
  692. package/extensions/ublock/lib/codemirror/addon/merge/merge.js +1006 -0
  693. package/extensions/ublock/lib/codemirror/addon/scroll/annotatescrollbar.js +128 -0
  694. package/extensions/ublock/lib/codemirror/addon/search/matchesonscrollbar.css +8 -0
  695. package/extensions/ublock/lib/codemirror/addon/search/searchcursor.js +296 -0
  696. package/extensions/ublock/lib/codemirror/addon/selection/active-line.js +72 -0
  697. package/extensions/ublock/lib/codemirror/lib/codemirror.css +350 -0
  698. package/extensions/ublock/lib/codemirror/lib/codemirror.js +9800 -0
  699. package/extensions/ublock/lib/codemirror/mode/css/css.js +864 -0
  700. package/extensions/ublock/lib/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
  701. package/extensions/ublock/lib/codemirror/mode/javascript/javascript.js +942 -0
  702. package/extensions/ublock/lib/codemirror/mode/xml/xml.js +413 -0
  703. package/extensions/ublock/lib/codemirror/theme/night.css +27 -0
  704. package/extensions/ublock/lib/csstree/LICENSE +19 -0
  705. package/extensions/ublock/lib/csstree/css-tree.js +17 -0
  706. package/extensions/ublock/lib/diff/README.md +34 -0
  707. package/extensions/ublock/lib/diff/swatinem_diff.js +272 -0
  708. package/extensions/ublock/lib/hsluv/LICENSE +20 -0
  709. package/extensions/ublock/lib/hsluv/README +3 -0
  710. package/extensions/ublock/lib/hsluv/hsluv-0.1.0.min.js +8 -0
  711. package/extensions/ublock/lib/js-beautify/LICENSE +9 -0
  712. package/extensions/ublock/lib/js-beautify/README +5 -0
  713. package/extensions/ublock/lib/js-beautify/beautifier.min.js +2 -0
  714. package/extensions/ublock/lib/lz4/README.md +52 -0
  715. package/extensions/ublock/lib/lz4/lz4-block-codec-any.js +151 -0
  716. package/extensions/ublock/lib/lz4/lz4-block-codec-js.js +297 -0
  717. package/extensions/ublock/lib/lz4/lz4-block-codec-wasm.js +195 -0
  718. package/extensions/ublock/lib/lz4/lz4-block-codec.wasm +0 -0
  719. package/extensions/ublock/lib/lz4/lz4-block-codec.wat +745 -0
  720. package/extensions/ublock/lib/publicsuffixlist/publicsuffixlist.js +641 -0
  721. package/extensions/ublock/lib/publicsuffixlist/wasm/README.md +29 -0
  722. package/extensions/ublock/lib/publicsuffixlist/wasm/publicsuffixlist.wasm +0 -0
  723. package/extensions/ublock/lib/publicsuffixlist/wasm/publicsuffixlist.wat +322 -0
  724. package/extensions/ublock/lib/punycode.js +493 -0
  725. package/extensions/ublock/lib/regexanalyzer/CHANGES.md +15 -0
  726. package/extensions/ublock/lib/regexanalyzer/README.md +14 -0
  727. package/extensions/ublock/lib/regexanalyzer/regex.js +2276 -0
  728. package/extensions/ublock/logger-ui.html +232 -0
  729. package/extensions/ublock/managed_storage.json +73 -0
  730. package/extensions/ublock/manifest.json +115 -0
  731. package/extensions/ublock/no-dashboard.html +27 -0
  732. package/extensions/ublock/popup-fenix.html +114 -0
  733. package/extensions/ublock/settings.html +98 -0
  734. package/extensions/ublock/support.html +131 -0
  735. package/extensions/ublock/web_accessible_resources/1x1.gif +0 -0
  736. package/extensions/ublock/web_accessible_resources/2x2.png +0 -0
  737. package/extensions/ublock/web_accessible_resources/32x32.png +0 -0
  738. package/extensions/ublock/web_accessible_resources/3x2.png +0 -0
  739. package/extensions/ublock/web_accessible_resources/README.txt +11 -0
  740. package/extensions/ublock/web_accessible_resources/addthis_widget.js +39 -0
  741. package/extensions/ublock/web_accessible_resources/amazon_ads.js +70 -0
  742. package/extensions/ublock/web_accessible_resources/amazon_apstag.js +62 -0
  743. package/extensions/ublock/web_accessible_resources/ampproject_v0.js +34 -0
  744. package/extensions/ublock/web_accessible_resources/chartbeat.js +30 -0
  745. package/extensions/ublock/web_accessible_resources/click2load.html +28 -0
  746. package/extensions/ublock/web_accessible_resources/doubleclick_instream_ad_status.js +1 -0
  747. package/extensions/ublock/web_accessible_resources/empty +0 -0
  748. package/extensions/ublock/web_accessible_resources/epicker-ui.html +76 -0
  749. package/extensions/ublock/web_accessible_resources/fingerprint2.js +55 -0
  750. package/extensions/ublock/web_accessible_resources/fingerprint3.js +45 -0
  751. package/extensions/ublock/web_accessible_resources/google-analytics_analytics.js +110 -0
  752. package/extensions/ublock/web_accessible_resources/google-analytics_cx_api.js +36 -0
  753. package/extensions/ublock/web_accessible_resources/google-analytics_ga.js +130 -0
  754. package/extensions/ublock/web_accessible_resources/google-analytics_inpage_linkid.js +28 -0
  755. package/extensions/ublock/web_accessible_resources/google-ima.js +855 -0
  756. package/extensions/ublock/web_accessible_resources/googlesyndication_adsbygoogle.js +56 -0
  757. package/extensions/ublock/web_accessible_resources/googletagmanager_gtm.js +43 -0
  758. package/extensions/ublock/web_accessible_resources/googletagservices_gpt.js +153 -0
  759. package/extensions/ublock/web_accessible_resources/hd-main.js +46 -0
  760. package/extensions/ublock/web_accessible_resources/ligatus_angular-tag.js +29 -0
  761. package/extensions/ublock/web_accessible_resources/monkeybroker.js +43 -0
  762. package/extensions/ublock/web_accessible_resources/mxpnl_mixpanel.js +51 -0
  763. package/extensions/ublock/web_accessible_resources/nobab.js +87 -0
  764. package/extensions/ublock/web_accessible_resources/nobab2.js +42 -0
  765. package/extensions/ublock/web_accessible_resources/noeval-silent.js +28 -0
  766. package/extensions/ublock/web_accessible_resources/noeval.js +30 -0
  767. package/extensions/ublock/web_accessible_resources/nofab.js +67 -0
  768. package/extensions/ublock/web_accessible_resources/noop-0.1s.mp3 +0 -0
  769. package/extensions/ublock/web_accessible_resources/noop-0.5s.mp3 +0 -0
  770. package/extensions/ublock/web_accessible_resources/noop-1s.mp4 +0 -0
  771. package/extensions/ublock/web_accessible_resources/noop-vmap1.0.xml +1 -0
  772. package/extensions/ublock/web_accessible_resources/noop.css +1 -0
  773. package/extensions/ublock/web_accessible_resources/noop.html +5 -0
  774. package/extensions/ublock/web_accessible_resources/noop.js +3 -0
  775. package/extensions/ublock/web_accessible_resources/noop.json +1 -0
  776. package/extensions/ublock/web_accessible_resources/noop.txt +1 -0
  777. package/extensions/ublock/web_accessible_resources/outbrain-widget.js +72 -0
  778. package/extensions/ublock/web_accessible_resources/popads-dummy.js +30 -0
  779. package/extensions/ublock/web_accessible_resources/popads.js +40 -0
  780. package/extensions/ublock/web_accessible_resources/prebid-ads.js +26 -0
  781. package/extensions/ublock/web_accessible_resources/scorecardresearch_beacon.js +31 -0
  782. package/extensions/ublock/whitelist.html +63 -0
  783. package/external/.gitkeep +0 -0
  784. package/fonts/Calibri Bold Italic.ttf +0 -0
  785. package/fonts/Calibri Bold.TTF +0 -0
  786. package/fonts/Calibri Italic.ttf +0 -0
  787. package/fonts/Calibri Light Italic.ttf +0 -0
  788. package/fonts/Calibri Light.ttf +0 -0
  789. package/fonts/Calibri Regular.ttf +0 -0
  790. package/fonts/Emoji.ttf +0 -0
  791. package/fonts/SegoeUI-Bold.ttf +0 -0
  792. package/fonts/SegoeUI-Light.ttf +0 -0
  793. package/fonts/SegoeUI-Regular.ttf +0 -0
  794. package/fonts/SegoeUI-Semibold.ttf +0 -0
  795. package/fonts/SegoeUI-Semilight.ttf +0 -0
  796. package/fonts/Tahoma Bold.ttf +0 -0
  797. package/fonts/Tahoma.ttf +0 -0
  798. package/fonts/fonts.conf +21 -0
  799. package/package.json +177 -0
  800. package/scripts/build-function.js +18 -0
  801. package/scripts/build-open-api.js +274 -0
  802. package/scripts/build-schemas.js +86 -0
  803. package/scripts/build-selectors.js +36 -0
  804. package/scripts/clean.js +7 -0
  805. package/scripts/install-adblock.js +45 -0
  806. package/scripts/install-cdp-json.js +37 -0
  807. package/scripts/start.sh +30 -0
  808. package/scripts/test.sh +17 -0
  809. package/src/browserless.ts +253 -0
  810. package/src/browsers/cdp-chromium.ts +422 -0
  811. package/src/browsers/index.ts +296 -0
  812. package/src/browsers/playwright-chromium.ts +168 -0
  813. package/src/browsers/playwright-firefox.ts +161 -0
  814. package/src/browsers/playwright-webkit.ts +161 -0
  815. package/src/config.ts +426 -0
  816. package/src/constants.ts +4 -0
  817. package/src/exports.ts +23 -0
  818. package/src/file-system.ts +54 -0
  819. package/src/hooks.ts +37 -0
  820. package/src/http.ts +157 -0
  821. package/src/index.ts +41 -0
  822. package/src/limiter.spec.ts +365 -0
  823. package/src/limiter.ts +225 -0
  824. package/src/metrics.spec.ts +49 -0
  825. package/src/metrics.ts +108 -0
  826. package/src/mime-types.ts +332 -0
  827. package/src/monitoring.ts +53 -0
  828. package/src/routes/chromium/http/content-post.ts +238 -0
  829. package/src/routes/chromium/http/download-post.ts +162 -0
  830. package/src/routes/chromium/http/function-post.ts +98 -0
  831. package/src/routes/chromium/http/pdf-post.ts +234 -0
  832. package/src/routes/chromium/http/performance.ts +71 -0
  833. package/src/routes/chromium/http/scrape-post.ts +439 -0
  834. package/src/routes/chromium/http/screenshot-post.ts +262 -0
  835. package/src/routes/chromium/tests/content.spec.ts +340 -0
  836. package/src/routes/chromium/tests/download.spec.ts +77 -0
  837. package/src/routes/chromium/tests/function.spec.ts +279 -0
  838. package/src/routes/chromium/tests/pdf.spec.ts +375 -0
  839. package/src/routes/chromium/tests/performance.spec.ts +155 -0
  840. package/src/routes/chromium/tests/scrape.spec.ts +414 -0
  841. package/src/routes/chromium/tests/screenshot.spec.ts +387 -0
  842. package/src/routes/chromium/tests/websocket.spec.ts +407 -0
  843. package/src/routes/chromium/utils/function/client.ts +99 -0
  844. package/src/routes/chromium/utils/function/handler.ts +172 -0
  845. package/src/routes/chromium/utils/performance/child.ts +38 -0
  846. package/src/routes/chromium/utils/performance/main.ts +90 -0
  847. package/src/routes/chromium/utils/performance/types.ts +24 -0
  848. package/src/routes/chromium/ws/browser.ts +31 -0
  849. package/src/routes/chromium/ws/cdp-chromium.ts +31 -0
  850. package/src/routes/chromium/ws/page.ts +31 -0
  851. package/src/routes/chromium/ws/playwright-chromium.ts +44 -0
  852. package/src/routes/firefox/tests/websocket.spec.ts +146 -0
  853. package/src/routes/firefox/ws/playwright-firefox.ts +44 -0
  854. package/src/routes/management/http/config-get.ts +82 -0
  855. package/src/routes/management/http/metrics-get.ts +43 -0
  856. package/src/routes/management/http/metrics-total-get.ts +89 -0
  857. package/src/routes/management/http/sessions-get.ts +39 -0
  858. package/src/routes/management/http/static-get.ts +109 -0
  859. package/src/routes/management/tests/management.spec.ts +71 -0
  860. package/src/routes/webkit/tests/websocket.spec.ts +146 -0
  861. package/src/routes/webkit/ws/playwright-webkit.ts +44 -0
  862. package/src/server.ts +609 -0
  863. package/src/shim.spec.ts +154 -0
  864. package/src/shim.ts +78 -0
  865. package/src/types.ts +470 -0
  866. package/src/utils.ts +787 -0
  867. package/src/webhooks.ts +50 -0
  868. package/static/docs/browserless-logo.png +0 -0
  869. package/static/docs/docs.js +2 -0
  870. package/static/docs/index.html +71 -0
  871. package/static/docs/swagger.json +4232 -0
  872. package/static/favicon-32x32.png +0 -0
  873. package/static/function/client.js +31623 -0
  874. package/static/function/index.html +12 -0
  875. package/tsconfig.json +31 -0
@@ -0,0 +1,4459 @@
1
+ /*******************************************************************************
2
+
3
+ uBlock Origin - a browser extension to block requests.
4
+ Copyright (C) 2020-present Raymond Hill
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program. If not, see {http://www.gnu.org/licenses/}.
18
+
19
+ Home: https://github.com/gorhill/uBlock
20
+ */
21
+
22
+ 'use strict';
23
+
24
+ /******************************************************************************/
25
+
26
+ import Regex from '../lib/regexanalyzer/regex.js';
27
+ import * as cssTree from '../lib/csstree/css-tree.js';
28
+
29
+ /*******************************************************************************
30
+ *
31
+ * The parser creates a simple unidirectional AST from a raw line of text.
32
+ * Each node in the AST is a sequence of numbers, so as to avoid the need to
33
+ * make frequent memory allocation to represent the AST.
34
+ *
35
+ * All the AST nodes are allocated in the same integer-only array, which
36
+ * array is reused when parsing new lines.
37
+ *
38
+ * The AST can only be walked from top to bottom, then left to right.
39
+ *
40
+ * Each node typically refer to a corresponding string slice in the source
41
+ * text.
42
+ *
43
+ * It may happens a node requires to normalize the corresponding source slice,
44
+ * in which case there will be a reference in the AST to a transformed source
45
+ * string. (For example, a domain name might contain unicode characters, in
46
+ * which case the corresponding node will contain a reference to the
47
+ * (transformed) punycoded version of the domain name.)
48
+ *
49
+ * The AST can be easily used for syntax coloring purpose, in which case it's
50
+ * just a matter of walking through all the nodes in natural order.
51
+ *
52
+ * A tree walking utility class exists for compilation and syntax coloring
53
+ * purpose.
54
+ *
55
+ **/
56
+
57
+ /******************************************************************************/
58
+
59
+ let iota = 0;
60
+
61
+ iota = 0;
62
+ export const AST_TYPE_NONE = iota++;
63
+ export const AST_TYPE_UNKNOWN = iota++;
64
+ export const AST_TYPE_COMMENT = iota++;
65
+ export const AST_TYPE_NETWORK = iota++;
66
+ export const AST_TYPE_EXTENDED = iota++;
67
+
68
+ iota = 0;
69
+ export const AST_TYPE_NETWORK_PATTERN_ANY = iota++;
70
+ export const AST_TYPE_NETWORK_PATTERN_HOSTNAME = iota++;
71
+ export const AST_TYPE_NETWORK_PATTERN_PLAIN = iota++;
72
+ export const AST_TYPE_NETWORK_PATTERN_REGEX = iota++;
73
+ export const AST_TYPE_NETWORK_PATTERN_GENERIC = iota++;
74
+ export const AST_TYPE_NETWORK_PATTERN_BAD = iota++;
75
+ export const AST_TYPE_EXTENDED_COSMETIC = iota++;
76
+ export const AST_TYPE_EXTENDED_SCRIPTLET = iota++;
77
+ export const AST_TYPE_EXTENDED_HTML = iota++;
78
+ export const AST_TYPE_EXTENDED_RESPONSEHEADER = iota++;
79
+ export const AST_TYPE_COMMENT_PREPARSER = iota++;
80
+
81
+ iota = 0;
82
+ export const AST_FLAG_UNSUPPORTED = 1 << iota++;
83
+ export const AST_FLAG_IGNORE = 1 << iota++;
84
+ export const AST_FLAG_HAS_ERROR = 1 << iota++;
85
+ export const AST_FLAG_IS_EXCEPTION = 1 << iota++;
86
+ export const AST_FLAG_EXT_STRONG = 1 << iota++;
87
+ export const AST_FLAG_EXT_STYLE = 1 << iota++;
88
+ export const AST_FLAG_EXT_SCRIPTLET_ADG = 1 << iota++;
89
+ export const AST_FLAG_NET_PATTERN_LEFT_HNANCHOR = 1 << iota++;
90
+ export const AST_FLAG_NET_PATTERN_RIGHT_PATHANCHOR = 1 << iota++;
91
+ export const AST_FLAG_NET_PATTERN_LEFT_ANCHOR = 1 << iota++;
92
+ export const AST_FLAG_NET_PATTERN_RIGHT_ANCHOR = 1 << iota++;
93
+ export const AST_FLAG_HAS_OPTIONS = 1 << iota++;
94
+
95
+ iota = 0;
96
+ export const AST_ERROR_NONE = 1 << iota++;
97
+ export const AST_ERROR_REGEX = 1 << iota++;
98
+ export const AST_ERROR_PATTERN = 1 << iota++;
99
+ export const AST_ERROR_DOMAIN_NAME = 1 << iota++;
100
+ export const AST_ERROR_OPTION_DUPLICATE = 1 << iota++;
101
+ export const AST_ERROR_OPTION_UNKNOWN = 1 << iota++;
102
+ export const AST_ERROR_OPTION_BADVALUE = 1 << iota++;
103
+ export const AST_ERROR_OPTION_EXCLUDED = 1 << iota++;
104
+ export const AST_ERROR_IF_TOKEN_UNKNOWN = 1 << iota++;
105
+ export const AST_ERROR_UNTRUSTED_SOURCE = 1 << iota++;
106
+
107
+ iota = 0;
108
+ const NODE_RIGHT_INDEX = iota++;
109
+ const NOOP_NODE_SIZE = iota;
110
+ const NODE_TYPE_INDEX = iota++;
111
+ const NODE_DOWN_INDEX = iota++;
112
+ const NODE_BEG_INDEX = iota++;
113
+ const NODE_END_INDEX = iota++;
114
+ const NODE_FLAGS_INDEX = iota++;
115
+ const NODE_TRANSFORM_INDEX = iota++;
116
+ const FULL_NODE_SIZE = iota;
117
+
118
+ iota = 0;
119
+ export const NODE_TYPE_NOOP = iota++;
120
+ export const NODE_TYPE_LINE_RAW = iota++;
121
+ export const NODE_TYPE_LINE_BODY = iota++;
122
+ export const NODE_TYPE_WHITESPACE = iota++;
123
+ export const NODE_TYPE_COMMENT = iota++;
124
+ export const NODE_TYPE_IGNORE = iota++;
125
+ export const NODE_TYPE_EXT_RAW = iota++;
126
+ export const NODE_TYPE_EXT_OPTIONS_ANCHOR = iota++;
127
+ export const NODE_TYPE_EXT_OPTIONS = iota++;
128
+ export const NODE_TYPE_EXT_DECORATION = iota++;
129
+ export const NODE_TYPE_EXT_PATTERN_RAW = iota++;
130
+ export const NODE_TYPE_EXT_PATTERN_COSMETIC = iota++;
131
+ export const NODE_TYPE_EXT_PATTERN_HTML = iota++;
132
+ export const NODE_TYPE_EXT_PATTERN_RESPONSEHEADER = iota++;
133
+ export const NODE_TYPE_EXT_PATTERN_SCRIPTLET = iota++;
134
+ export const NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN = iota++;
135
+ export const NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARGS = iota++;
136
+ export const NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG = iota++;
137
+ export const NODE_TYPE_NET_RAW = iota++;
138
+ export const NODE_TYPE_NET_EXCEPTION = iota++;
139
+ export const NODE_TYPE_NET_PATTERN_RAW = iota++;
140
+ export const NODE_TYPE_NET_PATTERN = iota++;
141
+ export const NODE_TYPE_NET_PATTERN_PART = iota++;
142
+ export const NODE_TYPE_NET_PATTERN_PART_SPECIAL = iota++;
143
+ export const NODE_TYPE_NET_PATTERN_PART_UNICODE = iota++;
144
+ export const NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR = iota++;
145
+ export const NODE_TYPE_NET_PATTERN_LEFT_ANCHOR = iota++;
146
+ export const NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR = iota++;
147
+ export const NODE_TYPE_NET_OPTIONS_ANCHOR = iota++;
148
+ export const NODE_TYPE_NET_OPTIONS = iota++;
149
+ export const NODE_TYPE_NET_OPTION_SEPARATOR = iota++;
150
+ export const NODE_TYPE_NET_OPTION_SENTINEL = iota++;
151
+ export const NODE_TYPE_NET_OPTION_RAW = iota++;
152
+ export const NODE_TYPE_NET_OPTION_NAME_NOT = iota++;
153
+ export const NODE_TYPE_NET_OPTION_NAME_UNKNOWN = iota++;
154
+ export const NODE_TYPE_NET_OPTION_NAME_1P = iota++;
155
+ export const NODE_TYPE_NET_OPTION_NAME_STRICT1P = iota++;
156
+ export const NODE_TYPE_NET_OPTION_NAME_3P = iota++;
157
+ export const NODE_TYPE_NET_OPTION_NAME_STRICT3P = iota++;
158
+ export const NODE_TYPE_NET_OPTION_NAME_ALL = iota++;
159
+ export const NODE_TYPE_NET_OPTION_NAME_BADFILTER = iota++;
160
+ export const NODE_TYPE_NET_OPTION_NAME_CNAME = iota++;
161
+ export const NODE_TYPE_NET_OPTION_NAME_CSP = iota++;
162
+ export const NODE_TYPE_NET_OPTION_NAME_CSS = iota++;
163
+ export const NODE_TYPE_NET_OPTION_NAME_DENYALLOW = iota++;
164
+ export const NODE_TYPE_NET_OPTION_NAME_DOC = iota++;
165
+ export const NODE_TYPE_NET_OPTION_NAME_EHIDE = iota++;
166
+ export const NODE_TYPE_NET_OPTION_NAME_EMPTY = iota++;
167
+ export const NODE_TYPE_NET_OPTION_NAME_FONT = iota++;
168
+ export const NODE_TYPE_NET_OPTION_NAME_FRAME = iota++;
169
+ export const NODE_TYPE_NET_OPTION_NAME_FROM = iota++;
170
+ export const NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK = iota++;
171
+ export const NODE_TYPE_NET_OPTION_NAME_GHIDE = iota++;
172
+ export const NODE_TYPE_NET_OPTION_NAME_HEADER = iota++;
173
+ export const NODE_TYPE_NET_OPTION_NAME_IMAGE = iota++;
174
+ export const NODE_TYPE_NET_OPTION_NAME_IMPORTANT = iota++;
175
+ export const NODE_TYPE_NET_OPTION_NAME_INLINEFONT = iota++;
176
+ export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++;
177
+ export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++;
178
+ export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
179
+ export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++;
180
+ export const NODE_TYPE_NET_OPTION_NAME_MP4 = iota++;
181
+ export const NODE_TYPE_NET_OPTION_NAME_NOOP = iota++;
182
+ export const NODE_TYPE_NET_OPTION_NAME_OBJECT = iota++;
183
+ export const NODE_TYPE_NET_OPTION_NAME_OTHER = iota++;
184
+ export const NODE_TYPE_NET_OPTION_NAME_PERMISSIONS = iota++;
185
+ export const NODE_TYPE_NET_OPTION_NAME_PING = iota++;
186
+ export const NODE_TYPE_NET_OPTION_NAME_POPUNDER = iota++;
187
+ export const NODE_TYPE_NET_OPTION_NAME_POPUP = iota++;
188
+ export const NODE_TYPE_NET_OPTION_NAME_REDIRECT = iota++;
189
+ export const NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE = iota++;
190
+ export const NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM = iota++;
191
+ export const NODE_TYPE_NET_OPTION_NAME_REPLACE = iota++;
192
+ export const NODE_TYPE_NET_OPTION_NAME_SCRIPT = iota++;
193
+ export const NODE_TYPE_NET_OPTION_NAME_SHIDE = iota++;
194
+ export const NODE_TYPE_NET_OPTION_NAME_TO = iota++;
195
+ export const NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM = iota++;
196
+ export const NODE_TYPE_NET_OPTION_NAME_XHR = iota++;
197
+ export const NODE_TYPE_NET_OPTION_NAME_WEBRTC = iota++;
198
+ export const NODE_TYPE_NET_OPTION_NAME_WEBSOCKET = iota++;
199
+ export const NODE_TYPE_NET_OPTION_ASSIGN = iota++;
200
+ export const NODE_TYPE_NET_OPTION_VALUE = iota++;
201
+ export const NODE_TYPE_OPTION_VALUE_DOMAIN_LIST = iota++;
202
+ export const NODE_TYPE_OPTION_VALUE_DOMAIN_RAW = iota++;
203
+ export const NODE_TYPE_OPTION_VALUE_NOT = iota++;
204
+ export const NODE_TYPE_OPTION_VALUE_DOMAIN = iota++;
205
+ export const NODE_TYPE_OPTION_VALUE_SEPARATOR = iota++;
206
+ export const NODE_TYPE_PREPARSE_DIRECTIVE = iota++;
207
+ export const NODE_TYPE_PREPARSE_DIRECTIVE_VALUE = iota++;
208
+ export const NODE_TYPE_PREPARSE_DIRECTIVE_IF = iota++;
209
+ export const NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE = iota++;
210
+ export const NODE_TYPE_COMMENT_URL = iota++;
211
+ export const NODE_TYPE_COUNT = iota;
212
+
213
+ iota = 0;
214
+ export const NODE_FLAG_IGNORE = 1 << iota++;
215
+ export const NODE_FLAG_ERROR = 1 << iota++;
216
+ export const NODE_FLAG_IS_NEGATED = 1 << iota++;
217
+ export const NODE_FLAG_OPTION_HAS_VALUE = 1 << iota++;
218
+ export const NODE_FLAG_PATTERN_UNTOKENIZABLE = 1 << iota++;
219
+
220
+ export const nodeTypeFromOptionName = new Map([
221
+ [ '', NODE_TYPE_NET_OPTION_NAME_UNKNOWN ],
222
+ [ '1p', NODE_TYPE_NET_OPTION_NAME_1P ],
223
+ /* synonym */ [ 'first-party', NODE_TYPE_NET_OPTION_NAME_1P ],
224
+ [ 'strict1p', NODE_TYPE_NET_OPTION_NAME_STRICT1P ],
225
+ [ '3p', NODE_TYPE_NET_OPTION_NAME_3P ],
226
+ /* synonym */ [ 'third-party', NODE_TYPE_NET_OPTION_NAME_3P ],
227
+ [ 'strict3p', NODE_TYPE_NET_OPTION_NAME_STRICT3P ],
228
+ [ 'all', NODE_TYPE_NET_OPTION_NAME_ALL ],
229
+ [ 'badfilter', NODE_TYPE_NET_OPTION_NAME_BADFILTER ],
230
+ [ 'cname', NODE_TYPE_NET_OPTION_NAME_CNAME ],
231
+ [ 'csp', NODE_TYPE_NET_OPTION_NAME_CSP ],
232
+ [ 'css', NODE_TYPE_NET_OPTION_NAME_CSS ],
233
+ /* synonym */ [ 'stylesheet', NODE_TYPE_NET_OPTION_NAME_CSS ],
234
+ [ 'denyallow', NODE_TYPE_NET_OPTION_NAME_DENYALLOW ],
235
+ [ 'doc', NODE_TYPE_NET_OPTION_NAME_DOC ],
236
+ /* synonym */ [ 'document', NODE_TYPE_NET_OPTION_NAME_DOC ],
237
+ [ 'ehide', NODE_TYPE_NET_OPTION_NAME_EHIDE ],
238
+ /* synonym */ [ 'elemhide', NODE_TYPE_NET_OPTION_NAME_EHIDE ],
239
+ [ 'empty', NODE_TYPE_NET_OPTION_NAME_EMPTY ],
240
+ [ 'font', NODE_TYPE_NET_OPTION_NAME_FONT ],
241
+ [ 'frame', NODE_TYPE_NET_OPTION_NAME_FRAME ],
242
+ /* synonym */ [ 'subdocument', NODE_TYPE_NET_OPTION_NAME_FRAME ],
243
+ [ 'from', NODE_TYPE_NET_OPTION_NAME_FROM ],
244
+ /* synonym */ [ 'domain', NODE_TYPE_NET_OPTION_NAME_FROM ],
245
+ [ 'genericblock', NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK ],
246
+ [ 'ghide', NODE_TYPE_NET_OPTION_NAME_GHIDE ],
247
+ /* synonym */ [ 'generichide', NODE_TYPE_NET_OPTION_NAME_GHIDE ],
248
+ [ 'header', NODE_TYPE_NET_OPTION_NAME_HEADER ],
249
+ [ 'image', NODE_TYPE_NET_OPTION_NAME_IMAGE ],
250
+ [ 'important', NODE_TYPE_NET_OPTION_NAME_IMPORTANT ],
251
+ [ 'inline-font', NODE_TYPE_NET_OPTION_NAME_INLINEFONT ],
252
+ [ 'inline-script', NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT ],
253
+ [ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
254
+ [ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
255
+ [ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
256
+ [ 'mp4', NODE_TYPE_NET_OPTION_NAME_MP4 ],
257
+ [ '_', NODE_TYPE_NET_OPTION_NAME_NOOP ],
258
+ [ 'object', NODE_TYPE_NET_OPTION_NAME_OBJECT ],
259
+ /* synonym */ [ 'object-subrequest', NODE_TYPE_NET_OPTION_NAME_OBJECT ],
260
+ [ 'other', NODE_TYPE_NET_OPTION_NAME_OTHER ],
261
+ [ 'permissions', NODE_TYPE_NET_OPTION_NAME_PERMISSIONS ],
262
+ [ 'ping', NODE_TYPE_NET_OPTION_NAME_PING ],
263
+ /* synonym */ [ 'beacon', NODE_TYPE_NET_OPTION_NAME_PING ],
264
+ [ 'popunder', NODE_TYPE_NET_OPTION_NAME_POPUNDER ],
265
+ [ 'popup', NODE_TYPE_NET_OPTION_NAME_POPUP ],
266
+ [ 'redirect', NODE_TYPE_NET_OPTION_NAME_REDIRECT ],
267
+ /* synonym */ [ 'rewrite', NODE_TYPE_NET_OPTION_NAME_REDIRECT ],
268
+ [ 'redirect-rule', NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE ],
269
+ [ 'removeparam', NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM ],
270
+ [ 'replace', NODE_TYPE_NET_OPTION_NAME_REPLACE ],
271
+ /* synonym */ [ 'queryprune', NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM ],
272
+ [ 'script', NODE_TYPE_NET_OPTION_NAME_SCRIPT ],
273
+ [ 'shide', NODE_TYPE_NET_OPTION_NAME_SHIDE ],
274
+ /* synonym */ [ 'specifichide', NODE_TYPE_NET_OPTION_NAME_SHIDE ],
275
+ [ 'to', NODE_TYPE_NET_OPTION_NAME_TO ],
276
+ [ 'urltransform', NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM ],
277
+ [ 'xhr', NODE_TYPE_NET_OPTION_NAME_XHR ],
278
+ /* synonym */ [ 'xmlhttprequest', NODE_TYPE_NET_OPTION_NAME_XHR ],
279
+ [ 'webrtc', NODE_TYPE_NET_OPTION_NAME_WEBRTC ],
280
+ [ 'websocket', NODE_TYPE_NET_OPTION_NAME_WEBSOCKET ],
281
+ ]);
282
+
283
+ export const nodeNameFromNodeType = new Map([
284
+ [ NODE_TYPE_NOOP, 'noop' ],
285
+ [ NODE_TYPE_LINE_RAW, 'lineRaw' ],
286
+ [ NODE_TYPE_LINE_BODY, 'lineBody' ],
287
+ [ NODE_TYPE_WHITESPACE, 'whitespace' ],
288
+ [ NODE_TYPE_COMMENT, 'comment' ],
289
+ [ NODE_TYPE_IGNORE, 'ignore' ],
290
+ [ NODE_TYPE_EXT_RAW, 'extRaw' ],
291
+ [ NODE_TYPE_EXT_OPTIONS_ANCHOR, 'extOptionsAnchor' ],
292
+ [ NODE_TYPE_EXT_OPTIONS, 'extOptions' ],
293
+ [ NODE_TYPE_EXT_DECORATION, 'extDecoration' ],
294
+ [ NODE_TYPE_EXT_PATTERN_RAW, 'extPatternRaw' ],
295
+ [ NODE_TYPE_EXT_PATTERN_COSMETIC, 'extPatternCosmetic' ],
296
+ [ NODE_TYPE_EXT_PATTERN_HTML, 'extPatternHtml' ],
297
+ [ NODE_TYPE_EXT_PATTERN_RESPONSEHEADER, 'extPatternResponseheader' ],
298
+ [ NODE_TYPE_EXT_PATTERN_SCRIPTLET, 'extPatternScriptlet' ],
299
+ [ NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN, 'extPatternScriptletToken' ],
300
+ [ NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARGS, 'extPatternScriptletArgs' ],
301
+ [ NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG, 'extPatternScriptletArg' ],
302
+ [ NODE_TYPE_NET_RAW, 'netRaw' ],
303
+ [ NODE_TYPE_NET_EXCEPTION, 'netException' ],
304
+ [ NODE_TYPE_NET_PATTERN_RAW, 'netPatternRaw' ],
305
+ [ NODE_TYPE_NET_PATTERN, 'netPattern' ],
306
+ [ NODE_TYPE_NET_PATTERN_PART, 'netPatternPart' ],
307
+ [ NODE_TYPE_NET_PATTERN_PART_SPECIAL, 'netPatternPartSpecial' ],
308
+ [ NODE_TYPE_NET_PATTERN_PART_UNICODE, 'netPatternPartUnicode' ],
309
+ [ NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR, 'netPatternLeftHnanchor' ],
310
+ [ NODE_TYPE_NET_PATTERN_LEFT_ANCHOR, 'netPatternLeftAnchor' ],
311
+ [ NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR, 'netPatternRightAnchor' ],
312
+ [ NODE_TYPE_NET_OPTIONS_ANCHOR, 'netOptionsAnchor' ],
313
+ [ NODE_TYPE_NET_OPTIONS, 'netOptions' ],
314
+ [ NODE_TYPE_NET_OPTION_RAW, 'netOptionRaw' ],
315
+ [ NODE_TYPE_NET_OPTION_SEPARATOR, 'netOptionSeparator'],
316
+ [ NODE_TYPE_NET_OPTION_SENTINEL, 'netOptionSentinel' ],
317
+ [ NODE_TYPE_NET_OPTION_NAME_NOT, 'netOptionNameNot'],
318
+ [ NODE_TYPE_NET_OPTION_ASSIGN, 'netOptionAssign' ],
319
+ [ NODE_TYPE_NET_OPTION_VALUE, 'netOptionValue' ],
320
+ [ NODE_TYPE_OPTION_VALUE_DOMAIN_LIST, 'netOptionValueDomainList' ],
321
+ [ NODE_TYPE_OPTION_VALUE_DOMAIN_RAW, 'netOptionValueDomainRaw' ],
322
+ [ NODE_TYPE_OPTION_VALUE_NOT, 'netOptionValueNot' ],
323
+ [ NODE_TYPE_OPTION_VALUE_DOMAIN, 'netOptionValueDomain' ],
324
+ [ NODE_TYPE_OPTION_VALUE_SEPARATOR, 'netOptionsValueSeparator' ],
325
+ ]);
326
+ {
327
+ for ( const [ name, type ] of nodeTypeFromOptionName ) {
328
+ nodeNameFromNodeType.set(type, name);
329
+ }
330
+ }
331
+
332
+ /******************************************************************************/
333
+
334
+ // Precomputed AST layouts for most common filters.
335
+
336
+ const astTemplates = {
337
+ // ||example.com^
338
+ netHnAnchoredHostnameAscii: {
339
+ flags: AST_FLAG_NET_PATTERN_LEFT_HNANCHOR |
340
+ AST_FLAG_NET_PATTERN_RIGHT_PATHANCHOR,
341
+ type: NODE_TYPE_LINE_BODY,
342
+ beg: 0,
343
+ end: 0,
344
+ children: [{
345
+ type: NODE_TYPE_NET_RAW,
346
+ beg: 0,
347
+ end: 0,
348
+ children: [{
349
+ type: NODE_TYPE_NET_PATTERN_RAW,
350
+ beg: 0,
351
+ end: 0,
352
+ register: true,
353
+ children: [{
354
+ type: NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR,
355
+ beg: 0,
356
+ end: 2,
357
+ }, {
358
+ type: NODE_TYPE_NET_PATTERN,
359
+ beg: 2,
360
+ end: -1,
361
+ register: true,
362
+ }, {
363
+ type: NODE_TYPE_NET_PATTERN_PART_SPECIAL,
364
+ beg: -1,
365
+ end: 0,
366
+ }],
367
+ }],
368
+ }],
369
+ },
370
+ // ||example.com^$third-party
371
+ net3pHnAnchoredHostnameAscii: {
372
+ flags: AST_FLAG_NET_PATTERN_LEFT_HNANCHOR |
373
+ AST_FLAG_NET_PATTERN_RIGHT_PATHANCHOR |
374
+ AST_FLAG_HAS_OPTIONS,
375
+ type: NODE_TYPE_LINE_BODY,
376
+ beg: 0,
377
+ end: 0,
378
+ children: [{
379
+ type: NODE_TYPE_NET_RAW,
380
+ beg: 0,
381
+ end: 0,
382
+ children: [{
383
+ type: NODE_TYPE_NET_PATTERN_RAW,
384
+ beg: 0,
385
+ end: 0,
386
+ register: true,
387
+ children: [{
388
+ type: NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR,
389
+ beg: 0,
390
+ end: 2,
391
+ }, {
392
+ type: NODE_TYPE_NET_PATTERN,
393
+ beg: 2,
394
+ end: -13,
395
+ register: true,
396
+ }, {
397
+ type: NODE_TYPE_NET_PATTERN_PART_SPECIAL,
398
+ beg: -13,
399
+ end: -12,
400
+ }],
401
+ }, {
402
+ type: NODE_TYPE_NET_OPTIONS_ANCHOR,
403
+ beg: -12,
404
+ end: -11,
405
+ }, {
406
+ type: NODE_TYPE_NET_OPTIONS,
407
+ beg: -11,
408
+ end: 0,
409
+ register: true,
410
+ children: [{
411
+ type: NODE_TYPE_NET_OPTION_RAW,
412
+ beg: 0,
413
+ end: 0,
414
+ children: [{
415
+ type: NODE_TYPE_NET_OPTION_NAME_3P,
416
+ beg: 0,
417
+ end: 0,
418
+ register: true,
419
+ }],
420
+ }],
421
+ }],
422
+ }],
423
+ },
424
+ // ||example.com/path/to/resource
425
+ netHnAnchoredPlainAscii: {
426
+ flags: AST_FLAG_NET_PATTERN_LEFT_HNANCHOR,
427
+ type: NODE_TYPE_LINE_BODY,
428
+ beg: 0,
429
+ end: 0,
430
+ children: [{
431
+ type: NODE_TYPE_NET_RAW,
432
+ beg: 0,
433
+ end: 0,
434
+ children: [{
435
+ type: NODE_TYPE_NET_PATTERN_RAW,
436
+ beg: 0,
437
+ end: 0,
438
+ register: true,
439
+ children: [{
440
+ type: NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR,
441
+ beg: 0,
442
+ end: 2,
443
+ }, {
444
+ type: NODE_TYPE_NET_PATTERN,
445
+ beg: 2,
446
+ end: 0,
447
+ register: true,
448
+ }],
449
+ }],
450
+ }],
451
+ },
452
+ // example.com
453
+ // -resource.
454
+ netPlainAscii: {
455
+ type: NODE_TYPE_LINE_BODY,
456
+ beg: 0,
457
+ end: 0,
458
+ children: [{
459
+ type: NODE_TYPE_NET_RAW,
460
+ beg: 0,
461
+ end: 0,
462
+ children: [{
463
+ type: NODE_TYPE_NET_PATTERN_RAW,
464
+ beg: 0,
465
+ end: 0,
466
+ register: true,
467
+ children: [{
468
+ type: NODE_TYPE_NET_PATTERN,
469
+ beg: 0,
470
+ end: 0,
471
+ register: true,
472
+ }],
473
+ }],
474
+ }],
475
+ },
476
+ // 127.0.0.1 example.com
477
+ netHosts1: {
478
+ type: NODE_TYPE_LINE_BODY,
479
+ beg: 0,
480
+ end: 0,
481
+ children: [{
482
+ type: NODE_TYPE_NET_RAW,
483
+ beg: 0,
484
+ end: 0,
485
+ children: [{
486
+ type: NODE_TYPE_NET_PATTERN_RAW,
487
+ beg: 0,
488
+ end: 0,
489
+ register: true,
490
+ children: [{
491
+ type: NODE_TYPE_IGNORE,
492
+ beg: 0,
493
+ end: 10,
494
+ }, {
495
+ type: NODE_TYPE_NET_PATTERN,
496
+ beg: 10,
497
+ end: 0,
498
+ register: true,
499
+ }],
500
+ }],
501
+ }],
502
+ },
503
+ // 0.0.0.0 example.com
504
+ netHosts2: {
505
+ type: NODE_TYPE_LINE_BODY,
506
+ beg: 0,
507
+ end: 0,
508
+ children: [{
509
+ type: NODE_TYPE_NET_RAW,
510
+ beg: 0,
511
+ end: 0,
512
+ children: [{
513
+ type: NODE_TYPE_NET_PATTERN_RAW,
514
+ beg: 0,
515
+ end: 0,
516
+ register: true,
517
+ children: [{
518
+ type: NODE_TYPE_IGNORE,
519
+ beg: 0,
520
+ end: 8,
521
+ }, {
522
+ type: NODE_TYPE_NET_PATTERN,
523
+ beg: 8,
524
+ end: 0,
525
+ register: true,
526
+ }],
527
+ }],
528
+ }],
529
+ },
530
+ // ##.ads-container
531
+ extPlainGenericSelector: {
532
+ type: NODE_TYPE_LINE_BODY,
533
+ beg: 0,
534
+ end: 0,
535
+ children: [{
536
+ type: NODE_TYPE_EXT_RAW,
537
+ beg: 0,
538
+ end: 0,
539
+ children: [{
540
+ type: NODE_TYPE_EXT_OPTIONS_ANCHOR,
541
+ beg: 0,
542
+ end: 2,
543
+ register: true,
544
+ }, {
545
+ type: NODE_TYPE_EXT_PATTERN_RAW,
546
+ beg: 2,
547
+ end: 0,
548
+ register: true,
549
+ children: [{
550
+ type: NODE_TYPE_EXT_PATTERN_COSMETIC,
551
+ beg: 0,
552
+ end: 0,
553
+ }],
554
+ }],
555
+ }],
556
+ },
557
+ };
558
+
559
+ /******************************************************************************/
560
+
561
+ export const removableHTTPHeaders = new Set([
562
+ 'location',
563
+ 'refresh',
564
+ 'report-to',
565
+ 'set-cookie',
566
+ ]);
567
+
568
+ export const preparserIfTokens = new Set([
569
+ 'ext_ublock',
570
+ 'ext_ubol',
571
+ 'ext_devbuild',
572
+ 'env_chromium',
573
+ 'env_edge',
574
+ 'env_firefox',
575
+ 'env_legacy',
576
+ 'env_mobile',
577
+ 'env_mv3',
578
+ 'env_safari',
579
+ 'cap_html_filtering',
580
+ 'cap_user_stylesheet',
581
+ 'false',
582
+ 'ext_abp',
583
+ 'adguard',
584
+ 'adguard_app_android',
585
+ 'adguard_app_ios',
586
+ 'adguard_app_mac',
587
+ 'adguard_app_windows',
588
+ 'adguard_ext_android_cb',
589
+ 'adguard_ext_chromium',
590
+ 'adguard_ext_edge',
591
+ 'adguard_ext_firefox',
592
+ 'adguard_ext_opera',
593
+ 'adguard_ext_safari',
594
+ ]);
595
+
596
+ /******************************************************************************/
597
+
598
+ const exCharCodeAt = (s, i) => {
599
+ const pos = i >= 0 ? i : s.length + i;
600
+ return pos >= 0 ? s.charCodeAt(pos) : -1;
601
+ };
602
+
603
+ /******************************************************************************/
604
+
605
+ class ArgListParser {
606
+ constructor(separatorChar = ',', mustQuote = false) {
607
+ this.separatorChar = this.actualSeparatorChar = separatorChar;
608
+ this.separatorCode = this.actualSeparatorCode = separatorChar.charCodeAt(0);
609
+ this.mustQuote = mustQuote;
610
+ this.quoteBeg = 0; this.quoteEnd = 0;
611
+ this.argBeg = 0; this.argEnd = 0;
612
+ this.separatorBeg = 0; this.separatorEnd = 0;
613
+ this.transform = false;
614
+ this.failed = false;
615
+ this.reWhitespaceStart = /^\s+/;
616
+ this.reWhitespaceEnd = /\s+$/;
617
+ this.reOddTrailingEscape = /(?:^|[^\\])(?:\\\\)*\\$/;
618
+ this.reTrailingEscapeChars = /\\+$/;
619
+ }
620
+ nextArg(pattern, beg = 0) {
621
+ const len = pattern.length;
622
+ this.quoteBeg = beg + this.leftWhitespaceCount(pattern.slice(beg));
623
+ this.failed = false;
624
+ const qc = pattern.charCodeAt(this.quoteBeg);
625
+ if ( qc === 0x22 /* " */ || qc === 0x27 /* ' */ || qc === 0x60 /* ` */ ) {
626
+ this.indexOfNextArgSeparator(pattern, qc);
627
+ if ( this.argEnd !== len ) {
628
+ this.quoteEnd = this.argEnd + 1;
629
+ this.separatorBeg = this.separatorEnd = this.quoteEnd;
630
+ this.separatorEnd += this.leftWhitespaceCount(pattern.slice(this.quoteEnd));
631
+ if ( this.separatorEnd === len ) { return this; }
632
+ if ( pattern.charCodeAt(this.separatorEnd) === this.separatorCode ) {
633
+ this.separatorEnd += 1;
634
+ return this;
635
+ }
636
+ }
637
+ }
638
+ this.indexOfNextArgSeparator(pattern, this.separatorCode);
639
+ this.separatorBeg = this.separatorEnd = this.argEnd;
640
+ if ( this.separatorBeg < len ) {
641
+ this.separatorEnd += 1;
642
+ }
643
+ this.argEnd -= this.rightWhitespaceCount(pattern.slice(0, this.separatorBeg));
644
+ this.quoteEnd = this.argEnd;
645
+ if ( this.mustQuote ) {
646
+ this.failed = true;
647
+ }
648
+ return this;
649
+ }
650
+ normalizeArg(s, char = '') {
651
+ if ( char === '' ) { char = this.actualSeparatorChar; }
652
+ let out = '';
653
+ let pos = 0;
654
+ while ( (pos = s.lastIndexOf(char)) !== -1 ) {
655
+ out = s.slice(pos) + out;
656
+ s = s.slice(0, pos);
657
+ const match = this.reTrailingEscapeChars.exec(s);
658
+ if ( match === null ) { continue; }
659
+ const tail = (match[0].length & 1) !== 0
660
+ ? match[0].slice(0, -1)
661
+ : match[0];
662
+ out = tail + out;
663
+ s = s.slice(0, -match[0].length);
664
+ }
665
+ if ( out === '' ) { return s; }
666
+ return s + out;
667
+ }
668
+ leftWhitespaceCount(s) {
669
+ const match = this.reWhitespaceStart.exec(s);
670
+ return match === null ? 0 : match[0].length;
671
+ }
672
+ rightWhitespaceCount(s) {
673
+ const match = this.reWhitespaceEnd.exec(s);
674
+ return match === null ? 0 : match[0].length;
675
+ }
676
+ indexOfNextArgSeparator(pattern, separatorCode) {
677
+ this.argBeg = this.argEnd = separatorCode !== this.separatorCode
678
+ ? this.quoteBeg + 1
679
+ : this.quoteBeg;
680
+ this.transform = false;
681
+ if ( separatorCode !== this.actualSeparatorCode ) {
682
+ this.actualSeparatorCode = separatorCode;
683
+ this.actualSeparatorChar = String.fromCharCode(separatorCode);
684
+ }
685
+ while ( this.argEnd < pattern.length ) {
686
+ const pos = pattern.indexOf(this.actualSeparatorChar, this.argEnd);
687
+ if ( pos === -1 ) {
688
+ return (this.argEnd = pattern.length);
689
+ }
690
+ if ( this.reOddTrailingEscape.test(pattern.slice(0, pos)) === false ) {
691
+ return (this.argEnd = pos);
692
+ }
693
+ this.transform = true;
694
+ this.argEnd = pos + 1;
695
+ }
696
+ }
697
+ }
698
+
699
+ /******************************************************************************/
700
+
701
+ class AstWalker {
702
+ constructor(parser, from = 0) {
703
+ this.parser = parser;
704
+ this.stack = [];
705
+ this.reset(from);
706
+ }
707
+ get depth() {
708
+ return this.stackPtr;
709
+ }
710
+ reset(from = 0) {
711
+ this.nodes = this.parser.nodes;
712
+ this.stackPtr = 0;
713
+ return (this.current = from || this.parser.rootNode);
714
+ }
715
+ next() {
716
+ const current = this.current;
717
+ if ( current === 0 ) { return 0; }
718
+ const down = this.nodes[current+NODE_DOWN_INDEX];
719
+ if ( down !== 0 ) {
720
+ this.stack[this.stackPtr++] = this.current;
721
+ return (this.current = down);
722
+ }
723
+ const right = this.nodes[current+NODE_RIGHT_INDEX];
724
+ if ( right !== 0 && this.stackPtr !== 0 ) {
725
+ return (this.current = right);
726
+ }
727
+ while ( this.stackPtr !== 0 ) {
728
+ const parent = this.stack[--this.stackPtr];
729
+ const right = this.nodes[parent+NODE_RIGHT_INDEX];
730
+ if ( right !== 0 ) {
731
+ return (this.current = right);
732
+ }
733
+ }
734
+ return (this.current = 0);
735
+ }
736
+ right() {
737
+ const current = this.current;
738
+ if ( current === 0 ) { return 0; }
739
+ const right = this.nodes[current+NODE_RIGHT_INDEX];
740
+ if ( right !== 0 && this.stackPtr !== 0 ) {
741
+ return (this.current = right);
742
+ }
743
+ while ( this.stackPtr !== 0 ) {
744
+ const parent = this.stack[--this.stackPtr];
745
+ const right = this.nodes[parent+NODE_RIGHT_INDEX];
746
+ if ( right !== 0 ) {
747
+ return (this.current = right);
748
+ }
749
+ }
750
+ return (this.current = 0);
751
+ }
752
+ until(which) {
753
+ let node = this.next();
754
+ while ( node !== 0 ) {
755
+ if ( this.nodes[node+NODE_TYPE_INDEX] === which ) { return node; }
756
+ node = this.next();
757
+ }
758
+ return 0;
759
+ }
760
+ canGoDown() {
761
+ return this.nodes[this.current+NODE_DOWN_INDEX] !== 0;
762
+ }
763
+ dispose() {
764
+ this.parser.walkerJunkyard.push(this);
765
+ }
766
+ }
767
+
768
+ /******************************************************************************/
769
+
770
+ class DomainListIterator {
771
+ constructor(parser, root) {
772
+ this.parser = parser;
773
+ this.walker = parser.getWalker();
774
+ this.value = undefined;
775
+ this.item = { hn: '', not: false, bad: false };
776
+ this.reuse(root);
777
+ }
778
+ next() {
779
+ if ( this.done ) { return this.value; }
780
+ let node = this.walker.current;
781
+ let ready = false;
782
+ while ( node !== 0 ) {
783
+ switch ( this.parser.getNodeType(node) ) {
784
+ case NODE_TYPE_OPTION_VALUE_DOMAIN_RAW:
785
+ this.item.hn = '';
786
+ this.item.not = false;
787
+ this.item.bad = this.parser.getNodeFlags(node, NODE_FLAG_ERROR) !== 0;
788
+ break;
789
+ case NODE_TYPE_OPTION_VALUE_NOT:
790
+ this.item.not = true;
791
+ break;
792
+ case NODE_TYPE_OPTION_VALUE_DOMAIN:
793
+ this.item.hn = this.parser.getNodeTransform(node);
794
+ this.value = this.item;
795
+ ready = true;
796
+ break;
797
+ default:
798
+ break;
799
+ }
800
+ node = this.walker.next();
801
+ if ( ready ) { return this; }
802
+ }
803
+ return this.stop();
804
+ }
805
+ reuse(root) {
806
+ this.walker.reset(root);
807
+ this.done = false;
808
+ return this;
809
+ }
810
+ stop() {
811
+ this.done = true;
812
+ this.value = undefined;
813
+ this.parser.domainListIteratorJunkyard.push(this);
814
+ return this;
815
+ }
816
+ [Symbol.iterator]() {
817
+ return this;
818
+ }
819
+ }
820
+
821
+ /******************************************************************************/
822
+
823
+ export class AstFilterParser {
824
+ constructor(options = {}) {
825
+ this.raw = '';
826
+ this.rawEnd = 0;
827
+ this.nodes = new Uint32Array(16384);
828
+ this.nodePoolPtr = FULL_NODE_SIZE;
829
+ this.nodePoolEnd = this.nodes.length;
830
+ this.astTransforms = [ null ];
831
+ this.astTransformPtr = 1;
832
+ this.rootNode = 0;
833
+ this.astType = AST_TYPE_NONE;
834
+ this.astTypeFlavor = AST_TYPE_NONE;
835
+ this.astFlags = 0;
836
+ this.astError = 0;
837
+ this.nodeTypeRegister = [];
838
+ this.nodeTypeRegisterPtr = 0;
839
+ this.nodeTypeLookupTable = new Uint32Array(NODE_TYPE_COUNT);
840
+ this.punycoder = new URL('https://ublock0.invalid/');
841
+ this.domainListIteratorJunkyard = [];
842
+ this.walkerJunkyard = [];
843
+ this.hasWhitespace = false;
844
+ this.hasUnicode = false;
845
+ this.hasUppercase = false;
846
+ // Options
847
+ this.options = options;
848
+ this.interactive = options.interactive || false;
849
+ this.badTypes = new Set(options.badTypes || []);
850
+ this.maxTokenLength = options.maxTokenLength || 7;
851
+ // TODO: rethink this
852
+ this.result = { exception: false, raw: '', compiled: '', error: undefined };
853
+ this.selectorCompiler = new ExtSelectorCompiler(options);
854
+ // Regexes
855
+ this.reWhitespaceStart = /^\s+/;
856
+ this.reWhitespaceEnd = /\s+$/;
857
+ this.reCommentLine = /^(?:!|#\s|####|\[adblock)/i;
858
+ this.reExtAnchor = /(#@?(?:\$\?|\$|%|\?)?#).{1,2}/;
859
+ this.reInlineComment = /(?:\s+#).*?$/;
860
+ this.reNetException = /^@@/;
861
+ this.reNetAnchor = /(?:)\$[^,\w~]/;
862
+ this.reHnAnchoredPlainAscii = /^\|\|[0-9a-z%&,\-.\/:;=?_]+$/;
863
+ this.reHnAnchoredHostnameAscii = /^\|\|(?:[\da-z][\da-z_-]*\.)*[\da-z_-]*[\da-z]\^$/;
864
+ this.reHnAnchoredHostnameUnicode = /^\|\|(?:[\p{L}\p{N}][\p{L}\p{N}\u{2d}]*\.)*[\p{L}\p{N}\u{2d}]*[\p{L}\p{N}]\^$/u;
865
+ this.reHn3pAnchoredHostnameAscii = /^\|\|(?:[\da-z][\da-z_-]*\.)*[\da-z_-]*[\da-z]\^\$third-party$/;
866
+ this.rePlainAscii = /^[0-9a-z%&\-.\/:;=?_]{2,}$/;
867
+ this.reNetHosts1 = /^127\.0\.0\.1 (?:[\da-z][\da-z_-]*\.)+[\da-z-]*[a-z]$/;
868
+ this.reNetHosts2 = /^0\.0\.0\.0 (?:[\da-z][\da-z_-]*\.)+[\da-z-]*[a-z]$/;
869
+ this.rePlainGenericCosmetic = /^##[.#][A-Za-z_][\w-]*$/;
870
+ this.reHostnameAscii = /^(?:[\da-z][\da-z_-]*\.)*[\da-z][\da-z-]*[\da-z]$/;
871
+ this.rePlainEntity = /^(?:[\da-z][\da-z_-]*\.)+\*$/;
872
+ this.reHostsSink = /^[\w%.:\[\]-]+\s+/;
873
+ this.reHostsRedirect = /(?:0\.0\.0\.0|broadcasthost|local|localhost(?:\.localdomain)?|ip6-\w+)(?:[^\w.-]|$)/;
874
+ this.reNetOptionComma = /,(?:~?[13a-z-]+(?:=.*?)?|_+)(?:,|$)/;
875
+ this.rePointlessLeftAnchor = /^\|\|?\*+/;
876
+ this.reIsTokenChar = /^[%0-9A-Za-z]/;
877
+ this.rePointlessLeadingWildcards = /^(\*+)[^%0-9A-Za-z\u{a0}-\u{10FFFF}]/u;
878
+ this.rePointlessTrailingSeparator = /\*(\^\**)$/;
879
+ this.rePointlessTrailingWildcards = /(?:[^%0-9A-Za-z]|[%0-9A-Za-z]{7,})(\*+)$/;
880
+ this.reHasWhitespaceChar = /\s/;
881
+ this.reHasUppercaseChar = /[A-Z]/;
882
+ this.reHasUnicodeChar = /[^\x00-\x7F]/;
883
+ this.reUnicodeChars = /\P{ASCII}/gu;
884
+ this.reBadHostnameChars = /[\x00-\x24\x26-\x29\x2b\x2c\x2f\x3b-\x40\x5c\x5e\x60\x7b-\x7f]/;
885
+ this.reIsEntity = /^[^*]+\.\*$/;
886
+ this.rePreparseDirectiveIf = /^!#if /;
887
+ this.rePreparseDirectiveAny = /^!#(?:else|endif|if |include )/;
888
+ this.reURL = /\bhttps?:\/\/\S+/;
889
+ this.reHasPatternSpecialChars = /[\*\^]/;
890
+ this.rePatternAllSpecialChars = /[\*\^]+|[^\x00-\x7f]+/g;
891
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/1146
892
+ // From https://codemirror.net/doc/manual.html#option_specialChars
893
+ this.reHasInvalidChar = /[\x00-\x1F\x7F-\x9F\xAD\u061C\u200B-\u200F\u2028\u2029\uFEFF\uFFF9-\uFFFC]/;
894
+ this.reHostnamePatternPart = /^[^\x00-\x24\x26-\x29\x2B\x2C\x2F\x3A-\x40\x5B-\x5E\x60\x7B-\x7F]+/;
895
+ this.reHostnameLabel = /[^.]+/g;
896
+ this.reResponseheaderPattern = /^\^responseheader\(.*\)$/;
897
+ this.rePatternScriptletJsonArgs = /^\{.*\}$/;
898
+ this.reGoodRegexToken = /[^\x01%0-9A-Za-z][%0-9A-Za-z]{7,}|[^\x01%0-9A-Za-z][%0-9A-Za-z]{1,6}[^\x01%0-9A-Za-z]/;
899
+ this.reBadCSP = /(?:=|;)\s*report-(?:to|uri)\b/;
900
+ this.reNoopOption = /^_+$/;
901
+ this.scriptletArgListParser = new ArgListParser(',');
902
+ }
903
+
904
+ finish() {
905
+ this.selectorCompiler.finish();
906
+ }
907
+
908
+ parse(raw) {
909
+ this.raw = raw;
910
+ this.rawEnd = raw.length;
911
+ this.nodePoolPtr = FULL_NODE_SIZE;
912
+ this.nodeTypeRegisterPtr = 0;
913
+ this.astTransformPtr = 1;
914
+ this.astType = AST_TYPE_NONE;
915
+ this.astTypeFlavor = AST_TYPE_NONE;
916
+ this.astFlags = 0;
917
+ this.astError = 0;
918
+ this.rootNode = this.allocTypedNode(NODE_TYPE_LINE_RAW, 0, this.rawEnd);
919
+ if ( this.rawEnd === 0 ) { return; }
920
+
921
+ // Fast-track very common simple filters using pre-computed AST layouts
922
+ // to skip parsing and validation.
923
+ const c1st = this.raw.charCodeAt(0);
924
+ const clast = exCharCodeAt(this.raw, -1);
925
+ if ( c1st === 0x7C /* | */ ) {
926
+ if (
927
+ clast === 0x5E /* ^ */ &&
928
+ this.reHnAnchoredHostnameAscii.test(this.raw)
929
+ ) {
930
+ // ||example.com^
931
+ this.astType = AST_TYPE_NETWORK;
932
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
933
+ const node = this.astFromTemplate(this.rootNode,
934
+ astTemplates.netHnAnchoredHostnameAscii
935
+ );
936
+ this.linkDown(this.rootNode, node);
937
+ return;
938
+ }
939
+ if (
940
+ this.raw.endsWith('$third-party') &&
941
+ this.reHn3pAnchoredHostnameAscii.test(this.raw)
942
+ ) {
943
+ // ||example.com^$third-party
944
+ this.astType = AST_TYPE_NETWORK;
945
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
946
+ const node = this.astFromTemplate(this.rootNode,
947
+ astTemplates.net3pHnAnchoredHostnameAscii
948
+ );
949
+ this.linkDown(this.rootNode, node);
950
+ return;
951
+ }
952
+ if ( this.reHnAnchoredPlainAscii.test(this.raw) ) {
953
+ // ||example.com/path/to/resource
954
+ this.astType = AST_TYPE_NETWORK;
955
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_PLAIN;
956
+ const node = this.astFromTemplate(this.rootNode,
957
+ astTemplates.netHnAnchoredPlainAscii
958
+ );
959
+ this.linkDown(this.rootNode, node);
960
+ return;
961
+ }
962
+ } else if ( c1st === 0x23 /* # */ ) {
963
+ if ( this.rePlainGenericCosmetic.test(this.raw) ) {
964
+ // ##.ads-container
965
+ this.astType = AST_TYPE_EXTENDED;
966
+ this.astTypeFlavor = AST_TYPE_EXTENDED_COSMETIC;
967
+ const node = this.astFromTemplate(this.rootNode,
968
+ astTemplates.extPlainGenericSelector
969
+ );
970
+ this.linkDown(this.rootNode, node);
971
+ this.result.exception = false;
972
+ this.result.raw = this.raw.slice(2);
973
+ this.result.compiled = this.raw.slice(2);
974
+ return;
975
+ }
976
+ } else if ( c1st === 0x31 /* 1 */ ) {
977
+ if ( this.reNetHosts1.test(this.raw) ) {
978
+ // 127.0.0.1 example.com
979
+ this.astType = AST_TYPE_NETWORK;
980
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
981
+ const node = this.astFromTemplate(this.rootNode,
982
+ astTemplates.netHosts1
983
+ );
984
+ this.linkDown(this.rootNode, node);
985
+ return;
986
+ }
987
+ } else if ( c1st === 0x30 /* 0 */ ) {
988
+ if ( this.reNetHosts2.test(this.raw) ) {
989
+ // 0.0.0.0 example.com
990
+ this.astType = AST_TYPE_NETWORK;
991
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
992
+ const node = this.astFromTemplate(this.rootNode,
993
+ astTemplates.netHosts2
994
+ );
995
+ this.linkDown(this.rootNode, node);
996
+ return;
997
+ }
998
+ } else if (
999
+ (c1st !== 0x2F /* / */ || clast !== 0x2F /* / */) &&
1000
+ (this.rePlainAscii.test(this.raw))
1001
+ ) {
1002
+ // example.com
1003
+ // -resource.
1004
+ this.astType = AST_TYPE_NETWORK;
1005
+ this.astTypeFlavor = this.reHostnameAscii.test(this.raw)
1006
+ ? AST_TYPE_NETWORK_PATTERN_HOSTNAME
1007
+ : AST_TYPE_NETWORK_PATTERN_PLAIN;
1008
+ const node = this.astFromTemplate(this.rootNode,
1009
+ astTemplates.netPlainAscii
1010
+ );
1011
+ this.linkDown(this.rootNode, node);
1012
+ return;
1013
+ }
1014
+
1015
+ // All else: full parsing and validation.
1016
+ this.hasWhitespace = this.reHasWhitespaceChar.test(raw);
1017
+ this.linkDown(this.rootNode, this.parseRaw(this.rootNode));
1018
+ }
1019
+
1020
+ astFromTemplate(parent, template) {
1021
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1022
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1023
+ const beg = template.beg + (template.beg >= 0 ? parentBeg : parentEnd);
1024
+ const end = template.end + (template.end <= 0 ? parentEnd : parentBeg);
1025
+ const node = this.allocTypedNode(template.type, beg, end);
1026
+ if ( template.register ) {
1027
+ this.addNodeToRegister(template.type, node);
1028
+ }
1029
+ if ( template.flags ) {
1030
+ this.addFlags(template.flags);
1031
+ }
1032
+ if ( template.nodeFlags ) {
1033
+ this.addNodeFlags(node, template.nodeFlags);
1034
+ }
1035
+ const children = template.children;
1036
+ if ( children === undefined ) { return node; }
1037
+ const head = this.astFromTemplate(node, children[0]);
1038
+ this.linkDown(node, head);
1039
+ const n = children.length;
1040
+ if ( n === 1 ) { return node; }
1041
+ let prev = head;
1042
+ for ( let i = 1; i < n; i++ ) {
1043
+ prev = this.linkRight(prev, this.astFromTemplate(node, children[i]));
1044
+ }
1045
+ return node;
1046
+ }
1047
+
1048
+ getType() {
1049
+ return this.astType;
1050
+ }
1051
+
1052
+ isComment() {
1053
+ return this.astType === AST_TYPE_COMMENT;
1054
+ }
1055
+
1056
+ isFilter() {
1057
+ return this.isNetworkFilter() || this.isExtendedFilter();
1058
+ }
1059
+
1060
+ isNetworkFilter() {
1061
+ return this.astType === AST_TYPE_NETWORK;
1062
+ }
1063
+
1064
+ isExtendedFilter() {
1065
+ return this.astType === AST_TYPE_EXTENDED;
1066
+ }
1067
+
1068
+ isCosmeticFilter() {
1069
+ return this.astType === AST_TYPE_EXTENDED &&
1070
+ this.astTypeFlavor === AST_TYPE_EXTENDED_COSMETIC;
1071
+ }
1072
+
1073
+ isScriptletFilter() {
1074
+ return this.astType === AST_TYPE_EXTENDED &&
1075
+ this.astTypeFlavor === AST_TYPE_EXTENDED_SCRIPTLET;
1076
+ }
1077
+
1078
+ isHtmlFilter() {
1079
+ return this.astType === AST_TYPE_EXTENDED &&
1080
+ this.astTypeFlavor === AST_TYPE_EXTENDED_HTML;
1081
+ }
1082
+
1083
+ isResponseheaderFilter() {
1084
+ return this.astType === AST_TYPE_EXTENDED &&
1085
+ this.astTypeFlavor === AST_TYPE_EXTENDED_RESPONSEHEADER;
1086
+ }
1087
+
1088
+ getFlags(flags = 0xFFFFFFFF) {
1089
+ return this.astFlags & flags;
1090
+ }
1091
+
1092
+ addFlags(flags) {
1093
+ this.astFlags |= flags;
1094
+ }
1095
+
1096
+ parseRaw(parent) {
1097
+ const head = this.allocHeadNode();
1098
+ let prev = head, next = 0;
1099
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1100
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1101
+ const l1 = this.hasWhitespace
1102
+ ? this.leftWhitespaceCount(this.getNodeString(parent))
1103
+ : 0;
1104
+ if ( l1 !== 0 ) {
1105
+ next = this.allocTypedNode(
1106
+ NODE_TYPE_WHITESPACE,
1107
+ parentBeg,
1108
+ parentBeg + l1
1109
+ );
1110
+ prev = this.linkRight(prev, next);
1111
+ if ( l1 === parentEnd ) { return this.throwHeadNode(head); }
1112
+ }
1113
+ const r0 = this.hasWhitespace
1114
+ ? parentEnd - this.rightWhitespaceCount(this.getNodeString(parent))
1115
+ : parentEnd;
1116
+ if ( r0 !== l1 ) {
1117
+ next = this.allocTypedNode(
1118
+ NODE_TYPE_LINE_BODY,
1119
+ parentBeg + l1,
1120
+ parentBeg + r0
1121
+ );
1122
+ this.linkDown(next, this.parseFilter(next));
1123
+ prev = this.linkRight(prev, next);
1124
+ }
1125
+ if ( r0 !== parentEnd ) {
1126
+ next = this.allocTypedNode(
1127
+ NODE_TYPE_WHITESPACE,
1128
+ parentBeg + r0,
1129
+ parentEnd
1130
+ );
1131
+ this.linkRight(prev, next);
1132
+ }
1133
+ return this.throwHeadNode(head);
1134
+ }
1135
+
1136
+ parseFilter(parent) {
1137
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1138
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1139
+ const parentStr = this.getNodeString(parent);
1140
+
1141
+ // A comment?
1142
+ if ( this.reCommentLine.test(parentStr) ) {
1143
+ const head = this.allocTypedNode(NODE_TYPE_COMMENT, parentBeg, parentEnd);
1144
+ this.astType = AST_TYPE_COMMENT;
1145
+ if ( this.interactive ) {
1146
+ this.linkDown(head, this.parseComment(head));
1147
+ }
1148
+ return head;
1149
+ }
1150
+
1151
+ // An extended filter? (or rarely, a comment)
1152
+ if ( this.reExtAnchor.test(parentStr) ) {
1153
+ const match = this.reExtAnchor.exec(parentStr);
1154
+ const matchLen = match[1].length;
1155
+ const head = this.allocTypedNode(NODE_TYPE_EXT_RAW, parentBeg, parentEnd);
1156
+ this.linkDown(head, this.parseExt(head, parentBeg + match.index, matchLen));
1157
+ return head;
1158
+ } else if ( parentStr.charCodeAt(0) === 0x23 /* # */ ) {
1159
+ const head = this.allocTypedNode(NODE_TYPE_COMMENT, parentBeg, parentEnd);
1160
+ this.astType = AST_TYPE_COMMENT;
1161
+ return head;
1162
+ }
1163
+
1164
+ // Good to know in advance to avoid costly tests later on
1165
+ this.hasUppercase = this.reHasUppercaseChar.test(parentStr);
1166
+ this.hasUnicode = this.reHasUnicodeChar.test(parentStr);
1167
+
1168
+ // A network filter (probably)
1169
+ this.astType = AST_TYPE_NETWORK;
1170
+
1171
+ // Parse inline comment if any
1172
+ let tail = 0, tailStart = parentEnd;
1173
+ if ( this.hasWhitespace && this.reInlineComment.test(parentStr) ) {
1174
+ const match = this.reInlineComment.exec(parentStr);
1175
+ tailStart = parentBeg + match.index;
1176
+ tail = this.allocTypedNode(NODE_TYPE_COMMENT, tailStart, parentEnd);
1177
+ }
1178
+
1179
+ const head = this.allocTypedNode(NODE_TYPE_NET_RAW, parentBeg, tailStart);
1180
+ if ( this.linkDown(head, this.parseNet(head)) === 0 ) {
1181
+ this.astType = AST_TYPE_UNKNOWN;
1182
+ this.addFlags(AST_FLAG_UNSUPPORTED | AST_FLAG_HAS_ERROR);
1183
+ }
1184
+ if ( tail !== 0 ) {
1185
+ this.linkRight(head, tail);
1186
+ }
1187
+ return head;
1188
+ }
1189
+
1190
+ parseComment(parent) {
1191
+ const parentStr = this.getNodeString(parent);
1192
+ if ( this.rePreparseDirectiveAny.test(parentStr) ) {
1193
+ this.astTypeFlavor = AST_TYPE_COMMENT_PREPARSER;
1194
+ return this.parsePreparseDirective(parent, parentStr);
1195
+ }
1196
+ if ( this.reURL.test(parentStr) === false ) { return 0; }
1197
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1198
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1199
+ const match = this.reURL.exec(parentStr);
1200
+ const urlBeg = parentBeg + match.index;
1201
+ const urlEnd = urlBeg + match[0].length;
1202
+ const head = this.allocTypedNode(NODE_TYPE_COMMENT, parentBeg, urlBeg);
1203
+ let next = this.allocTypedNode(NODE_TYPE_COMMENT_URL, urlBeg, urlEnd);
1204
+ let prev = this.linkRight(head, next);
1205
+ if ( urlEnd !== parentEnd ) {
1206
+ next = this.allocTypedNode(NODE_TYPE_COMMENT, urlEnd, parentEnd);
1207
+ this.linkRight(prev, next);
1208
+ }
1209
+ return head;
1210
+ }
1211
+
1212
+ parsePreparseDirective(parent, s) {
1213
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1214
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1215
+ const match = this.rePreparseDirectiveAny.exec(s);
1216
+ const directiveEnd = parentBeg + match[0].length;
1217
+ const head = this.allocTypedNode(
1218
+ NODE_TYPE_PREPARSE_DIRECTIVE,
1219
+ parentBeg,
1220
+ directiveEnd
1221
+ );
1222
+ if ( directiveEnd !== parentEnd ) {
1223
+ const type = s.startsWith('!#if ')
1224
+ ? NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE
1225
+ : NODE_TYPE_PREPARSE_DIRECTIVE_VALUE;
1226
+ const next = this.allocTypedNode(type, directiveEnd, parentEnd);
1227
+ this.linkRight(head, next);
1228
+ if ( type === NODE_TYPE_PREPARSE_DIRECTIVE_IF_VALUE ) {
1229
+ const rawToken = this.getNodeString(next).trim();
1230
+ if ( utils.preparser.evaluateExpr(rawToken) === undefined ) {
1231
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
1232
+ this.addFlags(AST_FLAG_HAS_ERROR);
1233
+ this.astError = AST_ERROR_IF_TOKEN_UNKNOWN;
1234
+ }
1235
+ }
1236
+ }
1237
+ return head;
1238
+ }
1239
+
1240
+ // Very common, look into fast-tracking such plain pattern:
1241
+ // /^[^!#\$\*\^][^#\$\*\^]*[^\$\*\|]$/
1242
+ parseNet(parent) {
1243
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1244
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1245
+ const parentStr = this.getNodeString(parent);
1246
+ const head = this.allocHeadNode();
1247
+ let patternBeg = parentBeg;
1248
+ let prev = head, next = 0, tail = 0;
1249
+ if ( this.reNetException.test(parentStr) ) {
1250
+ this.addFlags(AST_FLAG_IS_EXCEPTION);
1251
+ next = this.allocTypedNode(NODE_TYPE_NET_EXCEPTION, parentBeg, parentBeg+2);
1252
+ prev = this.linkRight(prev, next);
1253
+ patternBeg += 2;
1254
+ }
1255
+ let anchorBeg = this.indexOfNetAnchor(parentStr, patternBeg);
1256
+ if ( anchorBeg === -1 ) { return 0; }
1257
+ anchorBeg += parentBeg;
1258
+ if ( anchorBeg !== parentEnd ) {
1259
+ tail = this.allocTypedNode(
1260
+ NODE_TYPE_NET_OPTIONS_ANCHOR,
1261
+ anchorBeg,
1262
+ anchorBeg + 1
1263
+ );
1264
+ next = this.allocTypedNode(
1265
+ NODE_TYPE_NET_OPTIONS,
1266
+ anchorBeg + 1,
1267
+ parentEnd
1268
+ );
1269
+ this.addFlags(AST_FLAG_HAS_OPTIONS);
1270
+ this.addNodeToRegister(NODE_TYPE_NET_OPTIONS, next);
1271
+ this.linkDown(next, this.parseNetOptions(next));
1272
+ this.linkRight(tail, next);
1273
+ }
1274
+ next = this.allocTypedNode(
1275
+ NODE_TYPE_NET_PATTERN_RAW,
1276
+ patternBeg,
1277
+ anchorBeg
1278
+ );
1279
+ this.addNodeToRegister(NODE_TYPE_NET_PATTERN_RAW, next);
1280
+ this.linkDown(next, this.parseNetPattern(next));
1281
+ prev = this.linkRight(prev, next);
1282
+ if ( tail !== 0 ) {
1283
+ this.linkRight(prev, tail);
1284
+ }
1285
+ if ( this.astType === AST_TYPE_NETWORK ) {
1286
+ this.validateNet();
1287
+ }
1288
+ return this.throwHeadNode(head);
1289
+ }
1290
+
1291
+ validateNet() {
1292
+ const isException = this.isException();
1293
+ let bad = false, realBad = false;
1294
+ let abstractTypeCount = 0;
1295
+ let behaviorTypeCount = 0;
1296
+ let docTypeCount = 0;
1297
+ let modifierType = 0;
1298
+ let requestTypeCount = 0;
1299
+ let unredirectableTypeCount = 0;
1300
+ for ( let i = 0, n = this.nodeTypeRegisterPtr; i < n; i++ ) {
1301
+ const type = this.nodeTypeRegister[i];
1302
+ const targetNode = this.nodeTypeLookupTable[type];
1303
+ if ( targetNode === 0 ) { continue; }
1304
+ if ( this.badTypes.has(type) ) {
1305
+ this.addNodeFlags(NODE_FLAG_ERROR);
1306
+ this.addFlags(AST_FLAG_HAS_ERROR);
1307
+ this.astError = AST_ERROR_OPTION_EXCLUDED;
1308
+ }
1309
+ const flags = this.getNodeFlags(targetNode);
1310
+ if ( (flags & NODE_FLAG_ERROR) !== 0 ) { continue; }
1311
+ const isNegated = (flags & NODE_FLAG_IS_NEGATED) !== 0;
1312
+ const hasValue = (flags & NODE_FLAG_OPTION_HAS_VALUE) !== 0;
1313
+ bad = false; realBad = false;
1314
+ switch ( type ) {
1315
+ case NODE_TYPE_NET_OPTION_NAME_ALL:
1316
+ realBad = isNegated || hasValue || modifierType !== 0;
1317
+ break;
1318
+ case NODE_TYPE_NET_OPTION_NAME_1P:
1319
+ case NODE_TYPE_NET_OPTION_NAME_3P:
1320
+ realBad = hasValue;
1321
+ break;
1322
+ case NODE_TYPE_NET_OPTION_NAME_BADFILTER:
1323
+ case NODE_TYPE_NET_OPTION_NAME_NOOP:
1324
+ realBad = isNegated || hasValue;
1325
+ break;
1326
+ case NODE_TYPE_NET_OPTION_NAME_CSS:
1327
+ case NODE_TYPE_NET_OPTION_NAME_FONT:
1328
+ case NODE_TYPE_NET_OPTION_NAME_IMAGE:
1329
+ case NODE_TYPE_NET_OPTION_NAME_MEDIA:
1330
+ case NODE_TYPE_NET_OPTION_NAME_OBJECT:
1331
+ case NODE_TYPE_NET_OPTION_NAME_OTHER:
1332
+ case NODE_TYPE_NET_OPTION_NAME_SCRIPT:
1333
+ case NODE_TYPE_NET_OPTION_NAME_XHR:
1334
+ realBad = hasValue;
1335
+ if ( realBad ) { break; }
1336
+ requestTypeCount += 1;
1337
+ break;
1338
+ case NODE_TYPE_NET_OPTION_NAME_CNAME:
1339
+ realBad = isException === false || isNegated || hasValue;
1340
+ if ( realBad ) { break; }
1341
+ modifierType = type;
1342
+ break;
1343
+ case NODE_TYPE_NET_OPTION_NAME_CSP:
1344
+ realBad = (hasValue || isException) === false ||
1345
+ modifierType !== 0 ||
1346
+ this.reBadCSP.test(
1347
+ this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_CSP)
1348
+ );
1349
+ if ( realBad ) { break; }
1350
+ modifierType = type;
1351
+ break;
1352
+ case NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
1353
+ realBad = isNegated || hasValue === false ||
1354
+ this.getBranchFromType(NODE_TYPE_NET_OPTION_NAME_FROM) === 0;
1355
+ break;
1356
+ case NODE_TYPE_NET_OPTION_NAME_DOC:
1357
+ case NODE_TYPE_NET_OPTION_NAME_FRAME:
1358
+ realBad = hasValue;
1359
+ if ( realBad ) { break; }
1360
+ docTypeCount += 1;
1361
+ break;
1362
+ case NODE_TYPE_NET_OPTION_NAME_EHIDE:
1363
+ case NODE_TYPE_NET_OPTION_NAME_GHIDE:
1364
+ case NODE_TYPE_NET_OPTION_NAME_SHIDE:
1365
+ realBad = isNegated || hasValue || modifierType !== 0;
1366
+ if ( realBad ) { break; }
1367
+ behaviorTypeCount += 1;
1368
+ unredirectableTypeCount += 1;
1369
+ break;
1370
+ case NODE_TYPE_NET_OPTION_NAME_EMPTY:
1371
+ case NODE_TYPE_NET_OPTION_NAME_MP4:
1372
+ realBad = isNegated || hasValue || modifierType !== 0;
1373
+ if ( realBad ) { break; }
1374
+ modifierType = type;
1375
+ break;
1376
+ case NODE_TYPE_NET_OPTION_NAME_FROM:
1377
+ case NODE_TYPE_NET_OPTION_NAME_METHOD:
1378
+ case NODE_TYPE_NET_OPTION_NAME_TO:
1379
+ realBad = isNegated || hasValue === false;
1380
+ break;
1381
+ case NODE_TYPE_NET_OPTION_NAME_GENERICBLOCK:
1382
+ bad = true;
1383
+ realBad = isException === false || isNegated || hasValue;
1384
+ break;
1385
+ case NODE_TYPE_NET_OPTION_NAME_HEADER:
1386
+ realBad = isNegated || hasValue === false;
1387
+ break;
1388
+ case NODE_TYPE_NET_OPTION_NAME_IMPORTANT:
1389
+ realBad = isException || isNegated || hasValue;
1390
+ break;
1391
+ case NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
1392
+ case NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT:
1393
+ realBad = hasValue;
1394
+ if ( realBad ) { break; }
1395
+ modifierType = type;
1396
+ unredirectableTypeCount += 1;
1397
+ break;
1398
+ case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
1399
+ realBad = this.isRegexPattern() === false;
1400
+ break;
1401
+ case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
1402
+ realBad = modifierType !== 0 || (hasValue || isException) === false;
1403
+ if ( realBad ) { break; }
1404
+ modifierType = type;
1405
+ break;
1406
+ case NODE_TYPE_NET_OPTION_NAME_PING:
1407
+ case NODE_TYPE_NET_OPTION_NAME_WEBSOCKET:
1408
+ realBad = hasValue;
1409
+ if ( realBad ) { break; }
1410
+ requestTypeCount += 1;
1411
+ unredirectableTypeCount += 1;
1412
+ break;
1413
+ case NODE_TYPE_NET_OPTION_NAME_POPUNDER:
1414
+ case NODE_TYPE_NET_OPTION_NAME_POPUP:
1415
+ realBad = hasValue;
1416
+ if ( realBad ) { break; }
1417
+ abstractTypeCount += 1;
1418
+ unredirectableTypeCount += 1;
1419
+ break;
1420
+ case NODE_TYPE_NET_OPTION_NAME_REDIRECT:
1421
+ case NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
1422
+ case NODE_TYPE_NET_OPTION_NAME_REPLACE:
1423
+ case NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
1424
+ realBad = isNegated || (isException || hasValue) === false ||
1425
+ modifierType !== 0;
1426
+ if ( realBad ) { break; }
1427
+ modifierType = type;
1428
+ break;
1429
+ case NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
1430
+ realBad = isNegated || modifierType !== 0;
1431
+ if ( realBad ) { break; }
1432
+ modifierType = type;
1433
+ break;
1434
+ case NODE_TYPE_NET_OPTION_NAME_STRICT1P:
1435
+ case NODE_TYPE_NET_OPTION_NAME_STRICT3P:
1436
+ realBad = isNegated || hasValue;
1437
+ break;
1438
+ case NODE_TYPE_NET_OPTION_NAME_UNKNOWN:
1439
+ this.astError = AST_ERROR_OPTION_UNKNOWN;
1440
+ realBad = true;
1441
+ break;
1442
+ case NODE_TYPE_NET_OPTION_NAME_WEBRTC:
1443
+ realBad = true;
1444
+ break;
1445
+ case NODE_TYPE_NET_PATTERN_RAW:
1446
+ realBad = this.hasOptions() === false &&
1447
+ this.getNetPattern().length <= 1;
1448
+ break;
1449
+ default:
1450
+ break;
1451
+ }
1452
+ if ( bad || realBad ) {
1453
+ this.addNodeFlags(targetNode, NODE_FLAG_ERROR);
1454
+ }
1455
+ if ( realBad ) {
1456
+ this.addFlags(AST_FLAG_HAS_ERROR);
1457
+ }
1458
+ }
1459
+ switch ( modifierType ) {
1460
+ case NODE_TYPE_NET_OPTION_NAME_CNAME:
1461
+ realBad = abstractTypeCount || behaviorTypeCount || requestTypeCount;
1462
+ break;
1463
+ case NODE_TYPE_NET_OPTION_NAME_CSP:
1464
+ case NODE_TYPE_NET_OPTION_NAME_PERMISSIONS:
1465
+ realBad = abstractTypeCount || behaviorTypeCount || requestTypeCount;
1466
+ break;
1467
+ case NODE_TYPE_NET_OPTION_NAME_INLINEFONT:
1468
+ case NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT:
1469
+ realBad = behaviorTypeCount;
1470
+ break;
1471
+ case NODE_TYPE_NET_OPTION_NAME_EMPTY:
1472
+ realBad = abstractTypeCount || behaviorTypeCount;
1473
+ break;
1474
+ case NODE_TYPE_NET_OPTION_NAME_MEDIA:
1475
+ case NODE_TYPE_NET_OPTION_NAME_MP4:
1476
+ realBad = abstractTypeCount || behaviorTypeCount || docTypeCount || requestTypeCount;
1477
+ break;
1478
+ case NODE_TYPE_NET_OPTION_NAME_REDIRECT:
1479
+ case NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE: {
1480
+ realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount;
1481
+ break;
1482
+ }
1483
+ case NODE_TYPE_NET_OPTION_NAME_REPLACE: {
1484
+ realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount;
1485
+ if ( realBad ) { break; }
1486
+ if ( isException !== true && this.options.trustedSource !== true ) {
1487
+ this.astError = AST_ERROR_UNTRUSTED_SOURCE;
1488
+ realBad = true;
1489
+ break;
1490
+ }
1491
+ const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_REPLACE);
1492
+ if ( parseReplaceValue(value) === undefined ) {
1493
+ this.astError = AST_ERROR_OPTION_BADVALUE;
1494
+ realBad = true;
1495
+ }
1496
+ break;
1497
+ }
1498
+ case NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
1499
+ realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount;
1500
+ if ( realBad ) { break; }
1501
+ if ( isException !== true && this.options.trustedSource !== true ) {
1502
+ this.astError = AST_ERROR_UNTRUSTED_SOURCE;
1503
+ realBad = true;
1504
+ break;
1505
+ }
1506
+ const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM);
1507
+ if ( parseReplaceValue(value) === undefined ) {
1508
+ this.astError = AST_ERROR_OPTION_BADVALUE;
1509
+ realBad = true;
1510
+ }
1511
+ break;
1512
+ case NODE_TYPE_NET_OPTION_NAME_REMOVEPARAM:
1513
+ realBad = abstractTypeCount || behaviorTypeCount;
1514
+ break;
1515
+ default:
1516
+ break;
1517
+ }
1518
+ if ( realBad ) {
1519
+ const targetNode = this.getBranchFromType(modifierType);
1520
+ this.addNodeFlags(targetNode, NODE_FLAG_ERROR);
1521
+ this.addFlags(AST_FLAG_HAS_ERROR);
1522
+ }
1523
+ }
1524
+
1525
+ indexOfNetAnchor(s, start = 0) {
1526
+ const end = s.length;
1527
+ if ( end === start ) { return end; }
1528
+ let j = s.lastIndexOf('$');
1529
+ if ( j === -1 ) { return end; }
1530
+ if ( (j+1) === end ) { return end; }
1531
+ for (;;) {
1532
+ const before = s.charCodeAt(j-1);
1533
+ if ( j !== start && before === 0x24 /* $ */ ) { return -1; }
1534
+ const after = s.charCodeAt(j+1);
1535
+ if (
1536
+ after !== 0x29 /* ) */ &&
1537
+ after !== 0x2F /* / */ &&
1538
+ after !== 0x7C /* | */ &&
1539
+ before !== 0x5C /* \ */
1540
+ ) {
1541
+ return j;
1542
+ }
1543
+ if ( j <= start ) { break; }
1544
+ j = s.lastIndexOf('$', j-1);
1545
+ if ( j === -1 ) { break; }
1546
+ }
1547
+ return end;
1548
+ }
1549
+
1550
+ parseNetPattern(parent) {
1551
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1552
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1553
+
1554
+ // Empty pattern
1555
+ if ( parentEnd === parentBeg ) {
1556
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_ANY;
1557
+ const node = this.allocTypedNode(
1558
+ NODE_TYPE_NET_PATTERN,
1559
+ parentBeg,
1560
+ parentEnd
1561
+ );
1562
+ this.addNodeToRegister(NODE_TYPE_NET_PATTERN, node);
1563
+ this.setNodeTransform(node, '*');
1564
+ return node;
1565
+ }
1566
+
1567
+ const head = this.allocHeadNode();
1568
+ let prev = head, next = 0, tail = 0;
1569
+ let pattern = this.getNodeString(parent);
1570
+ const hasWildcard = pattern.includes('*');
1571
+ const c1st = pattern.charCodeAt(0);
1572
+ const c2nd = pattern.charCodeAt(1) || 0;
1573
+ const clast = exCharCodeAt(pattern, -1);
1574
+
1575
+ // Common case: Easylist syntax-based hostname
1576
+ if (
1577
+ hasWildcard === false &&
1578
+ c1st === 0x7C /* | */ && c2nd === 0x7C /* | */ &&
1579
+ clast === 0x5E /* ^ */ &&
1580
+ this.isAdblockHostnamePattern(pattern)
1581
+ ) {
1582
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
1583
+ this.addFlags(
1584
+ AST_FLAG_NET_PATTERN_LEFT_HNANCHOR |
1585
+ AST_FLAG_NET_PATTERN_RIGHT_PATHANCHOR
1586
+ );
1587
+ next = this.allocTypedNode(
1588
+ NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR,
1589
+ parentBeg,
1590
+ parentBeg + 2
1591
+ );
1592
+ prev = this.linkRight(prev, next);
1593
+ next = this.allocTypedNode(
1594
+ NODE_TYPE_NET_PATTERN,
1595
+ parentBeg + 2,
1596
+ parentEnd - 1
1597
+ );
1598
+ pattern = pattern.slice(2, -1);
1599
+ const normal = this.hasUnicode
1600
+ ? this.normalizeHostnameValue(pattern)
1601
+ : pattern;
1602
+ if ( normal !== undefined && normal !== pattern ) {
1603
+ this.setNodeTransform(next, normal);
1604
+ }
1605
+ this.addNodeToRegister(NODE_TYPE_NET_PATTERN, next);
1606
+ prev = this.linkRight(prev, next);
1607
+ next = this.allocTypedNode(
1608
+ NODE_TYPE_NET_PATTERN_PART_SPECIAL,
1609
+ parentEnd - 1,
1610
+ parentEnd
1611
+ );
1612
+ this.linkRight(prev, next);
1613
+ return this.throwHeadNode(head);
1614
+ }
1615
+
1616
+ let patternBeg = parentBeg;
1617
+ let patternEnd = parentEnd;
1618
+
1619
+ // Hosts file entry?
1620
+ if (
1621
+ this.hasWhitespace &&
1622
+ this.isException() === false &&
1623
+ this.hasOptions() === false &&
1624
+ this.reHostsSink.test(pattern)
1625
+ ) {
1626
+ const match = this.reHostsSink.exec(pattern);
1627
+ patternBeg += match[0].length;
1628
+ pattern = pattern.slice(patternBeg);
1629
+ next = this.allocTypedNode(NODE_TYPE_IGNORE, parentBeg, patternBeg);
1630
+ prev = this.linkRight(prev, next);
1631
+ if (
1632
+ this.reHostsRedirect.test(pattern) ||
1633
+ this.reHostnameAscii.test(pattern) === false
1634
+ ) {
1635
+ this.astType = AST_TYPE_NONE;
1636
+ this.addFlags(AST_FLAG_IGNORE);
1637
+ next = this.allocTypedNode(NODE_TYPE_IGNORE, patternBeg, parentEnd);
1638
+ prev = this.linkRight(prev, next);
1639
+ return this.throwHeadNode(head);
1640
+ }
1641
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
1642
+ this.addFlags(
1643
+ AST_FLAG_NET_PATTERN_LEFT_HNANCHOR |
1644
+ AST_FLAG_NET_PATTERN_RIGHT_PATHANCHOR
1645
+ );
1646
+ next = this.allocTypedNode(
1647
+ NODE_TYPE_NET_PATTERN,
1648
+ patternBeg,
1649
+ parentEnd
1650
+ );
1651
+ this.addNodeToRegister(NODE_TYPE_NET_PATTERN, next);
1652
+ this.linkRight(prev, next);
1653
+ return this.throwHeadNode(head);
1654
+ }
1655
+
1656
+ // Regex?
1657
+ if (
1658
+ c1st === 0x2F /* / */ && clast === 0x2F /* / */ &&
1659
+ pattern.length > 2
1660
+ ) {
1661
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_REGEX;
1662
+ const normal = this.normalizeRegexPattern(pattern);
1663
+ next = this.allocTypedNode(
1664
+ NODE_TYPE_NET_PATTERN,
1665
+ patternBeg,
1666
+ patternEnd
1667
+ );
1668
+ this.addNodeToRegister(NODE_TYPE_NET_PATTERN, next);
1669
+ if ( normal !== '' ) {
1670
+ if ( normal !== pattern ) {
1671
+ this.setNodeTransform(next, normal);
1672
+ }
1673
+ if ( this.interactive ) {
1674
+ const tokenizable = utils.regex.toTokenizableStr(normal);
1675
+ if ( this.reGoodRegexToken.test(tokenizable) === false ) {
1676
+ this.addNodeFlags(next, NODE_FLAG_PATTERN_UNTOKENIZABLE);
1677
+ }
1678
+ }
1679
+ } else {
1680
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_BAD;
1681
+ this.astError = AST_ERROR_REGEX;
1682
+ this.addFlags(AST_FLAG_HAS_ERROR);
1683
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
1684
+ }
1685
+ this.linkRight(prev, next);
1686
+ return this.throwHeadNode(head);
1687
+ }
1688
+
1689
+ // Left anchor
1690
+ if ( c1st === 0x7C /* '|' */ ) {
1691
+ if ( c2nd === 0x7C /* '|' */ ) {
1692
+ const type = this.isTokenCharCode(pattern.charCodeAt(2) || 0)
1693
+ ? NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR
1694
+ : NODE_TYPE_IGNORE;
1695
+ next = this.allocTypedNode(type, patternBeg, patternBeg+2);
1696
+ if ( type === NODE_TYPE_NET_PATTERN_LEFT_HNANCHOR ) {
1697
+ this.addFlags(AST_FLAG_NET_PATTERN_LEFT_HNANCHOR);
1698
+ }
1699
+ patternBeg += 2;
1700
+ pattern = pattern.slice(2);
1701
+ } else {
1702
+ const type = this.isTokenCharCode(c2nd)
1703
+ ? NODE_TYPE_NET_PATTERN_LEFT_ANCHOR
1704
+ : NODE_TYPE_IGNORE;
1705
+ next = this.allocTypedNode(type, patternBeg, patternBeg+1);
1706
+ if ( type === NODE_TYPE_NET_PATTERN_LEFT_ANCHOR ) {
1707
+ this.addFlags(AST_FLAG_NET_PATTERN_LEFT_ANCHOR);
1708
+ }
1709
+ patternBeg += 1;
1710
+ pattern = pattern.slice(1);
1711
+ }
1712
+ prev = this.linkRight(prev, next);
1713
+ if ( patternBeg === patternEnd ) {
1714
+ this.addNodeFlags(next, NODE_FLAG_IGNORE);
1715
+ }
1716
+ }
1717
+
1718
+ // Right anchor
1719
+ if ( exCharCodeAt(pattern, -1) === 0x7C /* | */ ) {
1720
+ const type = exCharCodeAt(pattern, -2) !== 0x2A /* * */
1721
+ ? NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR
1722
+ : NODE_TYPE_IGNORE;
1723
+ tail = this.allocTypedNode(type, patternEnd-1, patternEnd);
1724
+ if ( type === NODE_TYPE_NET_PATTERN_RIGHT_ANCHOR ) {
1725
+ this.addFlags(AST_FLAG_NET_PATTERN_RIGHT_ANCHOR);
1726
+ }
1727
+ patternEnd -= 1;
1728
+ pattern = pattern.slice(0, -1);
1729
+ if ( patternEnd === patternBeg ) {
1730
+ this.addNodeFlags(tail, NODE_FLAG_IGNORE);
1731
+ }
1732
+ }
1733
+
1734
+ // Ignore pointless leading wildcards
1735
+ if ( hasWildcard && this.rePointlessLeadingWildcards.test(pattern) ) {
1736
+ const match = this.rePointlessLeadingWildcards.exec(pattern);
1737
+ const ignoreLen = match[1].length;
1738
+ next = this.allocTypedNode(
1739
+ NODE_TYPE_IGNORE,
1740
+ patternBeg,
1741
+ patternBeg + ignoreLen
1742
+ );
1743
+ prev = this.linkRight(prev, next);
1744
+ patternBeg += ignoreLen;
1745
+ pattern = pattern.slice(ignoreLen);
1746
+ }
1747
+
1748
+ // Ignore pointless trailing separators
1749
+ if ( this.rePointlessTrailingSeparator.test(pattern) ) {
1750
+ const match = this.rePointlessTrailingSeparator.exec(pattern);
1751
+ const ignoreLen = match[1].length;
1752
+ next = this.allocTypedNode(
1753
+ NODE_TYPE_IGNORE,
1754
+ patternEnd - ignoreLen,
1755
+ patternEnd
1756
+ );
1757
+ patternEnd -= ignoreLen;
1758
+ pattern = pattern.slice(0, -ignoreLen);
1759
+ if ( tail !== 0 ) { this.linkRight(next, tail); }
1760
+ tail = next;
1761
+ }
1762
+
1763
+ // Ignore pointless trailing wildcards. Exception: when removing the
1764
+ // trailing wildcard make the pattern look like a regex.
1765
+ if ( hasWildcard && this.rePointlessTrailingWildcards.test(pattern) ) {
1766
+ const match = this.rePointlessTrailingWildcards.exec(pattern);
1767
+ const ignoreLen = match[1].length;
1768
+ const needWildcard = pattern.charCodeAt(0) === 0x2F &&
1769
+ exCharCodeAt(pattern, -ignoreLen-1) === 0x2F;
1770
+ const goodWildcardBeg = patternEnd - ignoreLen;
1771
+ const badWildcardBeg = goodWildcardBeg + (needWildcard ? 1 : 0);
1772
+ if ( badWildcardBeg !== patternEnd ) {
1773
+ next = this.allocTypedNode(
1774
+ NODE_TYPE_IGNORE,
1775
+ badWildcardBeg,
1776
+ patternEnd
1777
+ );
1778
+ if ( tail !== 0 ) {this.linkRight(next, tail); }
1779
+ tail = next;
1780
+ }
1781
+ if ( goodWildcardBeg !== badWildcardBeg ) {
1782
+ next = this.allocTypedNode(
1783
+ NODE_TYPE_NET_PATTERN_PART_SPECIAL,
1784
+ goodWildcardBeg,
1785
+ badWildcardBeg
1786
+ );
1787
+ if ( tail !== 0 ) { this.linkRight(next, tail); }
1788
+ tail = next;
1789
+ }
1790
+ patternEnd -= ignoreLen;
1791
+ pattern = pattern.slice(0, -ignoreLen);
1792
+ }
1793
+
1794
+ const patternHasWhitespace = this.hasWhitespace &&
1795
+ this.reHasWhitespaceChar.test(pattern);
1796
+ const needNormalization = this.needPatternNormalization(pattern);
1797
+ const normal = needNormalization
1798
+ ? this.normalizePattern(pattern)
1799
+ : pattern;
1800
+ next = this.allocTypedNode(NODE_TYPE_NET_PATTERN, patternBeg, patternEnd);
1801
+ if ( patternHasWhitespace || normal === undefined ) {
1802
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_BAD;
1803
+ this.addFlags(AST_FLAG_HAS_ERROR);
1804
+ this.astError = AST_ERROR_PATTERN;
1805
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
1806
+ } else if ( normal === '*' ) {
1807
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_ANY;
1808
+ } else if ( this.reHostnameAscii.test(normal) ) {
1809
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_HOSTNAME;
1810
+ } else if ( this.reHasPatternSpecialChars.test(normal) ) {
1811
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_GENERIC;
1812
+ } else {
1813
+ this.astTypeFlavor = AST_TYPE_NETWORK_PATTERN_PLAIN;
1814
+ }
1815
+ this.addNodeToRegister(NODE_TYPE_NET_PATTERN, next);
1816
+ if ( needNormalization && normal !== undefined ) {
1817
+ this.setNodeTransform(next, normal);
1818
+ }
1819
+ if ( this.interactive ) {
1820
+ this.linkDown(next, this.parsePatternParts(next, pattern));
1821
+ }
1822
+ prev = this.linkRight(prev, next);
1823
+
1824
+ if ( tail !== 0 ) {
1825
+ this.linkRight(prev, tail);
1826
+ }
1827
+ return this.throwHeadNode(head);
1828
+ }
1829
+
1830
+ isAdblockHostnamePattern(pattern) {
1831
+ if ( this.hasUnicode ) {
1832
+ return this.reHnAnchoredHostnameUnicode.test(pattern);
1833
+ }
1834
+ return this.reHnAnchoredHostnameAscii.test(pattern);
1835
+ }
1836
+
1837
+ parsePatternParts(parent, pattern) {
1838
+ if ( pattern.length === 0 ) { return 0; }
1839
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1840
+ const matches = pattern.matchAll(this.rePatternAllSpecialChars);
1841
+ const head = this.allocHeadNode();
1842
+ let prev = head, next = 0;
1843
+ let plainPartBeg = 0;
1844
+ for ( const match of matches ) {
1845
+ const plainPartEnd = match.index;
1846
+ if ( plainPartEnd !== plainPartBeg ) {
1847
+ next = this.allocTypedNode(
1848
+ NODE_TYPE_NET_PATTERN_PART,
1849
+ parentBeg + plainPartBeg,
1850
+ parentBeg + plainPartEnd
1851
+ );
1852
+ prev = this.linkRight(prev, next);
1853
+ }
1854
+ plainPartBeg = plainPartEnd + match[0].length;
1855
+ const type = match[0].charCodeAt(0) < 0x80
1856
+ ? NODE_TYPE_NET_PATTERN_PART_SPECIAL
1857
+ : NODE_TYPE_NET_PATTERN_PART_UNICODE;
1858
+ next = this.allocTypedNode(
1859
+ type,
1860
+ parentBeg + plainPartEnd,
1861
+ parentBeg + plainPartBeg
1862
+ );
1863
+ prev = this.linkRight(prev, next);
1864
+ }
1865
+ if ( plainPartBeg !== pattern.length ) {
1866
+ next = this.allocTypedNode(
1867
+ NODE_TYPE_NET_PATTERN_PART,
1868
+ parentBeg + plainPartBeg,
1869
+ parentBeg + pattern.length
1870
+ );
1871
+ this.linkRight(prev, next);
1872
+ }
1873
+ return this.throwHeadNode(head);
1874
+ }
1875
+
1876
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/1118#issuecomment-650730158
1877
+ // Be ready to deal with non-punycode-able Unicode characters.
1878
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/772
1879
+ // Encode Unicode characters beyond the hostname part.
1880
+ // Prepend with '*' character to prevent the browser API from refusing to
1881
+ // punycode -- this occurs when the extracted label starts with a dash.
1882
+ needPatternNormalization(pattern) {
1883
+ return pattern.length === 0 || this.hasUppercase || this.hasUnicode;
1884
+ }
1885
+
1886
+ normalizePattern(pattern) {
1887
+ if ( pattern.length === 0 ) { return '*'; }
1888
+ if ( this.reHasInvalidChar.test(pattern) ) { return; }
1889
+ let normal = pattern.toLowerCase();
1890
+ if ( this.hasUnicode === false ) { return normal; }
1891
+ // Punycode hostname part of the pattern.
1892
+ if ( this.reHostnamePatternPart.test(normal) ) {
1893
+ const match = this.reHostnamePatternPart.exec(normal);
1894
+ const hn = match[0].replace(this.reHostnameLabel, s => {
1895
+ if ( this.reHasUnicodeChar.test(s) === false ) { return s; }
1896
+ if ( s.charCodeAt(0) === 0x2D /* - */ ) { s = '*' + s; }
1897
+ return this.normalizeHostnameValue(s, 0b0001) || s;
1898
+ });
1899
+ normal = hn + normal.slice(match.index + match[0].length);
1900
+ }
1901
+ if ( this.reHasUnicodeChar.test(normal) === false ) { return normal; }
1902
+ // Percent-encode remaining Unicode characters.
1903
+ try {
1904
+ normal = normal.replace(this.reUnicodeChars, s =>
1905
+ encodeURIComponent(s).toLowerCase()
1906
+ );
1907
+ } catch (ex) {
1908
+ return;
1909
+ }
1910
+ return normal;
1911
+ }
1912
+
1913
+ getNetPattern() {
1914
+ const node = this.nodeTypeLookupTable[NODE_TYPE_NET_PATTERN];
1915
+ return this.getNodeTransform(node);
1916
+ }
1917
+
1918
+ isAnyPattern() {
1919
+ return this.astTypeFlavor === AST_TYPE_NETWORK_PATTERN_ANY;
1920
+ }
1921
+
1922
+ isHostnamePattern() {
1923
+ return this.astTypeFlavor === AST_TYPE_NETWORK_PATTERN_HOSTNAME;
1924
+ }
1925
+
1926
+ isRegexPattern() {
1927
+ return this.astTypeFlavor === AST_TYPE_NETWORK_PATTERN_REGEX;
1928
+ }
1929
+
1930
+ isPlainPattern() {
1931
+ return this.astTypeFlavor === AST_TYPE_NETWORK_PATTERN_PLAIN;
1932
+ }
1933
+
1934
+ isGenericPattern() {
1935
+ return this.astTypeFlavor === AST_TYPE_NETWORK_PATTERN_GENERIC;
1936
+ }
1937
+
1938
+ isBadPattern() {
1939
+ return this.astTypeFlavor === AST_TYPE_NETWORK_PATTERN_BAD;
1940
+ }
1941
+
1942
+ parseNetOptions(parent) {
1943
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1944
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
1945
+ if ( parentEnd === parentBeg ) { return 0; }
1946
+ const s = this.getNodeString(parent);
1947
+ const optionsEnd = s.length;
1948
+ const head = this.allocHeadNode();
1949
+ let prev = head, next = 0;
1950
+ let optionBeg = 0, optionEnd = 0;
1951
+ let emptyOption = false, badComma = false;
1952
+ while ( optionBeg !== optionsEnd ) {
1953
+ optionEnd = this.endOfNetOption(s, optionBeg);
1954
+ next = this.allocTypedNode(
1955
+ NODE_TYPE_NET_OPTION_RAW,
1956
+ parentBeg + optionBeg,
1957
+ parentBeg + optionEnd
1958
+ );
1959
+ emptyOption = optionEnd === optionBeg;
1960
+ this.linkDown(next, this.parseNetOption(next));
1961
+ prev = this.linkRight(prev, next);
1962
+ if ( optionEnd === optionsEnd ) { break; }
1963
+ optionBeg = optionEnd + 1;
1964
+ next = this.allocTypedNode(
1965
+ NODE_TYPE_NET_OPTION_SEPARATOR,
1966
+ parentBeg + optionEnd,
1967
+ parentBeg + optionBeg
1968
+ );
1969
+ badComma = optionBeg === optionsEnd;
1970
+ prev = this.linkRight(prev, next);
1971
+ if ( emptyOption || badComma ) {
1972
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
1973
+ this.addFlags(AST_FLAG_HAS_ERROR);
1974
+ }
1975
+ }
1976
+ this.linkRight(prev,
1977
+ this.allocSentinelNode(NODE_TYPE_NET_OPTION_SENTINEL, parentEnd)
1978
+ );
1979
+ return this.throwHeadNode(head);
1980
+ }
1981
+
1982
+ endOfNetOption(s, beg) {
1983
+ const match = this.reNetOptionComma.exec(s.slice(beg));
1984
+ return match !== null ? beg + match.index : s.length;
1985
+ }
1986
+
1987
+ parseNetOption(parent) {
1988
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
1989
+ const s = this.getNodeString(parent);
1990
+ const optionEnd = s.length;
1991
+ const head = this.allocHeadNode();
1992
+ let prev = head, next = 0;
1993
+ let nameBeg = 0;
1994
+ if ( s.charCodeAt(0) === 0x7E ) {
1995
+ this.addNodeFlags(parent, NODE_FLAG_IS_NEGATED);
1996
+ next = this.allocTypedNode(
1997
+ NODE_TYPE_NET_OPTION_NAME_NOT,
1998
+ parentBeg,
1999
+ parentBeg+1
2000
+ );
2001
+ prev = this.linkRight(prev, next);
2002
+ nameBeg += 1;
2003
+ }
2004
+ const equalPos = s.indexOf('=');
2005
+ const nameEnd = equalPos !== -1 ? equalPos : s.length;
2006
+ const name = s.slice(nameBeg, nameEnd);
2007
+ let nodeOptionType = nodeTypeFromOptionName.get(name);
2008
+ if ( nodeOptionType === undefined ) {
2009
+ nodeOptionType = this.reNoopOption.test(name)
2010
+ ? NODE_TYPE_NET_OPTION_NAME_NOOP
2011
+ : NODE_TYPE_NET_OPTION_NAME_UNKNOWN;
2012
+ }
2013
+ next = this.allocTypedNode(
2014
+ nodeOptionType,
2015
+ parentBeg + nameBeg,
2016
+ parentBeg + nameEnd
2017
+ );
2018
+ if (
2019
+ nodeOptionType !== NODE_TYPE_NET_OPTION_NAME_NOOP &&
2020
+ this.getBranchFromType(nodeOptionType) !== 0
2021
+ ) {
2022
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2023
+ this.addFlags(AST_FLAG_HAS_ERROR);
2024
+ this.astError = AST_ERROR_OPTION_DUPLICATE;
2025
+ } else {
2026
+ this.addNodeToRegister(nodeOptionType, parent);
2027
+ }
2028
+ prev = this.linkRight(prev, next);
2029
+ if ( equalPos === -1 ) {
2030
+ return this.throwHeadNode(head);
2031
+ }
2032
+ const valueBeg = equalPos + 1;
2033
+ next = this.allocTypedNode(
2034
+ NODE_TYPE_NET_OPTION_ASSIGN,
2035
+ parentBeg + equalPos,
2036
+ parentBeg + valueBeg
2037
+ );
2038
+ prev = this.linkRight(prev, next);
2039
+ if ( (equalPos+1) === optionEnd ) {
2040
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2041
+ this.addFlags(AST_FLAG_HAS_ERROR);
2042
+ return this.throwHeadNode(head);
2043
+ }
2044
+ this.addNodeFlags(parent, NODE_FLAG_OPTION_HAS_VALUE);
2045
+ next = this.allocTypedNode(
2046
+ NODE_TYPE_NET_OPTION_VALUE,
2047
+ parentBeg + valueBeg,
2048
+ parentBeg + optionEnd
2049
+ );
2050
+ switch ( nodeOptionType ) {
2051
+ case NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
2052
+ this.linkDown(next, this.parseDomainList(next, '|'), 0b00000);
2053
+ break;
2054
+ case NODE_TYPE_NET_OPTION_NAME_FROM:
2055
+ case NODE_TYPE_NET_OPTION_NAME_TO:
2056
+ this.linkDown(next, this.parseDomainList(next, '|', 0b11010));
2057
+ break;
2058
+ default:
2059
+ break;
2060
+ }
2061
+ this.linkRight(prev, next);
2062
+ return this.throwHeadNode(head);
2063
+ }
2064
+
2065
+ getNetOptionValue(type) {
2066
+ if ( this.nodeTypeRegister.includes(type) === false ) { return ''; }
2067
+ const optionNode = this.nodeTypeLookupTable[type];
2068
+ if ( optionNode === 0 ) { return ''; }
2069
+ const valueNode = this.findDescendantByType(optionNode, NODE_TYPE_NET_OPTION_VALUE);
2070
+ if ( valueNode === 0 ) { return ''; }
2071
+ return this.getNodeTransform(valueNode);
2072
+ }
2073
+
2074
+ parseDomainList(parent, separator, mode = 0b00000) {
2075
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2076
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
2077
+ const containerNode = this.allocTypedNode(
2078
+ NODE_TYPE_OPTION_VALUE_DOMAIN_LIST,
2079
+ parentBeg,
2080
+ parentEnd
2081
+ );
2082
+ if ( parentEnd === parentBeg ) { return containerNode; }
2083
+ const separatorCode = separator.charCodeAt(0);
2084
+ const listNode = this.allocHeadNode();
2085
+ let prev = listNode;
2086
+ let domainNode = 0;
2087
+ let separatorNode = 0;
2088
+ const s = this.getNodeString(parent);
2089
+ const listEnd = s.length;
2090
+ let beg = 0, end = 0, c = 0;
2091
+ while ( beg < listEnd ) {
2092
+ c = s.charCodeAt(beg);
2093
+ if ( c === 0x7E /* ~ */ ) {
2094
+ c = s.charCodeAt(beg+1) || 0;
2095
+ }
2096
+ if ( c !== 0x2F /* / */ ) {
2097
+ end = s.indexOf(separator, beg);
2098
+ } else {
2099
+ end = s.indexOf('/', beg+1);
2100
+ end = s.indexOf(separator, end !== -1 ? end+1 : beg);
2101
+ }
2102
+ if ( end === -1 ) { end = listEnd; }
2103
+ if ( end !== beg ) {
2104
+ domainNode = this.allocTypedNode(
2105
+ NODE_TYPE_OPTION_VALUE_DOMAIN_RAW,
2106
+ parentBeg + beg,
2107
+ parentBeg + end
2108
+ );
2109
+ this.linkDown(domainNode, this.parseDomain(domainNode, mode));
2110
+ prev = this.linkRight(prev, domainNode);
2111
+ } else {
2112
+ domainNode = 0;
2113
+ if ( separatorNode !== 0 ) {
2114
+ this.addNodeFlags(separatorNode, NODE_FLAG_ERROR);
2115
+ this.addFlags(AST_FLAG_HAS_ERROR);
2116
+ }
2117
+ }
2118
+ if ( s.charCodeAt(end) === separatorCode ) {
2119
+ beg = end;
2120
+ end += 1;
2121
+ separatorNode = this.allocTypedNode(
2122
+ NODE_TYPE_OPTION_VALUE_SEPARATOR,
2123
+ parentBeg + beg,
2124
+ parentBeg + end
2125
+ );
2126
+ prev = this.linkRight(prev, separatorNode);
2127
+ if ( domainNode === 0 ) {
2128
+ this.addNodeFlags(separatorNode, NODE_FLAG_ERROR);
2129
+ this.addFlags(AST_FLAG_HAS_ERROR);
2130
+ }
2131
+ } else {
2132
+ separatorNode = 0;
2133
+ }
2134
+ beg = end;
2135
+ }
2136
+ // Dangling separator node
2137
+ if ( separatorNode !== 0 ) {
2138
+ this.addNodeFlags(separatorNode, NODE_FLAG_ERROR);
2139
+ this.addFlags(AST_FLAG_HAS_ERROR);
2140
+ }
2141
+ this.linkDown(containerNode, this.throwHeadNode(listNode));
2142
+ return containerNode;
2143
+ }
2144
+
2145
+ parseDomain(parent, mode = 0b0000) {
2146
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2147
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
2148
+ let head = 0, next = 0;
2149
+ let beg = parentBeg;
2150
+ const c = this.charCodeAt(beg);
2151
+ if ( c === 0x7E /* ~ */ ) {
2152
+ this.addNodeFlags(parent, NODE_FLAG_IS_NEGATED);
2153
+ head = this.allocTypedNode(NODE_TYPE_OPTION_VALUE_NOT, beg, beg + 1);
2154
+ if ( (mode & 0b1000) === 0 ) {
2155
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2156
+ }
2157
+ beg += 1;
2158
+ }
2159
+ if ( beg !== parentEnd ) {
2160
+ next = this.allocTypedNode(NODE_TYPE_OPTION_VALUE_DOMAIN, beg, parentEnd);
2161
+ const hn = this.normalizeDomainValue(this.getNodeString(next), mode);
2162
+ if ( hn !== undefined ) {
2163
+ if ( hn !== '' ) {
2164
+ this.setNodeTransform(next, hn);
2165
+ } else {
2166
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2167
+ this.addFlags(AST_FLAG_HAS_ERROR);
2168
+ this.astError = AST_ERROR_DOMAIN_NAME;
2169
+ }
2170
+ }
2171
+ if ( head === 0 ) {
2172
+ head = next;
2173
+ } else {
2174
+ this.linkRight(head, next);
2175
+ }
2176
+ } else {
2177
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2178
+ this.addFlags(AST_FLAG_HAS_ERROR);
2179
+ }
2180
+ return head;
2181
+ }
2182
+
2183
+ // mode bits:
2184
+ // 0b00001: can use wildcard at any position
2185
+ // 0b00010: can use entity-based hostnames
2186
+ // 0b00100: can use single wildcard
2187
+ // 0b01000: can be negated
2188
+ // 0b10000: can be a regex
2189
+ normalizeDomainValue(s, modeBits) {
2190
+ if ( (modeBits & 0b10000) === 0 ||
2191
+ s.length <= 2 ||
2192
+ s.charCodeAt(0) !== 0x2F /* / */ ||
2193
+ exCharCodeAt(s, -1) !== 0x2F /* / */
2194
+ ) {
2195
+ return this.normalizeHostnameValue(s, modeBits);
2196
+ }
2197
+ const source = this.normalizeRegexPattern(s);
2198
+ if ( source === '' ) { return ''; }
2199
+ return `/${source}/`;
2200
+ }
2201
+
2202
+ parseExt(parent, anchorBeg, anchorLen) {
2203
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2204
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
2205
+ const head = this.allocHeadNode();
2206
+ let prev = head, next = 0;
2207
+ this.astType = AST_TYPE_EXTENDED;
2208
+ this.addFlags(this.extFlagsFromAnchor(anchorBeg));
2209
+ if ( anchorBeg > parentBeg ) {
2210
+ next = this.allocTypedNode(
2211
+ NODE_TYPE_EXT_OPTIONS,
2212
+ parentBeg,
2213
+ anchorBeg
2214
+ );
2215
+ this.addFlags(AST_FLAG_HAS_OPTIONS);
2216
+ this.addNodeToRegister(NODE_TYPE_EXT_OPTIONS, next);
2217
+ this.linkDown(next, this.parseDomainList(next, ',', 0b11110));
2218
+ prev = this.linkRight(prev, next);
2219
+ }
2220
+ next = this.allocTypedNode(
2221
+ NODE_TYPE_EXT_OPTIONS_ANCHOR,
2222
+ anchorBeg,
2223
+ anchorBeg + anchorLen
2224
+ );
2225
+ this.addNodeToRegister(NODE_TYPE_EXT_OPTIONS_ANCHOR, next);
2226
+ prev = this.linkRight(prev, next);
2227
+ next = this.allocTypedNode(
2228
+ NODE_TYPE_EXT_PATTERN_RAW,
2229
+ anchorBeg + anchorLen,
2230
+ parentEnd
2231
+ );
2232
+ this.addNodeToRegister(NODE_TYPE_EXT_PATTERN_RAW, next);
2233
+ const down = this.parseExtPattern(next);
2234
+ if ( down !== 0 ) {
2235
+ this.linkDown(next, down);
2236
+ } else {
2237
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
2238
+ this.addFlags(AST_FLAG_HAS_ERROR);
2239
+ }
2240
+ this.linkRight(prev, next);
2241
+ this.validateExt();
2242
+ return this.throwHeadNode(head);
2243
+ }
2244
+
2245
+ extFlagsFromAnchor(anchorBeg) {
2246
+ let c = this.charCodeAt(anchorBeg+1) ;
2247
+ if ( c === 0x23 /* # */ ) { return 0; }
2248
+ if ( c === 0x25 /* % */ ) { return AST_FLAG_EXT_SCRIPTLET_ADG; }
2249
+ if ( c === 0x3F /* ? */ ) { return AST_FLAG_EXT_STRONG; }
2250
+ if ( c === 0x24 /* $ */ ) {
2251
+ c = this.charCodeAt(anchorBeg+2);
2252
+ if ( c === 0x23 /* # */ ) { return AST_FLAG_EXT_STYLE; }
2253
+ if ( c === 0x3F /* ? */ ) {
2254
+ return AST_FLAG_EXT_STYLE | AST_FLAG_EXT_STRONG;
2255
+ }
2256
+ }
2257
+ if ( c === 0x40 /* @ */ ) {
2258
+ return AST_FLAG_IS_EXCEPTION | this.extFlagsFromAnchor(anchorBeg+1);
2259
+ }
2260
+ return AST_FLAG_UNSUPPORTED | AST_FLAG_HAS_ERROR;
2261
+ }
2262
+
2263
+ validateExt() {
2264
+ const isException = this.isException();
2265
+ let realBad = false;
2266
+ for ( let i = 0, n = this.nodeTypeRegisterPtr; i < n; i++ ) {
2267
+ const type = this.nodeTypeRegister[i];
2268
+ const targetNode = this.nodeTypeLookupTable[type];
2269
+ if ( targetNode === 0 ) { continue; }
2270
+ const flags = this.getNodeFlags(targetNode);
2271
+ if ( (flags & NODE_FLAG_ERROR) !== 0 ) { continue; }
2272
+ realBad = false;
2273
+ switch ( type ) {
2274
+ case NODE_TYPE_EXT_PATTERN_RESPONSEHEADER: {
2275
+ const pattern = this.getNodeString(targetNode);
2276
+ realBad =
2277
+ pattern !== '' && removableHTTPHeaders.has(pattern) === false ||
2278
+ pattern === '' && isException === false;
2279
+ break;
2280
+ }
2281
+ case NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN: {
2282
+ if ( this.interactive !== true ) { break; }
2283
+ if ( isException ) { break; }
2284
+ const { trustedSource, trustedScriptletTokens } = this.options;
2285
+ if ( trustedScriptletTokens instanceof Set === false ) { break; }
2286
+ const token = this.getNodeString(targetNode);
2287
+ if ( trustedScriptletTokens.has(token) && trustedSource !== true ) {
2288
+ this.astError = AST_ERROR_UNTRUSTED_SOURCE;
2289
+ realBad = true;
2290
+ }
2291
+ break;
2292
+ }
2293
+ default:
2294
+ break;
2295
+ }
2296
+ if ( realBad ) {
2297
+ this.addNodeFlags(targetNode, NODE_FLAG_ERROR);
2298
+ this.addFlags(AST_FLAG_HAS_ERROR);
2299
+ }
2300
+ }
2301
+ }
2302
+
2303
+ parseExtPattern(parent) {
2304
+ const c = this.charCodeAt(this.nodes[parent+NODE_BEG_INDEX]);
2305
+ // ##+js(...)
2306
+ if ( c === 0x2B /* + */ ) {
2307
+ const s = this.getNodeString(parent);
2308
+ if ( /^\+js\(.*\)$/.exec(s) !== null ) {
2309
+ this.astTypeFlavor = AST_TYPE_EXTENDED_SCRIPTLET;
2310
+ return this.parseExtPatternScriptlet(parent);
2311
+ }
2312
+ }
2313
+ // #%#//scriptlet(...)
2314
+ if ( this.getFlags(AST_FLAG_EXT_SCRIPTLET_ADG) ) {
2315
+ const s = this.getNodeString(parent);
2316
+ if ( /^\/\/scriptlet\(.*\)$/.exec(s) !== null ) {
2317
+ this.astTypeFlavor = AST_TYPE_EXTENDED_SCRIPTLET;
2318
+ return this.parseExtPatternScriptlet(parent);
2319
+ }
2320
+ return 0;
2321
+ }
2322
+ // ##^... | ##^responseheader(...)
2323
+ if ( c === 0x5E /* ^ */ ) {
2324
+ const s = this.getNodeString(parent);
2325
+ if ( this.reResponseheaderPattern.test(s) ) {
2326
+ this.astTypeFlavor = AST_TYPE_EXTENDED_RESPONSEHEADER;
2327
+ return this.parseExtPatternResponseheader(parent);
2328
+ }
2329
+ this.astTypeFlavor = AST_TYPE_EXTENDED_HTML;
2330
+ return this.parseExtPatternHtml(parent);
2331
+ }
2332
+ // ##...
2333
+ this.astTypeFlavor = AST_TYPE_EXTENDED_COSMETIC;
2334
+ return this.parseExtPatternCosmetic(parent);
2335
+ }
2336
+
2337
+ parseExtPatternScriptlet(parent) {
2338
+ const beg = this.nodes[parent+NODE_BEG_INDEX];
2339
+ const end = this.nodes[parent+NODE_END_INDEX];
2340
+ const s = this.getNodeString(parent);
2341
+ const rawArg0 = beg + (s.startsWith('+js') ? 4 : 12);
2342
+ const rawArg1 = end - 1;
2343
+ const head = this.allocTypedNode(NODE_TYPE_EXT_DECORATION, beg, rawArg0);
2344
+ let prev = head, next = 0;
2345
+ next = this.allocTypedNode(NODE_TYPE_EXT_PATTERN_SCRIPTLET, rawArg0, rawArg1);
2346
+ this.addNodeToRegister(NODE_TYPE_EXT_PATTERN_SCRIPTLET, next);
2347
+ this.linkDown(next, this.parseExtPatternScriptletArgs(next));
2348
+ prev = this.linkRight(prev, next);
2349
+ next = this.allocTypedNode(NODE_TYPE_EXT_DECORATION, rawArg1, end);
2350
+ this.linkRight(prev, next);
2351
+ return head;
2352
+ }
2353
+
2354
+ parseExtPatternScriptletArgs(parent) {
2355
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2356
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
2357
+ if ( parentEnd === parentBeg ) { return 0; }
2358
+ const head = this.allocHeadNode();
2359
+ let prev = head, next = 0;
2360
+ const s = this.getNodeString(parent);
2361
+ const argsEnd = s.length;
2362
+ // token
2363
+ this.scriptletArgListParser.mustQuote =
2364
+ this.getFlags(AST_FLAG_EXT_SCRIPTLET_ADG) !== 0;
2365
+ const details = this.scriptletArgListParser.nextArg(s, 0);
2366
+ if ( details.argBeg > 0 ) {
2367
+ next = this.allocTypedNode(
2368
+ NODE_TYPE_EXT_DECORATION,
2369
+ parentBeg,
2370
+ parentBeg + details.argBeg
2371
+ );
2372
+ prev = this.linkRight(prev, next);
2373
+ }
2374
+ const token = s.slice(details.argBeg, details.argEnd);
2375
+ const tokenEnd = details.argEnd - (token.endsWith('.js') ? 3 : 0);
2376
+ next = this.allocTypedNode(
2377
+ NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN,
2378
+ parentBeg + details.argBeg,
2379
+ parentBeg + tokenEnd
2380
+ );
2381
+ this.addNodeToRegister(NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN, next);
2382
+ if ( details.failed ) {
2383
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
2384
+ this.addFlags(AST_FLAG_HAS_ERROR);
2385
+ }
2386
+ prev = this.linkRight(prev, next);
2387
+ if ( tokenEnd < details.argEnd ) {
2388
+ next = this.allocTypedNode(
2389
+ NODE_TYPE_IGNORE,
2390
+ parentBeg + tokenEnd,
2391
+ parentBeg + details.argEnd
2392
+ );
2393
+ prev = this.linkRight(prev, next);
2394
+ }
2395
+ if ( details.quoteEnd < argsEnd ) {
2396
+ next = this.allocTypedNode(
2397
+ NODE_TYPE_EXT_DECORATION,
2398
+ parentBeg + details.argEnd,
2399
+ parentBeg + details.separatorEnd
2400
+ );
2401
+ prev = this.linkRight(prev, next);
2402
+ }
2403
+ // all args
2404
+ next = this.allocTypedNode(
2405
+ NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARGS,
2406
+ parentBeg + details.separatorEnd,
2407
+ parentBeg + argsEnd
2408
+ );
2409
+ this.linkDown(next, this.parseExtPatternScriptletArglist(next));
2410
+ prev = this.linkRight(prev, next);
2411
+ return this.throwHeadNode(head);
2412
+ }
2413
+
2414
+ parseExtPatternScriptletArglist(parent) {
2415
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2416
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
2417
+ if ( parentEnd === parentBeg ) { return 0; }
2418
+ const s = this.getNodeString(parent);
2419
+ const argsEnd = s.length;
2420
+ const head = this.allocHeadNode();
2421
+ let prev = head, next = 0;
2422
+ let decorationBeg = 0;
2423
+ let i = 0;
2424
+ for (;;) {
2425
+ const details = this.scriptletArgListParser.nextArg(s, i);
2426
+ if ( decorationBeg < details.argBeg ) {
2427
+ next = this.allocTypedNode(
2428
+ NODE_TYPE_EXT_DECORATION,
2429
+ parentBeg + decorationBeg,
2430
+ parentBeg + details.argBeg
2431
+ );
2432
+ prev = this.linkRight(prev, next);
2433
+ }
2434
+ if ( i === argsEnd ) { break; }
2435
+ next = this.allocTypedNode(
2436
+ NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG,
2437
+ parentBeg + details.argBeg,
2438
+ parentBeg + details.argEnd
2439
+ );
2440
+ if ( details.transform ) {
2441
+ const arg = s.slice(details.argBeg, details.argEnd);
2442
+ this.setNodeTransform(next,
2443
+ this.scriptletArgListParser.normalizeArg(arg)
2444
+ );
2445
+ }
2446
+ prev = this.linkRight(prev, next);
2447
+ if ( details.failed ) {
2448
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
2449
+ this.addFlags(AST_FLAG_HAS_ERROR);
2450
+ }
2451
+ decorationBeg = details.argEnd;
2452
+ i = details.separatorEnd;
2453
+ }
2454
+ return this.throwHeadNode(head);
2455
+ }
2456
+
2457
+ getScriptletArgs() {
2458
+ const args = [];
2459
+ if ( this.isScriptletFilter() === false ) { return args; }
2460
+ const root = this.getBranchFromType(NODE_TYPE_EXT_PATTERN_SCRIPTLET);
2461
+ const walker = this.getWalker(root);
2462
+ for ( let node = walker.next(); node !== 0; node = walker.next() ) {
2463
+ switch ( this.getNodeType(node) ) {
2464
+ case NODE_TYPE_EXT_PATTERN_SCRIPTLET_TOKEN:
2465
+ case NODE_TYPE_EXT_PATTERN_SCRIPTLET_ARG:
2466
+ args.push(this.getNodeTransform(node));
2467
+ break;
2468
+ default:
2469
+ break;
2470
+ }
2471
+ }
2472
+ walker.dispose();
2473
+ return args;
2474
+ }
2475
+
2476
+ parseExtPatternResponseheader(parent) {
2477
+ const beg = this.nodes[parent+NODE_BEG_INDEX];
2478
+ const end = this.nodes[parent+NODE_END_INDEX];
2479
+ const s = this.getNodeString(parent);
2480
+ const rawArg0 = beg + 16;
2481
+ const rawArg1 = end - 1;
2482
+ const head = this.allocTypedNode(NODE_TYPE_EXT_DECORATION, beg, rawArg0);
2483
+ let prev = head, next = 0;
2484
+ const trimmedArg0 = rawArg0 + this.leftWhitespaceCount(s);
2485
+ const trimmedArg1 = rawArg1 - this.rightWhitespaceCount(s);
2486
+ if ( trimmedArg0 !== rawArg0 ) {
2487
+ next = this.allocTypedNode(NODE_TYPE_WHITESPACE, rawArg0, trimmedArg0);
2488
+ prev = this.linkRight(prev, next);
2489
+ }
2490
+ next = this.allocTypedNode(NODE_TYPE_EXT_PATTERN_RESPONSEHEADER, rawArg0, rawArg1);
2491
+ this.addNodeToRegister(NODE_TYPE_EXT_PATTERN_RESPONSEHEADER, next);
2492
+ if ( rawArg1 === rawArg0 && this.isException() === false ) {
2493
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2494
+ this.addFlags(AST_FLAG_HAS_ERROR);
2495
+ }
2496
+ prev = this.linkRight(prev, next);
2497
+ if ( trimmedArg1 !== rawArg1 ) {
2498
+ next = this.allocTypedNode(NODE_TYPE_WHITESPACE, trimmedArg1, rawArg1);
2499
+ prev = this.linkRight(prev, next);
2500
+ }
2501
+ next = this.allocTypedNode(NODE_TYPE_EXT_DECORATION, rawArg1, end);
2502
+ this.linkRight(prev, next);
2503
+ return head;
2504
+ }
2505
+
2506
+ parseExtPatternHtml(parent) {
2507
+ const beg = this.nodes[parent+NODE_BEG_INDEX];
2508
+ const end = this.nodes[parent+NODE_END_INDEX];
2509
+ const head = this.allocTypedNode(NODE_TYPE_EXT_DECORATION, beg, beg + 1);
2510
+ let prev = head, next = 0;
2511
+ next = this.allocTypedNode(NODE_TYPE_EXT_PATTERN_HTML, beg + 1, end);
2512
+ this.linkRight(prev, next);
2513
+ if ( (this.hasOptions() || this.isException()) === false ) {
2514
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2515
+ this.addFlags(AST_FLAG_HAS_ERROR);
2516
+ return head;
2517
+ }
2518
+ this.result.exception = this.isException();
2519
+ this.result.raw = this.getNodeString(next);
2520
+ this.result.compiled = undefined;
2521
+ const success = this.selectorCompiler.compile(
2522
+ this.result.raw,
2523
+ this.result, {
2524
+ asProcedural: this.getFlags(AST_FLAG_EXT_STRONG) !== 0
2525
+ }
2526
+ );
2527
+ if ( success !== true ) {
2528
+ this.addNodeFlags(next, NODE_FLAG_ERROR);
2529
+ this.addFlags(AST_FLAG_HAS_ERROR);
2530
+ }
2531
+ return head;
2532
+ }
2533
+
2534
+ parseExtPatternCosmetic(parent) {
2535
+ const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2536
+ const parentEnd = this.nodes[parent+NODE_END_INDEX];
2537
+ const head = this.allocTypedNode(
2538
+ NODE_TYPE_EXT_PATTERN_COSMETIC,
2539
+ parentBeg,
2540
+ parentEnd
2541
+ );
2542
+ this.result.exception = this.isException();
2543
+ this.result.raw = this.getNodeString(head);
2544
+ this.result.compiled = undefined;
2545
+ const success = this.selectorCompiler.compile(
2546
+ this.result.raw,
2547
+ this.result, {
2548
+ asProcedural: this.getFlags(AST_FLAG_EXT_STRONG) !== 0,
2549
+ adgStyleSyntax: this.getFlags(AST_FLAG_EXT_STYLE) !== 0,
2550
+ }
2551
+ );
2552
+ if ( success !== true ) {
2553
+ this.addNodeFlags(head, NODE_FLAG_ERROR);
2554
+ this.addFlags(AST_FLAG_HAS_ERROR);
2555
+ }
2556
+ return head;
2557
+ }
2558
+
2559
+ hasError() {
2560
+ return (this.astFlags & AST_FLAG_HAS_ERROR) !== 0;
2561
+ }
2562
+
2563
+ isUnsupported() {
2564
+ return (this.astFlags & AST_FLAG_UNSUPPORTED) !== 0;
2565
+ }
2566
+
2567
+ hasOptions() {
2568
+ return (this.astFlags & AST_FLAG_HAS_OPTIONS) !== 0;
2569
+ }
2570
+
2571
+ isNegatedOption(type) {
2572
+ const node = this.nodeTypeLookupTable[type];
2573
+ const flags = this.nodes[node+NODE_FLAGS_INDEX];
2574
+ return (flags & NODE_FLAG_IS_NEGATED) !== 0;
2575
+ }
2576
+
2577
+ isException() {
2578
+ return (this.astFlags & AST_FLAG_IS_EXCEPTION) !== 0;
2579
+ }
2580
+
2581
+ isLeftHnAnchored() {
2582
+ return (this.astFlags & AST_FLAG_NET_PATTERN_LEFT_HNANCHOR) !== 0;
2583
+ }
2584
+
2585
+ isLeftAnchored() {
2586
+ return (this.astFlags & AST_FLAG_NET_PATTERN_LEFT_ANCHOR) !== 0;
2587
+ }
2588
+
2589
+ isRightAnchored() {
2590
+ return (this.astFlags & AST_FLAG_NET_PATTERN_RIGHT_ANCHOR) !== 0;
2591
+ }
2592
+
2593
+ linkRight(prev, next) {
2594
+ return (this.nodes[prev+NODE_RIGHT_INDEX] = next);
2595
+ }
2596
+
2597
+ linkDown(node, down) {
2598
+ return (this.nodes[node+NODE_DOWN_INDEX] = down);
2599
+ }
2600
+
2601
+ makeChain(nodes) {
2602
+ for ( let i = 1; i < nodes.length; i++ ) {
2603
+ this.nodes[nodes[i-1]+NODE_RIGHT_INDEX] = nodes[i];
2604
+ }
2605
+ return nodes[0];
2606
+ }
2607
+
2608
+ allocHeadNode() {
2609
+ const node = this.nodePoolPtr;
2610
+ this.nodePoolPtr += NOOP_NODE_SIZE;
2611
+ if ( this.nodePoolPtr > this.nodePoolEnd ) {
2612
+ this.growNodePool(this.nodePoolPtr);
2613
+ }
2614
+ this.nodes[node+NODE_RIGHT_INDEX] = 0;
2615
+ return node;
2616
+ }
2617
+
2618
+ throwHeadNode(head) {
2619
+ return this.nodes[head+NODE_RIGHT_INDEX];
2620
+ }
2621
+
2622
+ allocTypedNode(type, beg, end) {
2623
+ const node = this.nodePoolPtr;
2624
+ this.nodePoolPtr += FULL_NODE_SIZE;
2625
+ if ( this.nodePoolPtr > this.nodePoolEnd ) {
2626
+ this.growNodePool(this.nodePoolPtr);
2627
+ }
2628
+ this.nodes[node+NODE_RIGHT_INDEX] = 0;
2629
+ this.nodes[node+NODE_TYPE_INDEX] = type;
2630
+ this.nodes[node+NODE_DOWN_INDEX] = 0;
2631
+ this.nodes[node+NODE_BEG_INDEX] = beg;
2632
+ this.nodes[node+NODE_END_INDEX] = end;
2633
+ this.nodes[node+NODE_TRANSFORM_INDEX] = 0;
2634
+ this.nodes[node+NODE_FLAGS_INDEX] = 0;
2635
+ return node;
2636
+ }
2637
+
2638
+ allocSentinelNode(type, beg) {
2639
+ return this.allocTypedNode(type, beg, beg);
2640
+ }
2641
+
2642
+ growNodePool(min) {
2643
+ const oldSize = this.nodes.length;
2644
+ const newSize = (min + 16383) & ~16383;
2645
+ if ( newSize === oldSize ) { return; }
2646
+ const newArray = new Uint32Array(newSize);
2647
+ newArray.set(this.nodes);
2648
+ this.nodes = newArray;
2649
+ this.nodePoolEnd = newSize;
2650
+ }
2651
+
2652
+ getNodeTypes() {
2653
+ return this.nodeTypeRegister.slice(0, this.nodeTypeRegisterPtr);
2654
+ }
2655
+
2656
+ getNodeType(node) {
2657
+ return node !== 0 ? this.nodes[node+NODE_TYPE_INDEX] : 0;
2658
+ }
2659
+
2660
+ getNodeFlags(node, flags = 0xFFFFFFFF) {
2661
+ return this.nodes[node+NODE_FLAGS_INDEX] & flags;
2662
+ }
2663
+
2664
+ setNodeFlags(node, flags) {
2665
+ this.nodes[node+NODE_FLAGS_INDEX] = flags;
2666
+ }
2667
+
2668
+ addNodeFlags(node, flags) {
2669
+ if ( node === 0 ) { return; }
2670
+ this.nodes[node+NODE_FLAGS_INDEX] |= flags;
2671
+ }
2672
+
2673
+ removeNodeFlags(node, flags) {
2674
+ this.nodes[node+NODE_FLAGS_INDEX] &= ~flags;
2675
+ }
2676
+
2677
+ addNodeToRegister(type, node) {
2678
+ this.nodeTypeRegister[this.nodeTypeRegisterPtr++] = type;
2679
+ this.nodeTypeLookupTable[type] = node;
2680
+ }
2681
+
2682
+ getBranchFromType(type) {
2683
+ const ptr = this.nodeTypeRegisterPtr;
2684
+ if ( ptr === 0 ) { return 0; }
2685
+ return this.nodeTypeRegister.lastIndexOf(type, ptr-1) !== -1
2686
+ ? this.nodeTypeLookupTable[type]
2687
+ : 0;
2688
+ }
2689
+
2690
+ nodeIsEmptyString(node) {
2691
+ return this.nodes[node+NODE_END_INDEX] ===
2692
+ this.nodes[node+NODE_BEG_INDEX];
2693
+ }
2694
+
2695
+ getNodeString(node) {
2696
+ const beg = this.nodes[node+NODE_BEG_INDEX];
2697
+ const end = this.nodes[node+NODE_END_INDEX];
2698
+ if ( end === beg ) { return ''; }
2699
+ if ( beg === 0 && end === this.rawEnd ) {
2700
+ return this.raw;
2701
+ }
2702
+ return this.raw.slice(beg, end);
2703
+ }
2704
+
2705
+ getNodeStringBeg(node) {
2706
+ return this.nodes[node+NODE_BEG_INDEX];
2707
+ }
2708
+
2709
+ getNodeStringEnd(node) {
2710
+ return this.nodes[node+NODE_END_INDEX];
2711
+ }
2712
+
2713
+ getNodeStringLen(node) {
2714
+ if ( node === 0 ) { return ''; }
2715
+ return this.nodes[node+NODE_END_INDEX] - this.nodes[node+NODE_BEG_INDEX];
2716
+ }
2717
+
2718
+ isNodeTransformed(node) {
2719
+ return this.nodes[node+NODE_TRANSFORM_INDEX] !== 0;
2720
+ }
2721
+
2722
+ getNodeTransform(node) {
2723
+ if ( node === 0 ) { return ''; }
2724
+ const slot = this.nodes[node+NODE_TRANSFORM_INDEX];
2725
+ return slot !== 0 ? this.astTransforms[slot] : this.getNodeString(node);
2726
+ }
2727
+
2728
+ setNodeTransform(node, value) {
2729
+ const slot = this.astTransformPtr++;
2730
+ this.astTransforms[slot] = value;
2731
+ this.nodes[node+NODE_TRANSFORM_INDEX] = slot;
2732
+ }
2733
+
2734
+ getTypeString(type) {
2735
+ const node = this.getBranchFromType(type);
2736
+ if ( node === 0 ) { return; }
2737
+ return this.getNodeString(node);
2738
+ }
2739
+
2740
+ leftWhitespaceCount(s) {
2741
+ const match = this.reWhitespaceStart.exec(s);
2742
+ return match === null ? 0 : match[0].length;
2743
+ }
2744
+
2745
+ rightWhitespaceCount(s) {
2746
+ const match = this.reWhitespaceEnd.exec(s);
2747
+ return match === null ? 0 : match[0].length;
2748
+ }
2749
+
2750
+ nextCommaInCommaSeparatedListString(s, start) {
2751
+ const n = s.length;
2752
+ if ( n === 0 ) { return -1; }
2753
+ const ilastchar = n - 1;
2754
+ let i = start;
2755
+ while ( i < n ) {
2756
+ const c = s.charCodeAt(i);
2757
+ if ( c === 0x2C /* ',' */ ) { return i + 1; }
2758
+ if ( c === 0x5C /* '\\' */ ) {
2759
+ if ( i < ilastchar ) { i += 1; }
2760
+ }
2761
+ }
2762
+ return -1;
2763
+ }
2764
+
2765
+ endOfLiteralRegex(s, start) {
2766
+ const n = s.length;
2767
+ if ( n === 0 ) { return -1; }
2768
+ const ilastchar = n - 1;
2769
+ let i = start + 1;
2770
+ while ( i < n ) {
2771
+ const c = s.charCodeAt(i);
2772
+ if ( c === 0x2F /* '/' */ ) { return i + 1; }
2773
+ if ( c === 0x5C /* '\\' */ ) {
2774
+ if ( i < ilastchar ) { i += 1; }
2775
+ }
2776
+ i += 1;
2777
+ }
2778
+ return -1;
2779
+ }
2780
+
2781
+ charCodeAt(pos) {
2782
+ return pos < this.rawEnd ? this.raw.charCodeAt(pos) : -1;
2783
+ }
2784
+
2785
+ isTokenCharCode(c) {
2786
+ return c === 0x25 ||
2787
+ c >= 0x30 && c <= 0x39 ||
2788
+ c >= 0x41 && c <= 0x5A ||
2789
+ c >= 0x61 && c <= 0x7A;
2790
+ }
2791
+
2792
+ // Ultimately, let the browser API do the hostname normalization, after
2793
+ // making some other trivial checks.
2794
+ //
2795
+ // mode bits:
2796
+ // 0b00001: can use wildcard at any position
2797
+ // 0b00010: can use entity-based hostnames
2798
+ // 0b00100: can use single wildcard
2799
+ // 0b01000: can be negated
2800
+ //
2801
+ // returns:
2802
+ // undefined: no normalization needed, use original hostname
2803
+ // empty string: hostname is invalid
2804
+ // non-empty string: normalized hostname
2805
+ normalizeHostnameValue(s, modeBits = 0b00000) {
2806
+ if ( this.reHostnameAscii.test(s) ) { return; }
2807
+ if ( this.reBadHostnameChars.test(s) ) { return ''; }
2808
+ let hn = s;
2809
+ const hasWildcard = hn.includes('*');
2810
+ if ( hasWildcard ) {
2811
+ if ( modeBits === 0 ) { return ''; }
2812
+ if ( hn.length === 1 ) {
2813
+ if ( (modeBits & 0b0100) === 0 ) { return ''; }
2814
+ return;
2815
+ }
2816
+ if ( (modeBits & 0b0010) !== 0 ) {
2817
+ if ( this.rePlainEntity.test(hn) ) { return; }
2818
+ if ( this.reIsEntity.test(hn) === false ) { return ''; }
2819
+ } else if ( (modeBits & 0b0001) === 0 ) {
2820
+ return '';
2821
+ }
2822
+ hn = hn.replace(/\*/g, '__asterisk__');
2823
+ }
2824
+ this.punycoder.hostname = '_';
2825
+ try {
2826
+ this.punycoder.hostname = hn;
2827
+ hn = this.punycoder.hostname;
2828
+ } catch (_) {
2829
+ return '';
2830
+ }
2831
+ if ( hn === '_' || hn === '' ) { return ''; }
2832
+ if ( hasWildcard ) {
2833
+ hn = this.punycoder.hostname.replace(/__asterisk__/g, '*');
2834
+ }
2835
+ if (
2836
+ (modeBits & 0b0001) === 0 && (
2837
+ hn.charCodeAt(0) === 0x2E /* . */ ||
2838
+ exCharCodeAt(hn, -1) === 0x2E /* . */
2839
+ )
2840
+ ) {
2841
+ return '';
2842
+ }
2843
+ return hn;
2844
+ }
2845
+
2846
+ normalizeRegexPattern(s) {
2847
+ try {
2848
+ const source = /^\/.+\/$/.test(s) ? s.slice(1,-1) : s;
2849
+ const regex = new RegExp(source);
2850
+ return regex.source;
2851
+ } catch (ex) {
2852
+ this.normalizeRegexPattern.message = ex.toString();
2853
+ }
2854
+ return '';
2855
+ }
2856
+
2857
+ getDomainListIterator(root) {
2858
+ const iter = this.domainListIteratorJunkyard.length !== 0
2859
+ ? this.domainListIteratorJunkyard.pop().reuse(root)
2860
+ : new DomainListIterator(this, root);
2861
+ return root !== 0 ? iter : iter.stop();
2862
+ }
2863
+
2864
+ getNetFilterFromOptionIterator() {
2865
+ return this.getDomainListIterator(
2866
+ this.getBranchFromType(NODE_TYPE_NET_OPTION_NAME_FROM)
2867
+ );
2868
+ }
2869
+
2870
+ getNetFilterToOptionIterator() {
2871
+ return this.getDomainListIterator(
2872
+ this.getBranchFromType(NODE_TYPE_NET_OPTION_NAME_TO)
2873
+ );
2874
+ }
2875
+
2876
+ getNetFilterDenyallowOptionIterator() {
2877
+ return this.getDomainListIterator(
2878
+ this.getBranchFromType(NODE_TYPE_NET_OPTION_NAME_DENYALLOW)
2879
+ );
2880
+ }
2881
+
2882
+ getExtFilterDomainIterator() {
2883
+ return this.getDomainListIterator(
2884
+ this.getBranchFromType(NODE_TYPE_EXT_OPTIONS)
2885
+ );
2886
+ }
2887
+
2888
+ getWalker(from) {
2889
+ if ( this.walkerJunkyard.length === 0 ) {
2890
+ return new AstWalker(this, from);
2891
+ }
2892
+ const walker = this.walkerJunkyard.pop();
2893
+ walker.reset(from);
2894
+ return walker;
2895
+ }
2896
+
2897
+ findDescendantByType(from, type) {
2898
+ const walker = this.getWalker(from);
2899
+ let node = walker.next();
2900
+ while ( node !== 0 ) {
2901
+ if ( this.getNodeType(node) === type ) { return node; }
2902
+ node = walker.next();
2903
+ }
2904
+ return 0;
2905
+ }
2906
+
2907
+ dump() {
2908
+ if ( this.astType === AST_TYPE_COMMENT ) { return; }
2909
+ const walker = this.getWalker();
2910
+ for ( let node = walker.reset(); node !== 0; node = walker.next() ) {
2911
+ const type = this.nodes[node+NODE_TYPE_INDEX];
2912
+ const value = this.getNodeString(node);
2913
+ const name = nodeNameFromNodeType.get(type) || `${type}`;
2914
+ const bits = this.getNodeFlags(node).toString(2).padStart(4, '0');
2915
+ const indent = ' '.repeat(walker.depth);
2916
+ console.log(`${indent}type=${name} "${value}" 0b${bits}`);
2917
+ if ( this.isNodeTransformed(node) ) {
2918
+ console.log(`${indent} transform="${this.getNodeTransform(node)}`);
2919
+ }
2920
+ }
2921
+ }
2922
+ }
2923
+
2924
+ /******************************************************************************/
2925
+
2926
+ export function parseRedirectValue(arg) {
2927
+ let token = arg.trim();
2928
+ let priority = 0;
2929
+ const asDataURI = token.charCodeAt(0) === 0x25 /* '%' */;
2930
+ if ( asDataURI ) { token = token.slice(1); }
2931
+ const match = /:-?\d+$/.exec(token);
2932
+ if ( match !== null ) {
2933
+ priority = parseInt(token.slice(match.index + 1), 10);
2934
+ token = token.slice(0, match.index);
2935
+ }
2936
+ return { token, priority, asDataURI };
2937
+ }
2938
+
2939
+ export function parseQueryPruneValue(arg) {
2940
+ let s = arg.trim();
2941
+ if ( s === '' ) { return { all: true }; }
2942
+ const out = { };
2943
+ out.not = s.charCodeAt(0) === 0x7E /* '~' */;
2944
+ if ( out.not ) {
2945
+ s = s.slice(1);
2946
+ }
2947
+ const match = /^\/(.+)\/(i)?$/.exec(s);
2948
+ if ( match !== null ) {
2949
+ try {
2950
+ out.re = new RegExp(match[1], match[2] || '');
2951
+ }
2952
+ catch(ex) {
2953
+ out.bad = true;
2954
+ }
2955
+ return out;
2956
+ }
2957
+ // TODO: remove once no longer used in filter lists
2958
+ if ( s.startsWith('|') ) {
2959
+ try {
2960
+ out.re = new RegExp('^' + s.slice(1), 'i');
2961
+ } catch(ex) {
2962
+ out.bad = true;
2963
+ }
2964
+ return out;
2965
+ }
2966
+ // Multiple values not supported (because very inefficient)
2967
+ if ( s.includes('|') ) {
2968
+ out.bad = true;
2969
+ return out;
2970
+ }
2971
+ out.name = s;
2972
+ return out;
2973
+ }
2974
+
2975
+ export function parseHeaderValue(arg) {
2976
+ let s = arg.trim();
2977
+ const out = { };
2978
+ let pos = s.indexOf(':');
2979
+ if ( pos === -1 ) { pos = s.length; }
2980
+ out.name = s.slice(0, pos);
2981
+ out.bad = out.name === '';
2982
+ s = s.slice(pos + 1);
2983
+ out.not = s.charCodeAt(0) === 0x7E /* '~' */;
2984
+ if ( out.not ) { s = s.slice(1); }
2985
+ out.value = s;
2986
+ const match = /^\/(.+)\/(i)?$/.exec(s);
2987
+ if ( match !== null ) {
2988
+ try {
2989
+ out.re = new RegExp(match[1], match[2] || '');
2990
+ }
2991
+ catch(ex) {
2992
+ out.bad = true;
2993
+ }
2994
+ }
2995
+ return out;
2996
+ }
2997
+
2998
+
2999
+ // https://adguard.com/kb/general/ad-filtering/create-own-filters/#replace-modifier
3000
+
3001
+ export function parseReplaceValue(s) {
3002
+ if ( s.charCodeAt(0) !== 0x2F /* / */ ) { return; }
3003
+ const parser = new ArgListParser('/');
3004
+ parser.nextArg(s, 1);
3005
+ let pattern = s.slice(parser.argBeg, parser.argEnd);
3006
+ if ( parser.transform ) {
3007
+ pattern = parser.normalizeArg(pattern);
3008
+ }
3009
+ if ( pattern === '' ) { return; }
3010
+ pattern = parser.normalizeArg(pattern, '$');
3011
+ pattern = parser.normalizeArg(pattern, ',');
3012
+ parser.nextArg(s, parser.separatorEnd);
3013
+ let replacement = s.slice(parser.argBeg, parser.argEnd);
3014
+ if ( parser.separatorEnd === parser.separatorBeg ) { return; }
3015
+ if ( parser.transform ) {
3016
+ replacement = parser.normalizeArg(replacement);
3017
+ }
3018
+ replacement = parser.normalizeArg(replacement, '$');
3019
+ replacement = parser.normalizeArg(replacement, ',');
3020
+ const flags = s.slice(parser.separatorEnd);
3021
+ try {
3022
+ return { re: new RegExp(pattern, flags), replacement };
3023
+ } catch(_) {
3024
+ }
3025
+ }
3026
+
3027
+ /******************************************************************************/
3028
+
3029
+ export const netOptionTokenDescriptors = new Map([
3030
+ [ '1p', { canNegate: true } ],
3031
+ /* synonym */ [ 'first-party', { canNegate: true } ],
3032
+ [ 'strict1p', { } ],
3033
+ [ '3p', { canNegate: true } ],
3034
+ /* synonym */ [ 'third-party', { canNegate: true } ],
3035
+ [ 'strict3p', { } ],
3036
+ [ 'all', { } ],
3037
+ [ 'badfilter', { } ],
3038
+ [ 'cname', { allowOnly: true } ],
3039
+ [ 'csp', { mustAssign: true } ],
3040
+ [ 'css', { canNegate: true } ],
3041
+ /* synonym */ [ 'stylesheet', { canNegate: true } ],
3042
+ [ 'denyallow', { mustAssign: true } ],
3043
+ [ 'doc', { canNegate: true } ],
3044
+ /* synonym */ [ 'document', { canNegate: true } ],
3045
+ [ 'ehide', { } ],
3046
+ /* synonym */ [ 'elemhide', { } ],
3047
+ [ 'empty', { blockOnly: true } ],
3048
+ [ 'frame', { canNegate: true } ],
3049
+ /* synonym */ [ 'subdocument', { canNegate: true } ],
3050
+ [ 'from', { mustAssign: true } ],
3051
+ /* synonym */ [ 'domain', { mustAssign: true } ],
3052
+ [ 'font', { canNegate: true } ],
3053
+ [ 'genericblock', { } ],
3054
+ [ 'ghide', { } ],
3055
+ /* synonym */ [ 'generichide', { } ],
3056
+ [ 'header', { mustAssign: true } ],
3057
+ [ 'image', { canNegate: true } ],
3058
+ [ 'important', { blockOnly: true } ],
3059
+ [ 'inline-font', { canNegate: true } ],
3060
+ [ 'inline-script', { canNegate: true } ],
3061
+ [ 'match-case', { } ],
3062
+ [ 'media', { canNegate: true } ],
3063
+ [ 'method', { mustAssign: true } ],
3064
+ [ 'mp4', { blockOnly: true } ],
3065
+ [ '_', { } ],
3066
+ [ 'object', { canNegate: true } ],
3067
+ /* synonym */ [ 'object-subrequest', { canNegate: true } ],
3068
+ [ 'other', { canNegate: true } ],
3069
+ [ 'ping', { canNegate: true } ],
3070
+ /* synonym */ [ 'beacon', { canNegate: true } ],
3071
+ [ 'popunder', { } ],
3072
+ [ 'popup', { canNegate: true } ],
3073
+ [ 'redirect', { mustAssign: true } ],
3074
+ /* synonym */ [ 'rewrite', { mustAssign: true } ],
3075
+ [ 'redirect-rule', { mustAssign: true } ],
3076
+ [ 'removeparam', { } ],
3077
+ [ 'replace', { mustAssign: true } ],
3078
+ /* synonym */ [ 'queryprune', { } ],
3079
+ [ 'script', { canNegate: true } ],
3080
+ [ 'shide', { } ],
3081
+ /* synonym */ [ 'specifichide', { } ],
3082
+ [ 'to', { mustAssign: true } ],
3083
+ [ 'urltransform', { mustAssign: true } ],
3084
+ [ 'xhr', { canNegate: true } ],
3085
+ /* synonym */ [ 'xmlhttprequest', { canNegate: true } ],
3086
+ [ 'webrtc', { } ],
3087
+ [ 'websocket', { canNegate: true } ],
3088
+ ]);
3089
+
3090
+ /******************************************************************************/
3091
+
3092
+ // https://github.com/chrisaljoudi/uBlock/issues/1004
3093
+ // Detect and report invalid CSS selectors.
3094
+
3095
+ // Discard new ABP's `-abp-properties` directive until it is
3096
+ // implemented (if ever). Unlikely, see:
3097
+ // https://github.com/gorhill/uBlock/issues/1752
3098
+
3099
+ // https://github.com/gorhill/uBlock/issues/2624
3100
+ // Convert Adguard's `-ext-has='...'` into uBO's `:has(...)`.
3101
+
3102
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/89
3103
+ // Do not discard unknown pseudo-elements.
3104
+
3105
+ class ExtSelectorCompiler {
3106
+ constructor(instanceOptions) {
3107
+ this.reParseRegexLiteral = /^\/(.+)\/([imu]+)?$/;
3108
+
3109
+ // Use a regex for most common CSS selectors known to be valid in any
3110
+ // context.
3111
+ const cssIdentifier = '[A-Za-z_][\\w-]*';
3112
+ const cssClassOrId = `[.#]${cssIdentifier}`;
3113
+ const cssAttribute = `\\[${cssIdentifier}(?:[*^$]?="[^"\\]\\\\]+")?\\]`;
3114
+ const cssSimple =
3115
+ '(?:' +
3116
+ `${cssIdentifier}(?:${cssClassOrId})*(?:${cssAttribute})*` + '|' +
3117
+ `${cssClassOrId}(?:${cssClassOrId})*(?:${cssAttribute})*` + '|' +
3118
+ `${cssAttribute}(?:${cssAttribute})*` +
3119
+ ')';
3120
+ const cssCombinator = '(?: | [+>~] )';
3121
+ this.reCommonSelector = new RegExp(
3122
+ `^${cssSimple}(?:${cssCombinator}${cssSimple})*$`
3123
+ );
3124
+ // Resulting regex literal:
3125
+ // /^(?:[A-Za-z_][\w-]*(?:[.#][A-Za-z_][\w-]*)*(?:\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\])*|[.#][A-Za-z_][\w-]*(?:[.#][A-Za-z_][\w-]*)*(?:\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\])*|\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\](?:\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\])*)(?:(?:\s+|\s*[>+~]\s*)(?:[A-Za-z_][\w-]*(?:[.#][A-Za-z_][\w-]*)*(?:\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\])*|[.#][A-Za-z_][\w-]*(?:[.#][A-Za-z_][\w-]*)*(?:\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\])*|\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\](?:\[[A-Za-z_][\w-]*(?:[*^$]?="[^"\]\\]+")?\])*))*$/
3126
+
3127
+ this.reEatBackslashes = /\\([()])/g;
3128
+ this.reEscapeRegex = /[.*+?^${}()|[\]\\]/g;
3129
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-classes
3130
+ this.knownPseudoClasses = new Set([
3131
+ 'active', 'any-link', 'autofill',
3132
+ 'blank',
3133
+ 'checked', 'current',
3134
+ 'default', 'defined', 'dir', 'disabled',
3135
+ 'empty', 'enabled',
3136
+ 'first', 'first-child', 'first-of-type', 'fullscreen', 'future', 'focus', 'focus-visible', 'focus-within',
3137
+ 'has', 'host', 'host-context', 'hover',
3138
+ 'indeterminate', 'in-range', 'invalid', 'is',
3139
+ 'lang', 'last-child', 'last-of-type', 'left', 'link', 'local-link',
3140
+ 'modal',
3141
+ 'not', 'nth-child', 'nth-col', 'nth-last-child', 'nth-last-col', 'nth-last-of-type', 'nth-of-type',
3142
+ 'only-child', 'only-of-type', 'optional', 'out-of-range',
3143
+ 'past', 'picture-in-picture', 'placeholder-shown', 'paused', 'playing',
3144
+ 'read-only', 'read-write', 'required', 'right', 'root',
3145
+ 'scope', 'state', 'target', 'target-within',
3146
+ 'user-invalid', 'valid', 'visited',
3147
+ 'where',
3148
+ ]);
3149
+ this.knownPseudoClassesWithArgs = new Set([
3150
+ 'dir',
3151
+ 'has', 'host-context',
3152
+ 'is',
3153
+ 'lang',
3154
+ 'not', 'nth-child', 'nth-col', 'nth-last-child', 'nth-last-col', 'nth-last-of-type', 'nth-of-type',
3155
+ 'state',
3156
+ 'where',
3157
+ ]);
3158
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
3159
+ this.knownPseudoElements = new Set([
3160
+ 'after',
3161
+ 'backdrop', 'before',
3162
+ 'cue', 'cue-region',
3163
+ 'first-letter', 'first-line', 'file-selector-button',
3164
+ 'grammar-error', 'marker',
3165
+ 'part', 'placeholder',
3166
+ 'selection', 'slotted', 'spelling-error',
3167
+ 'target-text',
3168
+ ]);
3169
+ this.knownPseudoElementsWithArgs = new Set([
3170
+ 'part',
3171
+ 'slotted',
3172
+ ]);
3173
+ // https://github.com/gorhill/uBlock/issues/2793
3174
+ this.normalizedOperators = new Map([
3175
+ [ '-abp-has', 'has' ],
3176
+ [ '-abp-contains', 'has-text' ],
3177
+ [ 'contains', 'has-text' ],
3178
+ [ 'nth-ancestor', 'upward' ],
3179
+ [ 'watch-attrs', 'watch-attr' ],
3180
+ ]);
3181
+ this.actionOperators = new Set([
3182
+ ':remove',
3183
+ ':style',
3184
+ ]);
3185
+ this.proceduralOperatorNames = new Set([
3186
+ 'has-text',
3187
+ 'if',
3188
+ 'if-not',
3189
+ 'matches-attr',
3190
+ 'matches-css',
3191
+ 'matches-css-after',
3192
+ 'matches-css-before',
3193
+ 'matches-media',
3194
+ 'matches-path',
3195
+ 'min-text-length',
3196
+ 'others',
3197
+ 'upward',
3198
+ 'watch-attr',
3199
+ 'xpath',
3200
+ ]);
3201
+ this.maybeProceduralOperatorNames = new Set([
3202
+ 'has',
3203
+ 'not',
3204
+ ]);
3205
+ this.proceduralActionNames = new Set([
3206
+ 'remove',
3207
+ 'remove-attr',
3208
+ 'remove-class',
3209
+ 'style',
3210
+ ]);
3211
+ this.normalizedExtendedSyntaxOperators = new Map([
3212
+ [ 'contains', 'has-text' ],
3213
+ [ 'has', 'has' ],
3214
+ ]);
3215
+ this.reIsRelativeSelector = /^\s*[+>~]/;
3216
+ this.reExtendedSyntax = /\[-(?:abp|ext)-[a-z-]+=(['"])(?:.+?)(?:\1)\]/;
3217
+ this.reExtendedSyntaxReplacer = /\[-(?:abp|ext)-([a-z-]+)=(['"])(.+?)\2\]/g;
3218
+ this.abpProceduralOpReplacer = /:-abp-(?:[a-z]+)\(/g;
3219
+ this.nativeCssHas = instanceOptions.nativeCssHas === true;
3220
+ // https://www.w3.org/TR/css-syntax-3/#typedef-ident-token
3221
+ this.reInvalidIdentifier = /^\d/;
3222
+ this.error = undefined;
3223
+ }
3224
+
3225
+ // CSSTree library holds onto last string parsed, and this is problematic
3226
+ // when the string is a slice of a huge parent string (typically a whole
3227
+ // filter list), it causes the huge parent string to stay in memory.
3228
+ // Asking CSSTree to parse an empty string resolves this issue.
3229
+ finish() {
3230
+ cssTree.parse('');
3231
+ }
3232
+
3233
+ compile(raw, out, compileOptions = {}) {
3234
+ this.asProcedural = compileOptions.asProcedural === true;
3235
+
3236
+ // https://github.com/gorhill/uBlock/issues/952
3237
+ // Find out whether we are dealing with an Adguard-specific cosmetic
3238
+ // filter, and if so, translate it if supported, or discard it if not
3239
+ // supported.
3240
+ // We have an Adguard/ABP cosmetic filter if and only if the
3241
+ // character is `$`, `%` or `?`, otherwise it's not a cosmetic
3242
+ // filter.
3243
+ // Adguard's style injection: translate to uBO's format.
3244
+ if ( compileOptions.adgStyleSyntax === true ) {
3245
+ raw = this.translateAdguardCSSInjectionFilter(raw);
3246
+ if ( raw === '' ) { return false; }
3247
+ }
3248
+
3249
+ // Normalize AdGuard's attribute-based procedural operators.
3250
+ // Normalize ABP's procedural operator names
3251
+ if ( this.asProcedural ) {
3252
+ if ( this.reExtendedSyntax.test(raw) ) {
3253
+ raw = raw.replace(this.reExtendedSyntaxReplacer, (a, a1, a2, a3) => {
3254
+ const op = this.normalizedExtendedSyntaxOperators.get(a1);
3255
+ if ( op === undefined ) { return a; }
3256
+ return `:${op}(${a3})`;
3257
+ });
3258
+ } else {
3259
+ let asProcedural = false;
3260
+ raw = raw.replace(this.abpProceduralOpReplacer, match => {
3261
+ if ( match === ':-abp-contains(' ) { return ':has-text('; }
3262
+ if ( match === ':-abp-has(' ) { return ':has('; }
3263
+ asProcedural = true;
3264
+ return match;
3265
+ });
3266
+ this.asProcedural = asProcedural;
3267
+ }
3268
+ }
3269
+
3270
+ // Relative selectors not allowed at top level.
3271
+ if ( this.reIsRelativeSelector.test(raw) ) { return false; }
3272
+
3273
+ if ( this.reCommonSelector.test(raw) ) {
3274
+ out.compiled = raw;
3275
+ return true;
3276
+ }
3277
+
3278
+ this.error = undefined;
3279
+ out.compiled = this.compileSelector(raw);
3280
+ if ( out.compiled === undefined ) {
3281
+ out.error = this.error;
3282
+ return false;
3283
+ }
3284
+
3285
+ if ( out.compiled instanceof Object ) {
3286
+ out.compiled.raw = raw;
3287
+ out.compiled = JSON.stringify(out.compiled);
3288
+ }
3289
+ return true;
3290
+ }
3291
+
3292
+ compileSelector(raw) {
3293
+ const parts = this.astFromRaw(raw, 'selectorList');
3294
+ if ( parts === undefined ) { return; }
3295
+ if ( this.astHasType(parts, 'Error') ) { return; }
3296
+ if ( this.astHasType(parts, 'Selector') === false ) { return; }
3297
+ if ( this.astIsValidSelectorList(parts) === false ) { return; }
3298
+ if (
3299
+ this.astHasType(parts, 'ProceduralSelector') === false &&
3300
+ this.astHasType(parts, 'ActionSelector') === false
3301
+ ) {
3302
+ return this.astSerialize(parts);
3303
+ }
3304
+ const r = this.astCompile(parts);
3305
+ if ( this.isCssable(r) ) {
3306
+ r.cssable = true;
3307
+ }
3308
+ return r;
3309
+ }
3310
+
3311
+ isCssable(r) {
3312
+ if ( r instanceof Object === false ) { return false; }
3313
+ if ( Array.isArray(r.action) && r.action[0] !== 'style' ) { return false; }
3314
+ if ( Array.isArray(r.tasks) === false ) { return true; }
3315
+ if ( r.tasks[0][0] === 'matches-media' ) {
3316
+ if ( r.tasks.length === 1 ) { return true; }
3317
+ if ( r.tasks.length === 2 ) {
3318
+ if ( r.selector !== '' ) { return false; }
3319
+ if ( r.tasks[1][0] === 'spath' ) { return true; }
3320
+ }
3321
+ }
3322
+ return false;
3323
+ }
3324
+
3325
+ astFromRaw(raw, type) {
3326
+ let ast;
3327
+ try {
3328
+ ast = cssTree.parse(raw, {
3329
+ context: type,
3330
+ parseValue: false,
3331
+ });
3332
+ } catch(reason) {
3333
+ const lines = [ reason.message ];
3334
+ const extra = reason.sourceFragment().split('\n');
3335
+ if ( extra.length !== 0 ) { lines.push(''); }
3336
+ const match = /^[^|]+\|/.exec(extra[0]);
3337
+ const beg = match !== null ? match[0].length : 0;
3338
+ lines.push(...extra.map(a => a.slice(beg)));
3339
+ this.error = lines.join('\n');
3340
+ return;
3341
+ }
3342
+ const parts = [];
3343
+ this.astFlatten(ast, parts);
3344
+ return parts;
3345
+ }
3346
+
3347
+ astFlatten(data, out) {
3348
+ const head = data.children && data.children.head;
3349
+ let args;
3350
+ switch ( data.type ) {
3351
+ case 'AttributeSelector':
3352
+ case 'ClassSelector':
3353
+ case 'Combinator':
3354
+ case 'IdSelector':
3355
+ case 'MediaFeature':
3356
+ case 'Nth':
3357
+ case 'Raw':
3358
+ case 'TypeSelector':
3359
+ out.push({ data });
3360
+ break;
3361
+ case 'Declaration':
3362
+ if ( data.value ) {
3363
+ this.astFlatten(data.value, args = []);
3364
+ }
3365
+ out.push({ data, args });
3366
+ args = undefined;
3367
+ break;
3368
+ case 'DeclarationList':
3369
+ case 'Identifier':
3370
+ case 'MediaQueryList':
3371
+ case 'Selector':
3372
+ case 'SelectorList':
3373
+ args = out;
3374
+ out.push({ data });
3375
+ break;
3376
+ case 'MediaQuery':
3377
+ case 'PseudoClassSelector':
3378
+ case 'PseudoElementSelector':
3379
+ if ( head ) { args = []; }
3380
+ out.push({ data, args });
3381
+ break;
3382
+ case 'Value':
3383
+ args = out;
3384
+ break;
3385
+ default:
3386
+ break;
3387
+ }
3388
+ if ( head ) {
3389
+ if ( args ) {
3390
+ this.astFlatten(head.data, args);
3391
+ }
3392
+ let next = head.next;
3393
+ while ( next ) {
3394
+ this.astFlatten(next.data, args);
3395
+ next = next.next;
3396
+ }
3397
+ }
3398
+ if ( data.type !== 'PseudoClassSelector' ) { return; }
3399
+ if ( data.name.startsWith('-abp-') && this.asProcedural === false ) {
3400
+ this.error = `${data.name} requires '#?#' separator syntax`;
3401
+ return;
3402
+ }
3403
+ // Post-analysis, mind:
3404
+ // - https://w3c.github.io/csswg-drafts/selectors-4/#has-pseudo
3405
+ // - https://w3c.github.io/csswg-drafts/selectors-4/#negation
3406
+ data.name = this.normalizedOperators.get(data.name) || data.name;
3407
+ if ( this.proceduralOperatorNames.has(data.name) ) {
3408
+ data.type = 'ProceduralSelector';
3409
+ } else if ( this.proceduralActionNames.has(data.name) ) {
3410
+ data.type = 'ActionSelector';
3411
+ } else if ( data.name.startsWith('-abp-') ) {
3412
+ data.type = 'Error';
3413
+ this.error = `${data.name} is not supported`;
3414
+ return;
3415
+ }
3416
+ if ( this.maybeProceduralOperatorNames.has(data.name) === false ) {
3417
+ return;
3418
+ }
3419
+ if ( this.astHasType(args, 'ActionSelector') ) {
3420
+ data.type = 'Error';
3421
+ this.error = 'invalid use of action operator';
3422
+ return;
3423
+ }
3424
+ if ( this.astHasType(args, 'ProceduralSelector') ) {
3425
+ data.type = 'ProceduralSelector';
3426
+ return;
3427
+ }
3428
+ switch ( data.name ) {
3429
+ case 'has':
3430
+ if (
3431
+ this.asProcedural ||
3432
+ this.nativeCssHas !== true ||
3433
+ this.astHasName(args, 'has')
3434
+ ) {
3435
+ data.type = 'ProceduralSelector';
3436
+ } else if ( this.astHasType(args, 'PseudoElementSelector') ) {
3437
+ data.type = 'Error';
3438
+ }
3439
+ break;
3440
+ case 'not': {
3441
+ if ( this.astHasType(args, 'Combinator', 0) === false ) { break; }
3442
+ if ( this.astIsValidSelectorList(args) !== true ) {
3443
+ data.type = 'Error';
3444
+ }
3445
+ break;
3446
+ }
3447
+ default:
3448
+ break;
3449
+ }
3450
+ }
3451
+
3452
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/2300
3453
+ // Unquoted attribute values are parsed as Identifier instead of String.
3454
+ astSerializePart(part) {
3455
+ const out = [];
3456
+ const { data } = part;
3457
+ switch ( data.type ) {
3458
+ case 'AttributeSelector': {
3459
+ const name = data.name.name;
3460
+ if ( this.reInvalidIdentifier.test(name) ) { return; }
3461
+ if ( data.matcher === null ) {
3462
+ out.push(`[${name}]`);
3463
+ break;
3464
+ }
3465
+ let value = data.value.value;
3466
+ if ( typeof value !== 'string' ) {
3467
+ value = data.value.name;
3468
+ }
3469
+ value = value.replace(/["\\]/g, '\\$&');
3470
+ let flags = '';
3471
+ if ( typeof data.flags === 'string' ) {
3472
+ if ( /^(is?|si?)$/.test(data.flags) === false ) { return; }
3473
+ flags = ` ${data.flags}`;
3474
+ }
3475
+ out.push(`[${name}${data.matcher}"${value}"${flags}]`);
3476
+ break;
3477
+ }
3478
+ case 'ClassSelector':
3479
+ if ( this.reInvalidIdentifier.test(data.name) ) { return; }
3480
+ out.push(`.${data.name}`);
3481
+ break;
3482
+ case 'Combinator':
3483
+ out.push(data.name);
3484
+ break;
3485
+ case 'Identifier':
3486
+ if ( this.reInvalidIdentifier.test(data.name) ) { return; }
3487
+ out.push(data.name);
3488
+ break;
3489
+ case 'IdSelector':
3490
+ if ( this.reInvalidIdentifier.test(data.name) ) { return; }
3491
+ out.push(`#${data.name}`);
3492
+ break;
3493
+ case 'Nth': {
3494
+ if ( data.selector !== null ) { return; }
3495
+ if ( data.nth.type === 'AnPlusB' ) {
3496
+ const a = parseInt(data.nth.a, 10) || null;
3497
+ const b = parseInt(data.nth.b, 10) || null;
3498
+ if ( a !== null ) {
3499
+ out.push(`${a}n`);
3500
+ if ( b === null ) { break; }
3501
+ if ( b < 0 ) {
3502
+ out.push(`${b}`);
3503
+ } else {
3504
+ out.push(`+${b}`);
3505
+ }
3506
+ } else if ( b !== null ) {
3507
+ out.push(`${b}`);
3508
+ }
3509
+ } else if ( data.nth.type === 'Identifier' ) {
3510
+ out.push(data.nth.name);
3511
+ }
3512
+ break;
3513
+ }
3514
+ case 'PseudoElementSelector': {
3515
+ const hasArgs = Array.isArray(part.args);
3516
+ if ( data.name.charCodeAt(0) !== 0x2D /* '-' */ ) {
3517
+ if ( this.knownPseudoElements.has(data.name) === false ) { return; }
3518
+ if ( this.knownPseudoElementsWithArgs.has(data.name) && hasArgs === false ) { return; }
3519
+ }
3520
+ out.push(`::${data.name}`);
3521
+ if ( hasArgs ) {
3522
+ const arg = this.astSerialize(part.args);
3523
+ if ( typeof arg !== 'string' ) { return; }
3524
+ out.push(`(${arg})`);
3525
+ }
3526
+ break;
3527
+ }
3528
+ case 'PseudoClassSelector': {
3529
+ const hasArgs = Array.isArray(part.args);
3530
+ if ( data.name.charCodeAt(0) !== 0x2D /* '-' */ ) {
3531
+ if ( this.knownPseudoClasses.has(data.name) === false ) { return; }
3532
+ if ( this.knownPseudoClassesWithArgs.has(data.name) && hasArgs === false ) { return; }
3533
+ }
3534
+ out.push(`:${data.name}`);
3535
+ if ( hasArgs ) {
3536
+ const arg = this.astSerialize(part.args);
3537
+ if ( typeof arg !== 'string' ) { return; }
3538
+ out.push(`(${arg.trim()})`);
3539
+ }
3540
+ break;
3541
+ }
3542
+ case 'Raw':
3543
+ out.push(data.value);
3544
+ break;
3545
+ case 'TypeSelector':
3546
+ if ( this.reInvalidIdentifier.test(data.name) ) { return; }
3547
+ out.push(data.name);
3548
+ break;
3549
+ default:
3550
+ break;
3551
+ }
3552
+ return out.join('');
3553
+ }
3554
+
3555
+ astSerialize(parts, plainCSS = true) {
3556
+ const out = [];
3557
+ for ( const part of parts ) {
3558
+ const { data } = part;
3559
+ switch ( data.type ) {
3560
+ case 'AttributeSelector':
3561
+ case 'ClassSelector':
3562
+ case 'Identifier':
3563
+ case 'IdSelector':
3564
+ case 'Nth':
3565
+ case 'PseudoClassSelector':
3566
+ case 'PseudoElementSelector': {
3567
+ const s = this.astSerializePart(part);
3568
+ if ( s === undefined ) { return; }
3569
+ out.push(s);
3570
+ break;
3571
+ }
3572
+ case 'Combinator': {
3573
+ const s = this.astSerializePart(part);
3574
+ if ( s === undefined ) { return; }
3575
+ if ( out.length !== 0 ) { out.push(' '); }
3576
+ if ( s !== ' ' ) { out.push(s, ' '); }
3577
+ break;
3578
+ }
3579
+ case 'TypeSelector': {
3580
+ const s = this.astSerializePart(part);
3581
+ if ( s === undefined ) { return; }
3582
+ if ( s === '*' && out.length !== 0 ) {
3583
+ const before = out[out.length-1];
3584
+ if ( before.endsWith(' ') === false ) { return; }
3585
+ }
3586
+ out.push(s);
3587
+ break;
3588
+ }
3589
+ case 'Raw':
3590
+ if ( plainCSS ) { return; }
3591
+ out.push(this.astSerializePart(part));
3592
+ break;
3593
+ case 'Selector':
3594
+ if ( out.length !== 0 ) { out.push(', '); }
3595
+ break;
3596
+ case 'SelectorList':
3597
+ break;
3598
+ default:
3599
+ return;
3600
+ }
3601
+ }
3602
+ return out.join('');
3603
+ }
3604
+
3605
+ astCompile(parts, details = {}) {
3606
+ if ( Array.isArray(parts) === false ) { return; }
3607
+ if ( parts.length === 0 ) { return; }
3608
+ if ( parts[0].data.type !== 'SelectorList' ) { return; }
3609
+ const out = { selector: '' };
3610
+ const prelude = [];
3611
+ const tasks = [];
3612
+ let startOfSelector = true;
3613
+ for ( const part of parts ) {
3614
+ if ( out.action !== undefined ) { return; }
3615
+ const { data } = part;
3616
+ switch ( data.type ) {
3617
+ case 'ActionSelector': {
3618
+ if ( details.noaction ) { return; }
3619
+ if ( prelude.length !== 0 ) {
3620
+ if ( tasks.length === 0 ) {
3621
+ out.selector = prelude.join('');
3622
+ } else {
3623
+ tasks.push(this.createSpathTask(prelude.join('')));
3624
+ }
3625
+ prelude.length = 0;
3626
+ }
3627
+ const args = this.compileArgumentAst(data.name, part.args);
3628
+ if ( args === undefined ) { return; }
3629
+ out.action = [ data.name, args ];
3630
+ break;
3631
+ }
3632
+ case 'AttributeSelector':
3633
+ case 'ClassSelector':
3634
+ case 'IdSelector':
3635
+ case 'PseudoClassSelector':
3636
+ case 'PseudoElementSelector':
3637
+ case 'TypeSelector': {
3638
+ const s = this.astSerializePart(part);
3639
+ if ( s === undefined ) { return; }
3640
+ prelude.push(s);
3641
+ startOfSelector = false;
3642
+ break;
3643
+ }
3644
+ case 'Combinator': {
3645
+ const s = this.astSerializePart(part);
3646
+ if ( s === undefined ) { return; }
3647
+ if ( startOfSelector === false || prelude.length !== 0 ) {
3648
+ prelude.push(' ');
3649
+ }
3650
+ if ( s !== ' ' ) { prelude.push(s, ' '); }
3651
+ startOfSelector = false;
3652
+ break;
3653
+ }
3654
+ case 'ProceduralSelector': {
3655
+ if ( prelude.length !== 0 ) {
3656
+ let spath = prelude.join('');
3657
+ prelude.length = 0;
3658
+ if ( spath.endsWith(' ') ) { spath += '*'; }
3659
+ if ( tasks.length === 0 ) {
3660
+ out.selector = spath;
3661
+ } else {
3662
+ tasks.push(this.createSpathTask(spath));
3663
+ }
3664
+ }
3665
+ const args = this.compileArgumentAst(data.name, part.args);
3666
+ if ( args === undefined ) { return; }
3667
+ tasks.push([ data.name, args ]);
3668
+ startOfSelector = false;
3669
+ break;
3670
+ }
3671
+ case 'Selector':
3672
+ if ( prelude.length !== 0 ) {
3673
+ prelude.push(', ');
3674
+ }
3675
+ startOfSelector = true;
3676
+ break;
3677
+ case 'SelectorList':
3678
+ startOfSelector = true;
3679
+ break;
3680
+ default:
3681
+ return;
3682
+ }
3683
+ }
3684
+ if ( tasks.length === 0 && out.action === undefined ) {
3685
+ if ( prelude.length === 0 ) { return; }
3686
+ return prelude.join('').trim();
3687
+ }
3688
+ if ( prelude.length !== 0 ) {
3689
+ tasks.push(this.createSpathTask(prelude.join('')));
3690
+ }
3691
+ if ( tasks.length !== 0 ) {
3692
+ out.tasks = tasks;
3693
+ }
3694
+ return out;
3695
+ }
3696
+
3697
+ astHasType(parts, type, depth = 0x7FFFFFFF) {
3698
+ if ( Array.isArray(parts) === false ) { return false; }
3699
+ for ( const part of parts ) {
3700
+ if ( part.data.type === type ) { return true; }
3701
+ if (
3702
+ Array.isArray(part.args) &&
3703
+ depth !== 0 &&
3704
+ this.astHasType(part.args, type, depth-1)
3705
+ ) {
3706
+ return true;
3707
+ }
3708
+ }
3709
+ return false;
3710
+ }
3711
+
3712
+ astHasName(parts, name) {
3713
+ if ( Array.isArray(parts) === false ) { return false; }
3714
+ for ( const part of parts ) {
3715
+ if ( part.data.name === name ) { return true; }
3716
+ if ( Array.isArray(part.args) && this.astHasName(part.args, name) ) {
3717
+ return true;
3718
+ }
3719
+ }
3720
+ return false;
3721
+ }
3722
+
3723
+ astSelectorsFromSelectorList(args) {
3724
+ if ( Array.isArray(args) === false ) { return; }
3725
+ if ( args.length < 3 ) { return; }
3726
+ if ( args[0].data instanceof Object === false ) { return; }
3727
+ if ( args[0].data.type !== 'SelectorList' ) { return; }
3728
+ if ( args[1].data instanceof Object === false ) { return; }
3729
+ if ( args[1].data.type !== 'Selector' ) { return; }
3730
+ const out = [];
3731
+ let beg = 1, end = 0, i = 2;
3732
+ for (;;) {
3733
+ if ( i < args.length ) {
3734
+ const type = args[i].data instanceof Object && args[i].data.type;
3735
+ if ( type === 'Selector' ) {
3736
+ end = i;
3737
+ }
3738
+ } else {
3739
+ end = args.length;
3740
+ }
3741
+ if ( end !== 0 ) {
3742
+ const components = args.slice(beg+1, end);
3743
+ if ( components.length === 0 ) { return; }
3744
+ out.push(components);
3745
+ if ( end === args.length ) { break; }
3746
+ beg = end; end = 0;
3747
+ }
3748
+ if ( i === args.length ) { break; }
3749
+ i += 1;
3750
+ }
3751
+ return out;
3752
+ }
3753
+
3754
+ astIsValidSelector(components) {
3755
+ const len = components.length;
3756
+ if ( len === 0 ) { return false; }
3757
+ if ( components[0].data.type === 'Combinator' ) { return false; }
3758
+ if ( len === 1 ) { return true; }
3759
+ if ( components[len-1].data.type === 'Combinator' ) { return false; }
3760
+ return true;
3761
+ }
3762
+
3763
+ astIsValidSelectorList(args) {
3764
+ const selectors = this.astSelectorsFromSelectorList(args);
3765
+ if ( Array.isArray(selectors) === false || selectors.length === 0 ) {
3766
+ return false;
3767
+ }
3768
+ for ( const selector of selectors ) {
3769
+ if ( this.astIsValidSelector(selector) !== true ) { return false; }
3770
+ }
3771
+ return true;
3772
+ }
3773
+
3774
+ translateAdguardCSSInjectionFilter(suffix) {
3775
+ const matches = /^(.*)\s*\{([^}]+)\}\s*$/.exec(suffix);
3776
+ if ( matches === null ) { return ''; }
3777
+ const selector = matches[1].trim();
3778
+ const style = matches[2].trim();
3779
+ // Special style directive `remove: true` is converted into a
3780
+ // `:remove()` operator.
3781
+ if ( /^\s*remove:\s*true[; ]*$/.test(style) ) {
3782
+ return `${selector}:remove()`;
3783
+ }
3784
+ // For some reasons, many of Adguard's plain cosmetic filters are
3785
+ // "disguised" as style-based cosmetic filters: convert such filters
3786
+ // to plain cosmetic filters.
3787
+ return /display\s*:\s*none\s*!important;?$/.test(style)
3788
+ ? selector
3789
+ : `${selector}:style(${style})`;
3790
+ }
3791
+
3792
+ createSpathTask(selector) {
3793
+ return [ 'spath', selector ];
3794
+ }
3795
+
3796
+ compileArgumentAst(operator, parts) {
3797
+ switch ( operator ) {
3798
+ case 'has': {
3799
+ let r = this.astCompile(parts, { noaction: true });
3800
+ if ( typeof r === 'string' ) {
3801
+ r = { selector: r.replace(/^\s*:scope\s*/, '') };
3802
+ }
3803
+ return r;
3804
+ }
3805
+ case 'not': {
3806
+ return this.astCompile(parts, { noaction: true });
3807
+ }
3808
+ default:
3809
+ break;
3810
+ }
3811
+ if ( Array.isArray(parts) === false || parts.length === 0 ) { return; }
3812
+ const arg = this.astSerialize(parts, false);
3813
+ if ( arg === undefined ) { return; }
3814
+ switch ( operator ) {
3815
+ case 'has-text':
3816
+ return this.compileText(arg);
3817
+ case 'if':
3818
+ return this.compileSelector(arg);
3819
+ case 'if-not':
3820
+ return this.compileSelector(arg);
3821
+ case 'matches-attr':
3822
+ return this.compileMatchAttrArgument(arg);
3823
+ case 'matches-css':
3824
+ return this.compileCSSDeclaration(arg);
3825
+ case 'matches-css-after':
3826
+ return this.compileCSSDeclaration(`after, ${arg}`);
3827
+ case 'matches-css-before':
3828
+ return this.compileCSSDeclaration(`before, ${arg}`);
3829
+ case 'matches-media':
3830
+ return this.compileMediaQuery(arg);
3831
+ case 'matches-path':
3832
+ return this.compileText(arg);
3833
+ case 'min-text-length':
3834
+ return this.compileInteger(arg);
3835
+ case 'others':
3836
+ return this.compileNoArgument(arg);
3837
+ case 'remove':
3838
+ return this.compileNoArgument(arg);
3839
+ case 'remove-attr':
3840
+ return this.compileText(arg);
3841
+ case 'remove-class':
3842
+ return this.compileText(arg);
3843
+ case 'style':
3844
+ return this.compileStyleProperties(arg);
3845
+ case 'upward':
3846
+ return this.compileUpwardArgument(arg);
3847
+ case 'watch-attr':
3848
+ return this.compileAttrList(arg);
3849
+ case 'xpath':
3850
+ return this.compileXpathExpression(arg);
3851
+ default:
3852
+ break;
3853
+ }
3854
+ }
3855
+
3856
+ isBadRegex(s) {
3857
+ try {
3858
+ void new RegExp(s);
3859
+ } catch (ex) {
3860
+ this.isBadRegex.message = ex.toString();
3861
+ return true;
3862
+ }
3863
+ return false;
3864
+ }
3865
+
3866
+ unquoteString(s) {
3867
+ const end = s.length;
3868
+ if ( end === 0 ) {
3869
+ return { s: '', end };
3870
+ }
3871
+ if ( /^['"]/.test(s) === false ) {
3872
+ return { s, i: end };
3873
+ }
3874
+ const quote = s.charCodeAt(0);
3875
+ const out = [];
3876
+ let i = 1, c = 0;
3877
+ for (;;) {
3878
+ c = s.charCodeAt(i);
3879
+ if ( c === quote ) {
3880
+ i += 1;
3881
+ break;
3882
+ }
3883
+ if ( c === 0x5C /* '\\' */ ) {
3884
+ i += 1;
3885
+ if ( i === end ) { break; }
3886
+ c = s.charCodeAt(i);
3887
+ if ( c !== 0x5C && c !== quote ) {
3888
+ out.push(0x5C);
3889
+ }
3890
+ }
3891
+ out.push(c);
3892
+ i += 1;
3893
+ if ( i === end ) { break; }
3894
+ }
3895
+ return { s: String.fromCharCode(...out), i };
3896
+ }
3897
+
3898
+ compileMatchAttrArgument(s) {
3899
+ if ( s === '' ) { return; }
3900
+ let attr = '', value = '';
3901
+ let r = this.unquoteString(s);
3902
+ if ( r.i === s.length ) {
3903
+ const pos = r.s.indexOf('=');
3904
+ if ( pos === -1 ) {
3905
+ attr = r.s;
3906
+ } else {
3907
+ attr = r.s.slice(0, pos);
3908
+ value = r.s.slice(pos+1);
3909
+ }
3910
+ } else {
3911
+ attr = r.s;
3912
+ if ( s.charCodeAt(r.i) !== 0x3D ) { return; }
3913
+ value = s.slice(r.i+1);
3914
+ }
3915
+ if ( attr === '' ) { return; }
3916
+ if ( value.length !== 0 ) {
3917
+ r = this.unquoteString(value);
3918
+ if ( r.i !== value.length ) { return; }
3919
+ value = r.s;
3920
+ }
3921
+ return { attr, value };
3922
+ }
3923
+
3924
+ // Remove potentially present quotes before processing.
3925
+ compileText(s) {
3926
+ if ( s === '' ) {
3927
+ this.error = 'argument missing';
3928
+ return;
3929
+ }
3930
+ const r = this.unquoteString(s);
3931
+ if ( r.i !== s.length ) { return; }
3932
+ return r.s;
3933
+ }
3934
+
3935
+ compileCSSDeclaration(s) {
3936
+ let pseudo; {
3937
+ const match = /^[a-z-]+,/.exec(s);
3938
+ if ( match !== null ) {
3939
+ pseudo = match[0].slice(0, -1);
3940
+ s = s.slice(match[0].length).trim();
3941
+ }
3942
+ }
3943
+ const pos = s.indexOf(':');
3944
+ if ( pos === -1 ) { return; }
3945
+ const name = s.slice(0, pos).trim();
3946
+ const value = s.slice(pos + 1).trim();
3947
+ const match = this.reParseRegexLiteral.exec(value);
3948
+ let regexDetails;
3949
+ if ( match !== null ) {
3950
+ regexDetails = match[1];
3951
+ if ( this.isBadRegex(regexDetails) ) { return; }
3952
+ if ( match[2] ) {
3953
+ regexDetails = [ regexDetails, match[2] ];
3954
+ }
3955
+ } else {
3956
+ regexDetails = '^' + value.replace(this.reEscapeRegex, '\\$&') + '$';
3957
+ }
3958
+ return { name, pseudo, value: regexDetails };
3959
+ }
3960
+
3961
+ compileInteger(s, min = 0, max = 0x7FFFFFFF) {
3962
+ if ( /^\d+$/.test(s) === false ) { return; }
3963
+ const n = parseInt(s, 10);
3964
+ if ( n < min || n >= max ) { return; }
3965
+ return n;
3966
+ }
3967
+
3968
+ compileMediaQuery(s) {
3969
+ const parts = this.astFromRaw(s, 'mediaQueryList');
3970
+ if ( parts === undefined ) { return; }
3971
+ if ( this.astHasType(parts, 'Raw') ) { return; }
3972
+ if ( this.astHasType(parts, 'MediaQuery') === false ) { return; }
3973
+ // TODO: normalize by serializing resulting AST
3974
+ return s;
3975
+ }
3976
+
3977
+ compileUpwardArgument(s) {
3978
+ const i = this.compileInteger(s, 1, 256);
3979
+ if ( i !== undefined ) { return i; }
3980
+ const parts = this.astFromRaw(s, 'selectorList' );
3981
+ if ( this.astIsValidSelectorList(parts) !== true ) { return; }
3982
+ if ( this.astHasType(parts, 'ProceduralSelector') ) { return; }
3983
+ if ( this.astHasType(parts, 'ActionSelector') ) { return; }
3984
+ if ( this.astHasType(parts, 'Error') ) { return; }
3985
+ return s;
3986
+ }
3987
+
3988
+ compileNoArgument(s) {
3989
+ if ( s === '' ) { return s; }
3990
+ }
3991
+
3992
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/668
3993
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/1693
3994
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/1811
3995
+ // Forbid instances of:
3996
+ // - `image-set(`
3997
+ // - `url(`
3998
+ // - any instance of `//`
3999
+ // - backslashes `\`
4000
+ // - opening comment `/*`
4001
+ compileStyleProperties(s) {
4002
+ if ( /image-set\(|url\(|\/\s*\/|\\|\/\*/i.test(s) ) { return; }
4003
+ const parts = this.astFromRaw(s, 'declarationList');
4004
+ if ( parts === undefined ) { return; }
4005
+ if ( this.astHasType(parts, 'Declaration') === false ) { return; }
4006
+ return s;
4007
+ }
4008
+
4009
+ compileAttrList(s) {
4010
+ if ( s === '' ) { return s; }
4011
+ const attrs = s.split('\s*,\s*');
4012
+ const out = [];
4013
+ for ( const attr of attrs ) {
4014
+ if ( attr !== '' ) {
4015
+ out.push(attr);
4016
+ }
4017
+ }
4018
+ return out;
4019
+ }
4020
+
4021
+ compileXpathExpression(s) {
4022
+ const r = this.unquoteString(s);
4023
+ if ( r.i !== s.length ) { return; }
4024
+ try {
4025
+ globalThis.document.createExpression(r.s, null);
4026
+ } catch (e) {
4027
+ return;
4028
+ }
4029
+ return r.s;
4030
+ }
4031
+ }
4032
+
4033
+ // bit 0: can be used as auto-completion hint
4034
+ // bit 1: can not be used in HTML filtering
4035
+ //
4036
+ export const proceduralOperatorTokens = new Map([
4037
+ [ '-abp-contains', 0b00 ],
4038
+ [ '-abp-has', 0b00, ],
4039
+ [ 'contains', 0b00, ],
4040
+ [ 'has', 0b01 ],
4041
+ [ 'has-text', 0b01 ],
4042
+ [ 'if', 0b00 ],
4043
+ [ 'if-not', 0b00 ],
4044
+ [ 'matches-attr', 0b11 ],
4045
+ [ 'matches-css', 0b11 ],
4046
+ [ 'matches-media', 0b11 ],
4047
+ [ 'matches-path', 0b11 ],
4048
+ [ 'min-text-length', 0b01 ],
4049
+ [ 'not', 0b01 ],
4050
+ [ 'nth-ancestor', 0b00 ],
4051
+ [ 'others', 0b11 ],
4052
+ [ 'remove', 0b11 ],
4053
+ [ 'remove-attr', 0b11 ],
4054
+ [ 'remove-class', 0b11 ],
4055
+ [ 'style', 0b11 ],
4056
+ [ 'upward', 0b01 ],
4057
+ [ 'watch-attr', 0b11 ],
4058
+ [ 'watch-attrs', 0b00 ],
4059
+ [ 'xpath', 0b01 ],
4060
+ ]);
4061
+
4062
+ /******************************************************************************/
4063
+
4064
+ export const utils = (( ) => {
4065
+
4066
+ // Depends on:
4067
+ // https://github.com/foo123/RegexAnalyzer
4068
+ const regexAnalyzer = Regex && Regex.Analyzer || null;
4069
+
4070
+ class regex {
4071
+ static firstCharCodeClass(s) {
4072
+ return /^[\x01\x03%0-9A-Za-z]/.test(s) ? 1 : 0;
4073
+ }
4074
+
4075
+ static lastCharCodeClass(s) {
4076
+ return /[\x01\x03%0-9A-Za-z]$/.test(s) ? 1 : 0;
4077
+ }
4078
+
4079
+ static tokenizableStrFromNode(node) {
4080
+ switch ( node.type ) {
4081
+ case 1: /* T_SEQUENCE, 'Sequence' */ {
4082
+ let s = '';
4083
+ for ( let i = 0; i < node.val.length; i++ ) {
4084
+ s += this.tokenizableStrFromNode(node.val[i]);
4085
+ }
4086
+ return s;
4087
+ }
4088
+ case 2: /* T_ALTERNATION, 'Alternation' */
4089
+ case 8: /* T_CHARGROUP, 'CharacterGroup' */ {
4090
+ if ( node.flags.NegativeMatch ) { return '\x01'; }
4091
+ let firstChar = 0;
4092
+ let lastChar = 0;
4093
+ for ( let i = 0; i < node.val.length; i++ ) {
4094
+ const s = this.tokenizableStrFromNode(node.val[i]);
4095
+ if ( firstChar === 0 && this.firstCharCodeClass(s) === 1 ) {
4096
+ firstChar = 1;
4097
+ }
4098
+ if ( lastChar === 0 && this.lastCharCodeClass(s) === 1 ) {
4099
+ lastChar = 1;
4100
+ }
4101
+ if ( firstChar === 1 && lastChar === 1 ) { break; }
4102
+ }
4103
+ return String.fromCharCode(firstChar, lastChar);
4104
+ }
4105
+ case 4: /* T_GROUP, 'Group' */ {
4106
+ if (
4107
+ node.flags.NegativeLookAhead === 1 ||
4108
+ node.flags.NegativeLookBehind === 1
4109
+ ) {
4110
+ return '';
4111
+ }
4112
+ return this.tokenizableStrFromNode(node.val);
4113
+ }
4114
+ case 16: /* T_QUANTIFIER, 'Quantifier' */ {
4115
+ if ( node.flags.max === 0 ) { return ''; }
4116
+ const s = this.tokenizableStrFromNode(node.val);
4117
+ const first = this.firstCharCodeClass(s);
4118
+ const last = this.lastCharCodeClass(s);
4119
+ if ( node.flags.min !== 0 ) {
4120
+ return String.fromCharCode(first, last);
4121
+ }
4122
+ return String.fromCharCode(first+2, last+2);
4123
+ }
4124
+ case 64: /* T_HEXCHAR, 'HexChar' */ {
4125
+ if (
4126
+ node.flags.Code === '01' ||
4127
+ node.flags.Code === '02' ||
4128
+ node.flags.Code === '03'
4129
+ ) {
4130
+ return '\x00';
4131
+ }
4132
+ return node.flags.Char;
4133
+ }
4134
+ case 128: /* T_SPECIAL, 'Special' */ {
4135
+ const flags = node.flags;
4136
+ if (
4137
+ flags.EndCharGroup === 1 || // dangling `]`
4138
+ flags.EndGroup === 1 || // dangling `)`
4139
+ flags.EndRepeats === 1 // dangling `}`
4140
+ ) {
4141
+ throw new Error('Unmatched bracket');
4142
+ }
4143
+ return flags.MatchEnd === 1 ||
4144
+ flags.MatchStart === 1 ||
4145
+ flags.MatchWordBoundary === 1
4146
+ ? '\x00'
4147
+ : '\x01';
4148
+ }
4149
+ case 256: /* T_CHARS, 'Characters' */ {
4150
+ for ( let i = 0; i < node.val.length; i++ ) {
4151
+ if ( this.firstCharCodeClass(node.val[i]) === 1 ) {
4152
+ return '\x01';
4153
+ }
4154
+ }
4155
+ return '\x00';
4156
+ }
4157
+ // Ranges are assumed to always involve token-related characters.
4158
+ case 512: /* T_CHARRANGE, 'CharacterRange' */ {
4159
+ return '\x01';
4160
+ }
4161
+ case 1024: /* T_STRING, 'String' */ {
4162
+ return node.val;
4163
+ }
4164
+ case 2048: /* T_COMMENT, 'Comment' */ {
4165
+ return '';
4166
+ }
4167
+ default:
4168
+ break;
4169
+ }
4170
+ return '\x01';
4171
+ }
4172
+
4173
+ static isValid(reStr) {
4174
+ try {
4175
+ void new RegExp(reStr);
4176
+ if ( regexAnalyzer !== null ) {
4177
+ void this.tokenizableStrFromNode(
4178
+ regexAnalyzer(reStr, false).tree()
4179
+ );
4180
+ }
4181
+ } catch(ex) {
4182
+ return false;
4183
+ }
4184
+ return true;
4185
+ }
4186
+
4187
+ static isRE2(reStr) {
4188
+ if ( regexAnalyzer === null ) { return true; }
4189
+ let tree;
4190
+ try {
4191
+ tree = regexAnalyzer(reStr, false).tree();
4192
+ } catch(ex) {
4193
+ return;
4194
+ }
4195
+ const isRE2 = node => {
4196
+ if ( node instanceof Object === false ) { return true; }
4197
+ if ( node.flags instanceof Object ) {
4198
+ if ( node.flags.LookAhead === 1 ) { return false; }
4199
+ if ( node.flags.NegativeLookAhead === 1 ) { return false; }
4200
+ if ( node.flags.LookBehind === 1 ) { return false; }
4201
+ if ( node.flags.NegativeLookBehind === 1 ) { return false; }
4202
+ }
4203
+ if ( Array.isArray(node.val) ) {
4204
+ for ( const entry of node.val ) {
4205
+ if ( isRE2(entry) === false ) { return false; }
4206
+ }
4207
+ }
4208
+ if ( node.val instanceof Object ) {
4209
+ return isRE2(node.val);
4210
+ }
4211
+ return true;
4212
+ };
4213
+ return isRE2(tree);
4214
+ }
4215
+
4216
+ static toTokenizableStr(reStr) {
4217
+ if ( regexAnalyzer === null ) { return ''; }
4218
+ let s = '';
4219
+ try {
4220
+ s = this.tokenizableStrFromNode(
4221
+ regexAnalyzer(reStr, false).tree()
4222
+ );
4223
+ } catch(ex) {
4224
+ }
4225
+ // Process optional sequences
4226
+ const reOptional = /[\x02\x03]+/;
4227
+ for (;;) {
4228
+ const match = reOptional.exec(s);
4229
+ if ( match === null ) { break; }
4230
+ const left = s.slice(0, match.index);
4231
+ const middle = match[0];
4232
+ const right = s.slice(match.index + middle.length);
4233
+ s = left;
4234
+ s += this.firstCharCodeClass(right) === 1 ||
4235
+ this.firstCharCodeClass(middle) === 1
4236
+ ? '\x01'
4237
+ : '\x00';
4238
+ s += this.lastCharCodeClass(left) === 1 ||
4239
+ this.lastCharCodeClass(middle) === 1
4240
+ ? '\x01'
4241
+ : '\x00';
4242
+ s += right;
4243
+ }
4244
+ return s;
4245
+ }
4246
+ }
4247
+
4248
+ const preparserTokens = new Map([
4249
+ [ 'ext_ublock', 'ublock' ],
4250
+ [ 'ext_ubol', 'ubol' ],
4251
+ [ 'ext_devbuild', 'devbuild' ],
4252
+ [ 'env_chromium', 'chromium' ],
4253
+ [ 'env_edge', 'edge' ],
4254
+ [ 'env_firefox', 'firefox' ],
4255
+ [ 'env_legacy', 'legacy' ],
4256
+ [ 'env_mobile', 'mobile' ],
4257
+ [ 'env_mv3', 'mv3' ],
4258
+ [ 'env_safari', 'safari' ],
4259
+ [ 'cap_html_filtering', 'html_filtering' ],
4260
+ [ 'cap_user_stylesheet', 'user_stylesheet' ],
4261
+ [ 'false', 'false' ],
4262
+ // Hoping ABP-only list maintainers can at least make use of it to
4263
+ // help non-ABP content blockers better deal with filters benefiting
4264
+ // only ABP.
4265
+ [ 'ext_abp', 'false' ],
4266
+ // Compatibility with other blockers
4267
+ // https://kb.adguard.com/en/general/how-to-create-your-own-ad-filters#adguard-specific
4268
+ [ 'adguard', 'adguard' ],
4269
+ [ 'adguard_app_android', 'false' ],
4270
+ [ 'adguard_app_ios', 'false' ],
4271
+ [ 'adguard_app_mac', 'false' ],
4272
+ [ 'adguard_app_windows', 'false' ],
4273
+ [ 'adguard_ext_android_cb', 'false' ],
4274
+ [ 'adguard_ext_chromium', 'chromium' ],
4275
+ [ 'adguard_ext_edge', 'edge' ],
4276
+ [ 'adguard_ext_firefox', 'firefox' ],
4277
+ [ 'adguard_ext_opera', 'chromium' ],
4278
+ [ 'adguard_ext_safari', 'false' ],
4279
+ ]);
4280
+
4281
+ const toURL = url => {
4282
+ try {
4283
+ return new URL(url.trim());
4284
+ } catch (ex) {
4285
+ }
4286
+ };
4287
+
4288
+ // Useful reference:
4289
+ // https://adguard.com/kb/general/ad-filtering/create-own-filters/#conditions-directive
4290
+
4291
+ class preparser {
4292
+ static evaluateExprToken(token, env = []) {
4293
+ const not = token.charCodeAt(0) === 0x21 /* ! */;
4294
+ if ( not ) { token = token.slice(1); }
4295
+ const state = preparserTokens.get(token);
4296
+ if ( state === undefined ) { return; }
4297
+ return state === 'false' && not || env.includes(state) !== not;
4298
+ }
4299
+
4300
+ static evaluateExpr(expr, env = []) {
4301
+ if ( expr.startsWith('(') && expr.endsWith(')') ) {
4302
+ expr = expr.slice(1, -1);
4303
+ }
4304
+ const matches = Array.from(expr.matchAll(/(?:(?:&&|\|\|)\s+)?\S+/g));
4305
+ if ( matches.length === 0 ) { return; }
4306
+ if ( matches[0][0].startsWith('|') || matches[0][0].startsWith('&') ) { return; }
4307
+ let result = this.evaluateExprToken(matches[0][0], env);
4308
+ for ( let i = 1; i < matches.length; i++ ) {
4309
+ const parts = matches[i][0].split(/ +/);
4310
+ if ( parts.length !== 2 ) { return; }
4311
+ const state = this.evaluateExprToken(parts[1], env);
4312
+ if ( state === undefined ) { return; }
4313
+ if ( parts[0] === '||' ) {
4314
+ result = result || state;
4315
+ } else if ( parts[0] === '&&' ) {
4316
+ result = result && state;
4317
+ } else {
4318
+ return;
4319
+ }
4320
+ }
4321
+ return result;
4322
+ }
4323
+
4324
+ // This method returns an array of indices, corresponding to position in
4325
+ // the content string which should alternatively be parsed and discarded.
4326
+ static splitter(content, env = []) {
4327
+ const reIf = /^!#(if|else|endif)\b([^\n]*)(?:[\n\r]+|$)/gm;
4328
+ const stack = [];
4329
+ const parts = [ 0 ];
4330
+ let discard = false;
4331
+
4332
+ const shouldDiscard = ( ) => stack.some(v => v);
4333
+
4334
+ const begif = (startDiscard, match) => {
4335
+ if ( discard === false && startDiscard ) {
4336
+ parts.push(match.index);
4337
+ discard = true;
4338
+ }
4339
+ stack.push(startDiscard);
4340
+ };
4341
+
4342
+ const endif = match => {
4343
+ stack.pop();
4344
+ const stopDiscard = shouldDiscard() === false;
4345
+ if ( discard && stopDiscard ) {
4346
+ parts.push(match.index + match[0].length);
4347
+ discard = false;
4348
+ }
4349
+ };
4350
+
4351
+ for (;;) {
4352
+ const match = reIf.exec(content);
4353
+ if ( match === null ) { break; }
4354
+
4355
+ switch ( match[1] ) {
4356
+ case 'if': {
4357
+ const startDiscard = this.evaluateExpr(match[2].trim(), env) === false;
4358
+ begif(startDiscard, match);
4359
+ break;
4360
+ }
4361
+ case 'else': {
4362
+ if ( stack.length === 0 ) { break; }
4363
+ const startDiscard = stack[stack.length-1] === false;
4364
+ endif(match);
4365
+ begif(startDiscard, match);
4366
+ break;
4367
+ }
4368
+ case 'endif': {
4369
+ endif(match);
4370
+ break;
4371
+ }
4372
+ default:
4373
+ break;
4374
+ }
4375
+ }
4376
+
4377
+ parts.push(content.length);
4378
+ return parts;
4379
+ }
4380
+
4381
+ static expandIncludes(parts, env = []) {
4382
+ const out = [];
4383
+ const reInclude = /^!#include +(\S+)[^\n\r]*(?:[\n\r]+|$)/gm;
4384
+ for ( const part of parts ) {
4385
+ if ( typeof part === 'string' ) {
4386
+ out.push(part);
4387
+ continue;
4388
+ }
4389
+ if ( part instanceof Object === false ) { continue; }
4390
+ const content = part.content;
4391
+ const slices = this.splitter(content, env);
4392
+ for ( let i = 0, n = slices.length - 1; i < n; i++ ) {
4393
+ const slice = content.slice(slices[i+0], slices[i+1]);
4394
+ if ( (i & 1) !== 0 ) {
4395
+ out.push(slice);
4396
+ continue;
4397
+ }
4398
+ let lastIndex = 0;
4399
+ for (;;) {
4400
+ const match = reInclude.exec(slice);
4401
+ if ( match === null ) { break; }
4402
+ if ( toURL(match[1]) !== undefined ) { continue; }
4403
+ if ( match[1].indexOf('..') !== -1 ) { continue; }
4404
+ // Compute nested list path relative to parent list path
4405
+ const pos = part.url.lastIndexOf('/');
4406
+ if ( pos === -1 ) { continue; }
4407
+ const subURL = part.url.slice(0, pos + 1) + match[1].trim();
4408
+ out.push(
4409
+ slice.slice(lastIndex, match.index + match[0].length),
4410
+ `! >>>>>>>> ${subURL}\n`,
4411
+ { url: subURL },
4412
+ `! <<<<<<<< ${subURL}\n`
4413
+ );
4414
+ lastIndex = reInclude.lastIndex;
4415
+ }
4416
+ out.push(lastIndex === 0 ? slice : slice.slice(lastIndex));
4417
+ }
4418
+ }
4419
+ return out;
4420
+ }
4421
+
4422
+ static prune(content, env) {
4423
+ const parts = this.splitter(content, env);
4424
+ const out = [];
4425
+ for ( let i = 0, n = parts.length - 1; i < n; i += 2 ) {
4426
+ const beg = parts[i+0];
4427
+ const end = parts[i+1];
4428
+ out.push(content.slice(beg, end));
4429
+ }
4430
+ return out.join('\n');
4431
+ }
4432
+
4433
+ static getHints() {
4434
+ const out = [];
4435
+ const vals = new Set();
4436
+ for ( const [ key, val ] of preparserTokens ) {
4437
+ if ( vals.has(val) ) { continue; }
4438
+ vals.add(val);
4439
+ out.push(key);
4440
+ }
4441
+ return out;
4442
+ }
4443
+
4444
+ static getTokens(env) {
4445
+ const out = new Map();
4446
+ for ( const [ key, val ] of preparserTokens ) {
4447
+ out.set(key, val !== 'false' && env.includes(val));
4448
+ }
4449
+ return Array.from(out);
4450
+ }
4451
+ }
4452
+
4453
+ return {
4454
+ preparser,
4455
+ regex,
4456
+ };
4457
+ })();
4458
+
4459
+ /******************************************************************************/