@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.
- package/CHANGELOG.md +674 -0
- package/LICENSE +6 -0
- package/README.md +132 -0
- package/assets/logo.png +0 -0
- package/bin/browserless.js +227 -0
- package/browser.json +7 -0
- package/build/browserless.d.ts +33 -0
- package/build/browserless.js +146 -0
- package/build/browsers/cdp-chromium.d.ts +41 -0
- package/build/browsers/cdp-chromium.js +287 -0
- package/build/browsers/index.d.ts +26 -0
- package/build/browsers/index.js +183 -0
- package/build/browsers/playwright-chromium.d.ts +34 -0
- package/build/browsers/playwright-chromium.js +106 -0
- package/build/browsers/playwright-firefox.d.ts +34 -0
- package/build/browsers/playwright-firefox.js +101 -0
- package/build/browsers/playwright-webkit.d.ts +34 -0
- package/build/browsers/playwright-webkit.js +101 -0
- package/build/config.d.ts +138 -0
- package/build/config.js +349 -0
- package/build/constants.d.ts +4 -0
- package/build/constants.js +4 -0
- package/build/data/classes.json +1 -0
- package/build/data/selectors.json +1 -0
- package/build/exports.d.ts +20 -0
- package/build/exports.js +22 -0
- package/build/file-system.d.ts +24 -0
- package/build/file-system.js +46 -0
- package/build/hooks.d.ts +5 -0
- package/build/hooks.js +20 -0
- package/build/http.d.ts +175 -0
- package/build/http.js +104 -0
- package/build/index.d.ts +1 -0
- package/build/index.js +39 -0
- package/build/limiter.d.ts +24 -0
- package/build/limiter.js +147 -0
- package/build/limiter.spec.d.ts +1 -0
- package/build/limiter.spec.js +241 -0
- package/build/metrics.d.ts +24 -0
- package/build/metrics.js +86 -0
- package/build/metrics.spec.d.ts +1 -0
- package/build/metrics.spec.js +35 -0
- package/build/mime-types.d.ts +1 -0
- package/build/mime-types.js +328 -0
- package/build/monitoring.d.ts +13 -0
- package/build/monitoring.js +38 -0
- package/build/routes/chromium/http/content-post.body.json +514 -0
- package/build/routes/chromium/http/content-post.d.ts +34 -0
- package/build/routes/chromium/http/content-post.js +109 -0
- package/build/routes/chromium/http/content-post.query.json +183 -0
- package/build/routes/chromium/http/content-post.response.json +5 -0
- package/build/routes/chromium/http/download-post.body.json +32 -0
- package/build/routes/chromium/http/download-post.d.ts +16 -0
- package/build/routes/chromium/http/download-post.js +92 -0
- package/build/routes/chromium/http/download-post.query.json +120 -0
- package/build/routes/chromium/http/download-post.response.json +4 -0
- package/build/routes/chromium/http/function-post.body.json +32 -0
- package/build/routes/chromium/http/function-post.d.ts +18 -0
- package/build/routes/chromium/http/function-post.js +53 -0
- package/build/routes/chromium/http/function-post.query.json +120 -0
- package/build/routes/chromium/http/function-post.response.json +4 -0
- package/build/routes/chromium/http/pdf-post.body.json +654 -0
- package/build/routes/chromium/http/pdf-post.d.ts +35 -0
- package/build/routes/chromium/http/pdf-post.js +107 -0
- package/build/routes/chromium/http/pdf-post.query.json +120 -0
- package/build/routes/chromium/http/pdf-post.response.json +5 -0
- package/build/routes/chromium/http/performance.body.json +26 -0
- package/build/routes/chromium/http/performance.d.ts +17 -0
- package/build/routes/chromium/http/performance.js +30 -0
- package/build/routes/chromium/http/performance.query.json +120 -0
- package/build/routes/chromium/http/performance.response.json +7 -0
- package/build/routes/chromium/http/scrape-post.body.json +561 -0
- package/build/routes/chromium/http/scrape-post.d.ts +106 -0
- package/build/routes/chromium/http/scrape-post.js +205 -0
- package/build/routes/chromium/http/scrape-post.query.json +183 -0
- package/build/routes/chromium/http/scrape-post.response.json +325 -0
- package/build/routes/chromium/http/screenshot-post.body.json +604 -0
- package/build/routes/chromium/http/screenshot-post.d.ts +37 -0
- package/build/routes/chromium/http/screenshot-post.js +124 -0
- package/build/routes/chromium/http/screenshot-post.query.json +120 -0
- package/build/routes/chromium/http/screenshot-post.response.json +5 -0
- package/build/routes/chromium/tests/content.spec.d.ts +1 -0
- package/build/routes/chromium/tests/content.spec.js +285 -0
- package/build/routes/chromium/tests/download.spec.d.ts +1 -0
- package/build/routes/chromium/tests/download.spec.js +67 -0
- package/build/routes/chromium/tests/function.spec.d.ts +1 -0
- package/build/routes/chromium/tests/function.spec.js +245 -0
- package/build/routes/chromium/tests/pdf.spec.d.ts +1 -0
- package/build/routes/chromium/tests/pdf.spec.js +333 -0
- package/build/routes/chromium/tests/performance.spec.d.ts +1 -0
- package/build/routes/chromium/tests/performance.spec.js +124 -0
- package/build/routes/chromium/tests/scrape.spec.d.ts +1 -0
- package/build/routes/chromium/tests/scrape.spec.js +354 -0
- package/build/routes/chromium/tests/screenshot.spec.d.ts +1 -0
- package/build/routes/chromium/tests/screenshot.spec.js +339 -0
- package/build/routes/chromium/tests/websocket.spec.d.ts +1 -0
- package/build/routes/chromium/tests/websocket.spec.js +309 -0
- package/build/routes/chromium/utils/function/client.d.ts +26 -0
- package/build/routes/chromium/utils/function/client.js +66 -0
- package/build/routes/chromium/utils/function/handler.d.ts +18 -0
- package/build/routes/chromium/utils/function/handler.js +95 -0
- package/build/routes/chromium/utils/performance/child.d.ts +1 -0
- package/build/routes/chromium/utils/performance/child.js +29 -0
- package/build/routes/chromium/utils/performance/main.d.ts +3 -0
- package/build/routes/chromium/utils/performance/main.js +65 -0
- package/build/routes/chromium/utils/performance/types.d.ts +21 -0
- package/build/routes/chromium/utils/performance/types.js +1 -0
- package/build/routes/chromium/ws/browser.d.ts +6 -0
- package/build/routes/chromium/ws/browser.js +11 -0
- package/build/routes/chromium/ws/browser.query.json +120 -0
- package/build/routes/chromium/ws/cdp-chromium.d.ts +6 -0
- package/build/routes/chromium/ws/cdp-chromium.js +11 -0
- package/build/routes/chromium/ws/cdp-chromium.query.json +120 -0
- package/build/routes/chromium/ws/page.d.ts +6 -0
- package/build/routes/chromium/ws/page.js +11 -0
- package/build/routes/chromium/ws/page.query.json +120 -0
- package/build/routes/chromium/ws/playwright-chromium.d.ts +6 -0
- package/build/routes/chromium/ws/playwright-chromium.js +19 -0
- package/build/routes/chromium/ws/playwright-chromium.query.json +100 -0
- package/build/routes/firefox/tests/websocket.spec.d.ts +1 -0
- package/build/routes/firefox/tests/websocket.spec.js +104 -0
- package/build/routes/firefox/ws/playwright-firefox.d.ts +6 -0
- package/build/routes/firefox/ws/playwright-firefox.js +19 -0
- package/build/routes/firefox/ws/playwright-firefox.query.json +100 -0
- package/build/routes/management/http/config-get.d.ts +25 -0
- package/build/routes/management/http/config-get.js +43 -0
- package/build/routes/management/http/config-get.response.json +107 -0
- package/build/routes/management/http/metrics-get.d.ts +4 -0
- package/build/routes/management/http/metrics-get.js +24 -0
- package/build/routes/management/http/metrics-get.response.json +94 -0
- package/build/routes/management/http/metrics-total-get.d.ts +4 -0
- package/build/routes/management/http/metrics-total-get.js +60 -0
- package/build/routes/management/http/metrics-total-get.response.json +72 -0
- package/build/routes/management/http/sessions-get.d.ts +4 -0
- package/build/routes/management/http/sessions-get.js +21 -0
- package/build/routes/management/http/sessions-get.response.json +221 -0
- package/build/routes/management/http/static-get.d.ts +3 -0
- package/build/routes/management/http/static-get.js +67 -0
- package/build/routes/management/tests/management.spec.d.ts +1 -0
- package/build/routes/management/tests/management.spec.js +41 -0
- package/build/routes/webkit/tests/websocket.spec.d.ts +1 -0
- package/build/routes/webkit/tests/websocket.spec.js +104 -0
- package/build/routes/webkit/ws/playwright-webkit.d.ts +6 -0
- package/build/routes/webkit/ws/playwright-webkit.js +19 -0
- package/build/routes/webkit/ws/playwright-webkit.query.json +100 -0
- package/build/server.d.ts +38 -0
- package/build/server.js +365 -0
- package/build/shim.d.ts +9 -0
- package/build/shim.js +54 -0
- package/build/shim.spec.d.ts +1 -0
- package/build/shim.spec.js +114 -0
- package/build/types.d.ts +360 -0
- package/build/types.js +6 -0
- package/build/utils.d.ts +111 -0
- package/build/utils.js +570 -0
- package/build/webhooks.d.ts +11 -0
- package/build/webhooks.js +43 -0
- package/docker/base/.dockerignore +16 -0
- package/docker/base/Dockerfile +70 -0
- package/docker/chrome/.dockerignore +16 -0
- package/docker/chrome/Dockerfile +40 -0
- package/docker/firefox/.dockerignore +16 -0
- package/docker/firefox/Dockerfile +39 -0
- package/docker/multi/.dockerignore +16 -0
- package/docker/multi/Dockerfile +37 -0
- package/docker/sdk/.dockerignore +16 -0
- package/docker/sdk/Dockerfile +34 -0
- package/docker/webkit/.dockerignore +16 -0
- package/docker/webkit/Dockerfile +40 -0
- package/extensions/screencast/background.js +143 -0
- package/extensions/screencast/content_script.js +18 -0
- package/extensions/screencast/manifest.json +19 -0
- package/extensions/ublock/1p-filters.html +69 -0
- package/extensions/ublock/3p-filters.html +119 -0
- package/extensions/ublock/LICENSE.txt +674 -0
- package/extensions/ublock/_locales/ar/messages.json +1290 -0
- package/extensions/ublock/_locales/az/messages.json +1290 -0
- package/extensions/ublock/_locales/be/messages.json +1290 -0
- package/extensions/ublock/_locales/bg/messages.json +1290 -0
- package/extensions/ublock/_locales/bn/messages.json +1290 -0
- package/extensions/ublock/_locales/br_FR/messages.json +1290 -0
- package/extensions/ublock/_locales/bs/messages.json +1290 -0
- package/extensions/ublock/_locales/ca/messages.json +1290 -0
- package/extensions/ublock/_locales/cs/messages.json +1290 -0
- package/extensions/ublock/_locales/cv/messages.json +1290 -0
- package/extensions/ublock/_locales/da/messages.json +1290 -0
- package/extensions/ublock/_locales/de/messages.json +1290 -0
- package/extensions/ublock/_locales/el/messages.json +1290 -0
- package/extensions/ublock/_locales/en/messages.json +1292 -0
- package/extensions/ublock/_locales/en_GB/messages.json +1290 -0
- package/extensions/ublock/_locales/eo/messages.json +1290 -0
- package/extensions/ublock/_locales/es/messages.json +1290 -0
- package/extensions/ublock/_locales/et/messages.json +1290 -0
- package/extensions/ublock/_locales/eu/messages.json +1290 -0
- package/extensions/ublock/_locales/fa/messages.json +1290 -0
- package/extensions/ublock/_locales/fi/messages.json +1290 -0
- package/extensions/ublock/_locales/fil/messages.json +1290 -0
- package/extensions/ublock/_locales/fr/messages.json +1290 -0
- package/extensions/ublock/_locales/fy/messages.json +1290 -0
- package/extensions/ublock/_locales/gl/messages.json +1290 -0
- package/extensions/ublock/_locales/gu/messages.json +1290 -0
- package/extensions/ublock/_locales/he/messages.json +1290 -0
- package/extensions/ublock/_locales/hi/messages.json +1290 -0
- package/extensions/ublock/_locales/hr/messages.json +1290 -0
- package/extensions/ublock/_locales/hu/messages.json +1290 -0
- package/extensions/ublock/_locales/hy/messages.json +1290 -0
- package/extensions/ublock/_locales/id/messages.json +1290 -0
- package/extensions/ublock/_locales/it/messages.json +1290 -0
- package/extensions/ublock/_locales/ja/messages.json +1290 -0
- package/extensions/ublock/_locales/ka/messages.json +1290 -0
- package/extensions/ublock/_locales/kk/messages.json +1290 -0
- package/extensions/ublock/_locales/kn/messages.json +1290 -0
- package/extensions/ublock/_locales/ko/messages.json +1290 -0
- package/extensions/ublock/_locales/ku/messages.json +1290 -0
- package/extensions/ublock/_locales/lt/messages.json +1290 -0
- package/extensions/ublock/_locales/lv/messages.json +1290 -0
- package/extensions/ublock/_locales/mk/messages.json +1290 -0
- package/extensions/ublock/_locales/ml/messages.json +1290 -0
- package/extensions/ublock/_locales/mr/messages.json +1290 -0
- package/extensions/ublock/_locales/ms/messages.json +1290 -0
- package/extensions/ublock/_locales/nb/messages.json +1290 -0
- package/extensions/ublock/_locales/nl/messages.json +1290 -0
- package/extensions/ublock/_locales/no/messages.json +1290 -0
- package/extensions/ublock/_locales/oc/messages.json +1290 -0
- package/extensions/ublock/_locales/pa/messages.json +1290 -0
- package/extensions/ublock/_locales/pl/messages.json +1290 -0
- package/extensions/ublock/_locales/pt_BR/messages.json +1290 -0
- package/extensions/ublock/_locales/pt_PT/messages.json +1290 -0
- package/extensions/ublock/_locales/ro/messages.json +1290 -0
- package/extensions/ublock/_locales/ru/messages.json +1290 -0
- package/extensions/ublock/_locales/si/messages.json +1290 -0
- package/extensions/ublock/_locales/sk/messages.json +1290 -0
- package/extensions/ublock/_locales/sl/messages.json +1290 -0
- package/extensions/ublock/_locales/so/messages.json +1290 -0
- package/extensions/ublock/_locales/sq/messages.json +1290 -0
- package/extensions/ublock/_locales/sr/messages.json +1290 -0
- package/extensions/ublock/_locales/sv/messages.json +1290 -0
- package/extensions/ublock/_locales/sw/messages.json +1290 -0
- package/extensions/ublock/_locales/ta/messages.json +1290 -0
- package/extensions/ublock/_locales/te/messages.json +1290 -0
- package/extensions/ublock/_locales/th/messages.json +1290 -0
- package/extensions/ublock/_locales/tr/messages.json +1290 -0
- package/extensions/ublock/_locales/uk/messages.json +1290 -0
- package/extensions/ublock/_locales/ur/messages.json +1290 -0
- package/extensions/ublock/_locales/vi/messages.json +1290 -0
- package/extensions/ublock/_locales/zh_CN/messages.json +1290 -0
- package/extensions/ublock/_locales/zh_TW/messages.json +1290 -0
- package/extensions/ublock/about.html +63 -0
- package/extensions/ublock/advanced-settings.html +42 -0
- package/extensions/ublock/asset-viewer.html +50 -0
- package/extensions/ublock/assets/assets.json +903 -0
- package/extensions/ublock/assets/resources/scriptlets.js +4255 -0
- package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +65576 -0
- package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +33219 -0
- package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/README.md +29 -0
- package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +3732 -0
- package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +15431 -0
- package/extensions/ublock/assets/thirdparties/urlhaus-filter/LICENSE.md +42 -0
- package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +1970 -0
- package/extensions/ublock/assets/ublock/badlists.txt +77 -0
- package/extensions/ublock/assets/ublock/badware.min.txt +3033 -0
- package/extensions/ublock/assets/ublock/filters.min.txt +23419 -0
- package/extensions/ublock/assets/ublock/privacy.min.txt +575 -0
- package/extensions/ublock/assets/ublock/quick-fixes.min.txt +99 -0
- package/extensions/ublock/assets/ublock/unbreak.min.txt +2448 -0
- package/extensions/ublock/background.html +12 -0
- package/extensions/ublock/cloud-ui.html +23 -0
- package/extensions/ublock/code-viewer.html +53 -0
- package/extensions/ublock/css/1p-filters.css +26 -0
- package/extensions/ublock/css/3p-filters.css +250 -0
- package/extensions/ublock/css/about.css +3 -0
- package/extensions/ublock/css/advanced-settings.css +26 -0
- package/extensions/ublock/css/asset-viewer.css +79 -0
- package/extensions/ublock/css/click2load.css +53 -0
- package/extensions/ublock/css/cloud-ui.css +104 -0
- package/extensions/ublock/css/code-viewer.css +67 -0
- package/extensions/ublock/css/codemirror.css +326 -0
- package/extensions/ublock/css/common.css +347 -0
- package/extensions/ublock/css/dashboard-common.css +55 -0
- package/extensions/ublock/css/dashboard.css +115 -0
- package/extensions/ublock/css/devtools.css +22 -0
- package/extensions/ublock/css/document-blocked.css +146 -0
- package/extensions/ublock/css/dyna-rules.css +79 -0
- package/extensions/ublock/css/epicker-ui.css +270 -0
- package/extensions/ublock/css/fa-icons.css +149 -0
- package/extensions/ublock/css/fonts/Inter/Inter-Regular.woff2 +0 -0
- package/extensions/ublock/css/fonts/Inter/Inter-SemiBold.woff2 +0 -0
- package/extensions/ublock/css/fonts/Inter/LICENSE.txt +93 -0
- package/extensions/ublock/css/fonts/Metropolis/Metropolis-Regular.woff2 +0 -0
- package/extensions/ublock/css/fonts/Metropolis/Metropolis-SemiBold.woff2 +0 -0
- package/extensions/ublock/css/fonts/Metropolis/README.md +25 -0
- package/extensions/ublock/css/fonts/Metropolis/UNLICENSE +24 -0
- package/extensions/ublock/css/logger-ui-inspector.css +116 -0
- package/extensions/ublock/css/logger-ui.css +978 -0
- package/extensions/ublock/css/popup-fenix.css +778 -0
- package/extensions/ublock/css/settings.css +74 -0
- package/extensions/ublock/css/support.css +110 -0
- package/extensions/ublock/css/themes/default.css +526 -0
- package/extensions/ublock/css/whitelist.css +22 -0
- package/extensions/ublock/dashboard.html +47 -0
- package/extensions/ublock/devtools.html +58 -0
- package/extensions/ublock/document-blocked.html +64 -0
- package/extensions/ublock/dyna-rules.html +67 -0
- package/extensions/ublock/img/cloud.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/README +9 -0
- package/extensions/ublock/img/flags-of-the-world/ad.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ae.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/af.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ag.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ai.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/al.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/am.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ao.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/aq.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ar.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/as.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/at.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/au.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/aw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ax.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/az.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ba.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bb.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bd.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/be.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bh.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bi.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bj.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bo.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bq.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/br.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bs.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bv.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/by.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/bz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ca.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cd.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ch.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ci.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ck.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/co.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cv.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cx.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cy.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/cz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/de.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/dj.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/dk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/dm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/do.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/dz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ec.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ee.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/eg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/eh.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/er.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/es.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/et.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/fi.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/fj.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/fk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/fm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/fo.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/fr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ga.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gb-eng.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gb-nir.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gb-sct.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gb-wls.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gb.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gd.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ge.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gh.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gi.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gp.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gq.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gs.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/gy.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/hk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/hm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/hn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/hr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ht.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/hu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/id.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ie.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/il.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/im.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/in.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/io.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/iq.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ir.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/is.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/it.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/je.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/jm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/jo.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/jp.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ke.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kh.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ki.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/km.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kp.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ky.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/kz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/la.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lb.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/li.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ls.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/lv.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ly.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ma.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/md.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/me.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mh.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ml.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mo.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mp.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mq.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ms.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mv.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mx.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/my.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/mz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/na.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/nc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ne.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/nf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ng.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ni.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/nl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/no.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/np.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/nr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/nu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/nz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/om.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pa.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pe.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ph.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ps.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/pw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/py.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/qa.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/re.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ro.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/rs.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ru.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/rw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sa.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sb.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sd.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/se.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sh.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/si.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sj.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/so.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ss.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/st.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sv.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sx.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sy.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/sz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/td.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/th.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tj.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tl.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/to.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tr.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tv.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tw.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/tz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ua.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ug.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/um.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/us.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/uy.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/uz.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/va.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/vc.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ve.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/vg.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/vi.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/vn.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/vu.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/wf.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ws.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/xk.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/ye.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/yt.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/za.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/zm.png +0 -0
- package/extensions/ublock/img/flags-of-the-world/zw.png +0 -0
- package/extensions/ublock/img/fontawesome/LICENSE.txt +25 -0
- package/extensions/ublock/img/fontawesome/fontawesome-defs.svg +79 -0
- package/extensions/ublock/img/help16.png +0 -0
- package/extensions/ublock/img/icon_128.png +0 -0
- package/extensions/ublock/img/icon_16-loading.png +0 -0
- package/extensions/ublock/img/icon_16-off.png +0 -0
- package/extensions/ublock/img/icon_16.png +0 -0
- package/extensions/ublock/img/icon_32-loading.png +0 -0
- package/extensions/ublock/img/icon_32-off.png +0 -0
- package/extensions/ublock/img/icon_32.png +0 -0
- package/extensions/ublock/img/icon_64-loading.png +0 -0
- package/extensions/ublock/img/icon_64-off.png +0 -0
- package/extensions/ublock/img/icon_64.png +0 -0
- package/extensions/ublock/img/material-design.svg +16 -0
- package/extensions/ublock/img/photon.svg +16 -0
- package/extensions/ublock/img/ublock-defs.svg +27 -0
- package/extensions/ublock/img/ublock.svg +44 -0
- package/extensions/ublock/is-webrtc-supported.html +9 -0
- package/extensions/ublock/js/1p-filters.js +336 -0
- package/extensions/ublock/js/3p-filters.js +867 -0
- package/extensions/ublock/js/about.js +34 -0
- package/extensions/ublock/js/advanced-settings.js +194 -0
- package/extensions/ublock/js/asset-viewer.js +112 -0
- package/extensions/ublock/js/assets.js +1448 -0
- package/extensions/ublock/js/background.js +404 -0
- package/extensions/ublock/js/base64-custom.js +246 -0
- package/extensions/ublock/js/benchmarks.js +421 -0
- package/extensions/ublock/js/biditrie.js +947 -0
- package/extensions/ublock/js/cachestorage.js +510 -0
- package/extensions/ublock/js/click2load.js +60 -0
- package/extensions/ublock/js/cloud-ui.js +238 -0
- package/extensions/ublock/js/code-viewer.js +311 -0
- package/extensions/ublock/js/codemirror/search-thread.js +199 -0
- package/extensions/ublock/js/codemirror/search.js +504 -0
- package/extensions/ublock/js/codemirror/ubo-dynamic-filtering.js +239 -0
- package/extensions/ublock/js/codemirror/ubo-static-filtering.js +1126 -0
- package/extensions/ublock/js/commands.js +181 -0
- package/extensions/ublock/js/console.js +59 -0
- package/extensions/ublock/js/contentscript-extra.js +662 -0
- package/extensions/ublock/js/contentscript.js +1366 -0
- package/extensions/ublock/js/contextmenu.js +270 -0
- package/extensions/ublock/js/cosmetic-filtering.js +983 -0
- package/extensions/ublock/js/dashboard-common.js +215 -0
- package/extensions/ublock/js/dashboard.js +166 -0
- package/extensions/ublock/js/devtools.js +184 -0
- package/extensions/ublock/js/diff-updater.js +288 -0
- package/extensions/ublock/js/document-blocked.js +230 -0
- package/extensions/ublock/js/dom.js +213 -0
- package/extensions/ublock/js/dyna-rules.js +678 -0
- package/extensions/ublock/js/dynamic-net-filtering.js +488 -0
- package/extensions/ublock/js/epicker-ui.js +924 -0
- package/extensions/ublock/js/fa-icons.js +129 -0
- package/extensions/ublock/js/filtering-context.js +461 -0
- package/extensions/ublock/js/filtering-engines.js +50 -0
- package/extensions/ublock/js/hnswitches.js +289 -0
- package/extensions/ublock/js/hntrie.js +780 -0
- package/extensions/ublock/js/html-filtering.js +465 -0
- package/extensions/ublock/js/httpheader-filtering.js +213 -0
- package/extensions/ublock/js/i18n.js +346 -0
- package/extensions/ublock/js/is-webrtc-supported.js +52 -0
- package/extensions/ublock/js/logger-ui-inspector.js +652 -0
- package/extensions/ublock/js/logger-ui.js +3028 -0
- package/extensions/ublock/js/logger.js +84 -0
- package/extensions/ublock/js/lz4.js +190 -0
- package/extensions/ublock/js/messaging.js +2095 -0
- package/extensions/ublock/js/pagestore.js +1140 -0
- package/extensions/ublock/js/popup-fenix.js +1529 -0
- package/extensions/ublock/js/redirect-engine.js +494 -0
- package/extensions/ublock/js/redirect-resources.js +193 -0
- package/extensions/ublock/js/reverselookup-worker.js +287 -0
- package/extensions/ublock/js/reverselookup.js +223 -0
- package/extensions/ublock/js/scriptlet-filtering.js +556 -0
- package/extensions/ublock/js/scriptlets/cosmetic-logger.js +376 -0
- package/extensions/ublock/js/scriptlets/cosmetic-off.js +48 -0
- package/extensions/ublock/js/scriptlets/cosmetic-on.js +48 -0
- package/extensions/ublock/js/scriptlets/cosmetic-report.js +142 -0
- package/extensions/ublock/js/scriptlets/dom-inspector.js +906 -0
- package/extensions/ublock/js/scriptlets/dom-survey-elements.js +72 -0
- package/extensions/ublock/js/scriptlets/dom-survey-scripts.js +126 -0
- package/extensions/ublock/js/scriptlets/epicker.js +1365 -0
- package/extensions/ublock/js/scriptlets/load-3p-css.js +67 -0
- package/extensions/ublock/js/scriptlets/load-large-media-all.js +62 -0
- package/extensions/ublock/js/scriptlets/load-large-media-interactive.js +299 -0
- package/extensions/ublock/js/scriptlets/noscript-spoof.js +89 -0
- package/extensions/ublock/js/scriptlets/should-inject-contentscript.js +40 -0
- package/extensions/ublock/js/scriptlets/subscriber.js +113 -0
- package/extensions/ublock/js/scriptlets/updater.js +101 -0
- package/extensions/ublock/js/settings.js +317 -0
- package/extensions/ublock/js/start.js +509 -0
- package/extensions/ublock/js/static-dnr-filtering.js +497 -0
- package/extensions/ublock/js/static-ext-filtering-db.js +171 -0
- package/extensions/ublock/js/static-ext-filtering.js +184 -0
- package/extensions/ublock/js/static-filtering-io.js +144 -0
- package/extensions/ublock/js/static-filtering-parser.js +4459 -0
- package/extensions/ublock/js/static-net-filtering.js +5631 -0
- package/extensions/ublock/js/storage.js +1683 -0
- package/extensions/ublock/js/support.js +335 -0
- package/extensions/ublock/js/tab.js +1178 -0
- package/extensions/ublock/js/tasks.js +42 -0
- package/extensions/ublock/js/text-encode.js +275 -0
- package/extensions/ublock/js/text-utils.js +107 -0
- package/extensions/ublock/js/theme.js +151 -0
- package/extensions/ublock/js/traffic.js +1260 -0
- package/extensions/ublock/js/ublock.js +696 -0
- package/extensions/ublock/js/uri-utils.js +175 -0
- package/extensions/ublock/js/url-net-filtering.js +336 -0
- package/extensions/ublock/js/utils.js +208 -0
- package/extensions/ublock/js/vapi-background-ext.js +254 -0
- package/extensions/ublock/js/vapi-background.js +1802 -0
- package/extensions/ublock/js/vapi-client-extra.js +312 -0
- package/extensions/ublock/js/vapi-client.js +280 -0
- package/extensions/ublock/js/vapi-common.js +308 -0
- package/extensions/ublock/js/vapi.js +89 -0
- package/extensions/ublock/js/wasm/README.md +24 -0
- package/extensions/ublock/js/wasm/biditrie.wasm +0 -0
- package/extensions/ublock/js/wasm/biditrie.wat +728 -0
- package/extensions/ublock/js/wasm/hntrie.wasm +0 -0
- package/extensions/ublock/js/wasm/hntrie.wat +724 -0
- package/extensions/ublock/js/webext.js +164 -0
- package/extensions/ublock/js/whitelist.js +258 -0
- package/extensions/ublock/lib/codemirror/LICENSE +21 -0
- package/extensions/ublock/lib/codemirror/README.md +47 -0
- package/extensions/ublock/lib/codemirror/addon/comment/comment.js +211 -0
- package/extensions/ublock/lib/codemirror/addon/display/panel.js +133 -0
- package/extensions/ublock/lib/codemirror/addon/edit/closebrackets.js +201 -0
- package/extensions/ublock/lib/codemirror/addon/edit/matchbrackets.js +160 -0
- package/extensions/ublock/lib/codemirror/addon/fold/foldcode.js +157 -0
- package/extensions/ublock/lib/codemirror/addon/fold/foldgutter.css +20 -0
- package/extensions/ublock/lib/codemirror/addon/fold/foldgutter.js +163 -0
- package/extensions/ublock/lib/codemirror/addon/hint/show-hint.css +36 -0
- package/extensions/ublock/lib/codemirror/addon/hint/show-hint.js +509 -0
- package/extensions/ublock/lib/codemirror/addon/merge/merge.css +119 -0
- package/extensions/ublock/lib/codemirror/addon/merge/merge.js +1006 -0
- package/extensions/ublock/lib/codemirror/addon/scroll/annotatescrollbar.js +128 -0
- package/extensions/ublock/lib/codemirror/addon/search/matchesonscrollbar.css +8 -0
- package/extensions/ublock/lib/codemirror/addon/search/searchcursor.js +296 -0
- package/extensions/ublock/lib/codemirror/addon/selection/active-line.js +72 -0
- package/extensions/ublock/lib/codemirror/lib/codemirror.css +350 -0
- package/extensions/ublock/lib/codemirror/lib/codemirror.js +9800 -0
- package/extensions/ublock/lib/codemirror/mode/css/css.js +864 -0
- package/extensions/ublock/lib/codemirror/mode/htmlmixed/htmlmixed.js +153 -0
- package/extensions/ublock/lib/codemirror/mode/javascript/javascript.js +942 -0
- package/extensions/ublock/lib/codemirror/mode/xml/xml.js +413 -0
- package/extensions/ublock/lib/codemirror/theme/night.css +27 -0
- package/extensions/ublock/lib/csstree/LICENSE +19 -0
- package/extensions/ublock/lib/csstree/css-tree.js +17 -0
- package/extensions/ublock/lib/diff/README.md +34 -0
- package/extensions/ublock/lib/diff/swatinem_diff.js +272 -0
- package/extensions/ublock/lib/hsluv/LICENSE +20 -0
- package/extensions/ublock/lib/hsluv/README +3 -0
- package/extensions/ublock/lib/hsluv/hsluv-0.1.0.min.js +8 -0
- package/extensions/ublock/lib/js-beautify/LICENSE +9 -0
- package/extensions/ublock/lib/js-beautify/README +5 -0
- package/extensions/ublock/lib/js-beautify/beautifier.min.js +2 -0
- package/extensions/ublock/lib/lz4/README.md +52 -0
- package/extensions/ublock/lib/lz4/lz4-block-codec-any.js +151 -0
- package/extensions/ublock/lib/lz4/lz4-block-codec-js.js +297 -0
- package/extensions/ublock/lib/lz4/lz4-block-codec-wasm.js +195 -0
- package/extensions/ublock/lib/lz4/lz4-block-codec.wasm +0 -0
- package/extensions/ublock/lib/lz4/lz4-block-codec.wat +745 -0
- package/extensions/ublock/lib/publicsuffixlist/publicsuffixlist.js +641 -0
- package/extensions/ublock/lib/publicsuffixlist/wasm/README.md +29 -0
- package/extensions/ublock/lib/publicsuffixlist/wasm/publicsuffixlist.wasm +0 -0
- package/extensions/ublock/lib/publicsuffixlist/wasm/publicsuffixlist.wat +322 -0
- package/extensions/ublock/lib/punycode.js +493 -0
- package/extensions/ublock/lib/regexanalyzer/CHANGES.md +15 -0
- package/extensions/ublock/lib/regexanalyzer/README.md +14 -0
- package/extensions/ublock/lib/regexanalyzer/regex.js +2276 -0
- package/extensions/ublock/logger-ui.html +232 -0
- package/extensions/ublock/managed_storage.json +73 -0
- package/extensions/ublock/manifest.json +115 -0
- package/extensions/ublock/no-dashboard.html +27 -0
- package/extensions/ublock/popup-fenix.html +114 -0
- package/extensions/ublock/settings.html +98 -0
- package/extensions/ublock/support.html +131 -0
- package/extensions/ublock/web_accessible_resources/1x1.gif +0 -0
- package/extensions/ublock/web_accessible_resources/2x2.png +0 -0
- package/extensions/ublock/web_accessible_resources/32x32.png +0 -0
- package/extensions/ublock/web_accessible_resources/3x2.png +0 -0
- package/extensions/ublock/web_accessible_resources/README.txt +11 -0
- package/extensions/ublock/web_accessible_resources/addthis_widget.js +39 -0
- package/extensions/ublock/web_accessible_resources/amazon_ads.js +70 -0
- package/extensions/ublock/web_accessible_resources/amazon_apstag.js +62 -0
- package/extensions/ublock/web_accessible_resources/ampproject_v0.js +34 -0
- package/extensions/ublock/web_accessible_resources/chartbeat.js +30 -0
- package/extensions/ublock/web_accessible_resources/click2load.html +28 -0
- package/extensions/ublock/web_accessible_resources/doubleclick_instream_ad_status.js +1 -0
- package/extensions/ublock/web_accessible_resources/empty +0 -0
- package/extensions/ublock/web_accessible_resources/epicker-ui.html +76 -0
- package/extensions/ublock/web_accessible_resources/fingerprint2.js +55 -0
- package/extensions/ublock/web_accessible_resources/fingerprint3.js +45 -0
- package/extensions/ublock/web_accessible_resources/google-analytics_analytics.js +110 -0
- package/extensions/ublock/web_accessible_resources/google-analytics_cx_api.js +36 -0
- package/extensions/ublock/web_accessible_resources/google-analytics_ga.js +130 -0
- package/extensions/ublock/web_accessible_resources/google-analytics_inpage_linkid.js +28 -0
- package/extensions/ublock/web_accessible_resources/google-ima.js +855 -0
- package/extensions/ublock/web_accessible_resources/googlesyndication_adsbygoogle.js +56 -0
- package/extensions/ublock/web_accessible_resources/googletagmanager_gtm.js +43 -0
- package/extensions/ublock/web_accessible_resources/googletagservices_gpt.js +153 -0
- package/extensions/ublock/web_accessible_resources/hd-main.js +46 -0
- package/extensions/ublock/web_accessible_resources/ligatus_angular-tag.js +29 -0
- package/extensions/ublock/web_accessible_resources/monkeybroker.js +43 -0
- package/extensions/ublock/web_accessible_resources/mxpnl_mixpanel.js +51 -0
- package/extensions/ublock/web_accessible_resources/nobab.js +87 -0
- package/extensions/ublock/web_accessible_resources/nobab2.js +42 -0
- package/extensions/ublock/web_accessible_resources/noeval-silent.js +28 -0
- package/extensions/ublock/web_accessible_resources/noeval.js +30 -0
- package/extensions/ublock/web_accessible_resources/nofab.js +67 -0
- package/extensions/ublock/web_accessible_resources/noop-0.1s.mp3 +0 -0
- package/extensions/ublock/web_accessible_resources/noop-0.5s.mp3 +0 -0
- package/extensions/ublock/web_accessible_resources/noop-1s.mp4 +0 -0
- package/extensions/ublock/web_accessible_resources/noop-vmap1.0.xml +1 -0
- package/extensions/ublock/web_accessible_resources/noop.css +1 -0
- package/extensions/ublock/web_accessible_resources/noop.html +5 -0
- package/extensions/ublock/web_accessible_resources/noop.js +3 -0
- package/extensions/ublock/web_accessible_resources/noop.json +1 -0
- package/extensions/ublock/web_accessible_resources/noop.txt +1 -0
- package/extensions/ublock/web_accessible_resources/outbrain-widget.js +72 -0
- package/extensions/ublock/web_accessible_resources/popads-dummy.js +30 -0
- package/extensions/ublock/web_accessible_resources/popads.js +40 -0
- package/extensions/ublock/web_accessible_resources/prebid-ads.js +26 -0
- package/extensions/ublock/web_accessible_resources/scorecardresearch_beacon.js +31 -0
- package/extensions/ublock/whitelist.html +63 -0
- package/external/.gitkeep +0 -0
- package/fonts/Calibri Bold Italic.ttf +0 -0
- package/fonts/Calibri Bold.TTF +0 -0
- package/fonts/Calibri Italic.ttf +0 -0
- package/fonts/Calibri Light Italic.ttf +0 -0
- package/fonts/Calibri Light.ttf +0 -0
- package/fonts/Calibri Regular.ttf +0 -0
- package/fonts/Emoji.ttf +0 -0
- package/fonts/SegoeUI-Bold.ttf +0 -0
- package/fonts/SegoeUI-Light.ttf +0 -0
- package/fonts/SegoeUI-Regular.ttf +0 -0
- package/fonts/SegoeUI-Semibold.ttf +0 -0
- package/fonts/SegoeUI-Semilight.ttf +0 -0
- package/fonts/Tahoma Bold.ttf +0 -0
- package/fonts/Tahoma.ttf +0 -0
- package/fonts/fonts.conf +21 -0
- package/package.json +177 -0
- package/scripts/build-function.js +18 -0
- package/scripts/build-open-api.js +274 -0
- package/scripts/build-schemas.js +86 -0
- package/scripts/build-selectors.js +36 -0
- package/scripts/clean.js +7 -0
- package/scripts/install-adblock.js +45 -0
- package/scripts/install-cdp-json.js +37 -0
- package/scripts/start.sh +30 -0
- package/scripts/test.sh +17 -0
- package/src/browserless.ts +253 -0
- package/src/browsers/cdp-chromium.ts +422 -0
- package/src/browsers/index.ts +296 -0
- package/src/browsers/playwright-chromium.ts +168 -0
- package/src/browsers/playwright-firefox.ts +161 -0
- package/src/browsers/playwright-webkit.ts +161 -0
- package/src/config.ts +426 -0
- package/src/constants.ts +4 -0
- package/src/exports.ts +23 -0
- package/src/file-system.ts +54 -0
- package/src/hooks.ts +37 -0
- package/src/http.ts +157 -0
- package/src/index.ts +41 -0
- package/src/limiter.spec.ts +365 -0
- package/src/limiter.ts +225 -0
- package/src/metrics.spec.ts +49 -0
- package/src/metrics.ts +108 -0
- package/src/mime-types.ts +332 -0
- package/src/monitoring.ts +53 -0
- package/src/routes/chromium/http/content-post.ts +238 -0
- package/src/routes/chromium/http/download-post.ts +162 -0
- package/src/routes/chromium/http/function-post.ts +98 -0
- package/src/routes/chromium/http/pdf-post.ts +234 -0
- package/src/routes/chromium/http/performance.ts +71 -0
- package/src/routes/chromium/http/scrape-post.ts +439 -0
- package/src/routes/chromium/http/screenshot-post.ts +262 -0
- package/src/routes/chromium/tests/content.spec.ts +340 -0
- package/src/routes/chromium/tests/download.spec.ts +77 -0
- package/src/routes/chromium/tests/function.spec.ts +279 -0
- package/src/routes/chromium/tests/pdf.spec.ts +375 -0
- package/src/routes/chromium/tests/performance.spec.ts +155 -0
- package/src/routes/chromium/tests/scrape.spec.ts +414 -0
- package/src/routes/chromium/tests/screenshot.spec.ts +387 -0
- package/src/routes/chromium/tests/websocket.spec.ts +407 -0
- package/src/routes/chromium/utils/function/client.ts +99 -0
- package/src/routes/chromium/utils/function/handler.ts +172 -0
- package/src/routes/chromium/utils/performance/child.ts +38 -0
- package/src/routes/chromium/utils/performance/main.ts +90 -0
- package/src/routes/chromium/utils/performance/types.ts +24 -0
- package/src/routes/chromium/ws/browser.ts +31 -0
- package/src/routes/chromium/ws/cdp-chromium.ts +31 -0
- package/src/routes/chromium/ws/page.ts +31 -0
- package/src/routes/chromium/ws/playwright-chromium.ts +44 -0
- package/src/routes/firefox/tests/websocket.spec.ts +146 -0
- package/src/routes/firefox/ws/playwright-firefox.ts +44 -0
- package/src/routes/management/http/config-get.ts +82 -0
- package/src/routes/management/http/metrics-get.ts +43 -0
- package/src/routes/management/http/metrics-total-get.ts +89 -0
- package/src/routes/management/http/sessions-get.ts +39 -0
- package/src/routes/management/http/static-get.ts +109 -0
- package/src/routes/management/tests/management.spec.ts +71 -0
- package/src/routes/webkit/tests/websocket.spec.ts +146 -0
- package/src/routes/webkit/ws/playwright-webkit.ts +44 -0
- package/src/server.ts +609 -0
- package/src/shim.spec.ts +154 -0
- package/src/shim.ts +78 -0
- package/src/types.ts +470 -0
- package/src/utils.ts +787 -0
- package/src/webhooks.ts +50 -0
- package/static/docs/browserless-logo.png +0 -0
- package/static/docs/docs.js +2 -0
- package/static/docs/index.html +71 -0
- package/static/docs/swagger.json +4232 -0
- package/static/favicon-32x32.png +0 -0
- package/static/function/client.js +31623 -0
- package/static/function/index.html +12 -0
- 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
|
+
/******************************************************************************/
|