@browserless.io/browserless 2.20.2 → 2.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/CHANGELOG.md +15 -1
  2. package/bin/browserless.js +2 -1
  3. package/build/browserless.js +3 -2
  4. package/build/browsers/index.d.ts +3 -2
  5. package/build/browsers/index.js +3 -1
  6. package/build/routes/chrome/http/content.post.body.json +8 -8
  7. package/build/routes/chrome/http/pdf.post.body.json +8 -8
  8. package/build/routes/chrome/http/scrape.post.body.json +8 -8
  9. package/build/routes/chrome/http/screenshot.post.body.json +8 -8
  10. package/build/routes/chrome/tests/pdf.spec.js +24 -12
  11. package/build/routes/chromium/http/content.post.body.json +8 -8
  12. package/build/routes/chromium/http/pdf.post.body.json +8 -8
  13. package/build/routes/chromium/http/scrape.post.body.json +8 -8
  14. package/build/routes/chromium/http/screenshot.post.body.json +8 -8
  15. package/build/routes/chromium/tests/pdf.spec.js +24 -12
  16. package/build/shared/pdf.http.js +10 -5
  17. package/docker/sdk/Dockerfile +11 -0
  18. package/extensions/ublock/_locales/ar/messages.json +5 -1
  19. package/extensions/ublock/_locales/az/messages.json +4 -0
  20. package/extensions/ublock/_locales/be/messages.json +4 -0
  21. package/extensions/ublock/_locales/bg/messages.json +4 -0
  22. package/extensions/ublock/_locales/bn/messages.json +4 -0
  23. package/extensions/ublock/_locales/br_FR/messages.json +9 -5
  24. package/extensions/ublock/_locales/bs/messages.json +4 -0
  25. package/extensions/ublock/_locales/ca/messages.json +5 -1
  26. package/extensions/ublock/_locales/cs/messages.json +4 -0
  27. package/extensions/ublock/_locales/cv/messages.json +4 -0
  28. package/extensions/ublock/_locales/cy/messages.json +4 -0
  29. package/extensions/ublock/_locales/da/messages.json +4 -0
  30. package/extensions/ublock/_locales/de/messages.json +4 -0
  31. package/extensions/ublock/_locales/el/messages.json +8 -4
  32. package/extensions/ublock/_locales/en/messages.json +4 -0
  33. package/extensions/ublock/_locales/en_GB/messages.json +4 -0
  34. package/extensions/ublock/_locales/eo/messages.json +9 -5
  35. package/extensions/ublock/_locales/es/messages.json +4 -0
  36. package/extensions/ublock/_locales/et/messages.json +4 -0
  37. package/extensions/ublock/_locales/eu/messages.json +4 -0
  38. package/extensions/ublock/_locales/fa/messages.json +4 -0
  39. package/extensions/ublock/_locales/fi/messages.json +6 -2
  40. package/extensions/ublock/_locales/fil/messages.json +4 -0
  41. package/extensions/ublock/_locales/fr/messages.json +4 -0
  42. package/extensions/ublock/_locales/fy/messages.json +4 -0
  43. package/extensions/ublock/_locales/gl/messages.json +12 -8
  44. package/extensions/ublock/_locales/gu/messages.json +4 -0
  45. package/extensions/ublock/_locales/he/messages.json +4 -0
  46. package/extensions/ublock/_locales/hi/messages.json +4 -0
  47. package/extensions/ublock/_locales/hr/messages.json +4 -0
  48. package/extensions/ublock/_locales/hu/messages.json +68 -64
  49. package/extensions/ublock/_locales/hy/messages.json +4 -0
  50. package/extensions/ublock/_locales/id/messages.json +6 -2
  51. package/extensions/ublock/_locales/it/messages.json +4 -0
  52. package/extensions/ublock/_locales/ja/messages.json +4 -0
  53. package/extensions/ublock/_locales/ka/messages.json +4 -0
  54. package/extensions/ublock/_locales/kk/messages.json +4 -0
  55. package/extensions/ublock/_locales/kn/messages.json +4 -0
  56. package/extensions/ublock/_locales/ko/messages.json +4 -0
  57. package/extensions/ublock/_locales/lt/messages.json +4 -0
  58. package/extensions/ublock/_locales/lv/messages.json +4 -0
  59. package/extensions/ublock/_locales/mk/messages.json +4 -0
  60. package/extensions/ublock/_locales/ml/messages.json +4 -0
  61. package/extensions/ublock/_locales/mr/messages.json +4 -0
  62. package/extensions/ublock/_locales/ms/messages.json +4 -0
  63. package/extensions/ublock/_locales/nb/messages.json +4 -0
  64. package/extensions/ublock/_locales/nl/messages.json +4 -0
  65. package/extensions/ublock/_locales/no/messages.json +4 -0
  66. package/extensions/ublock/_locales/oc/messages.json +4 -0
  67. package/extensions/ublock/_locales/pa/messages.json +8 -4
  68. package/extensions/ublock/_locales/pl/messages.json +4 -0
  69. package/extensions/ublock/_locales/pt_BR/messages.json +4 -0
  70. package/extensions/ublock/_locales/pt_PT/messages.json +4 -0
  71. package/extensions/ublock/_locales/ro/messages.json +4 -0
  72. package/extensions/ublock/_locales/ru/messages.json +4 -0
  73. package/extensions/ublock/_locales/si/messages.json +4 -0
  74. package/extensions/ublock/_locales/sk/messages.json +4 -0
  75. package/extensions/ublock/_locales/sl/messages.json +4 -0
  76. package/extensions/ublock/_locales/so/messages.json +4 -0
  77. package/extensions/ublock/_locales/sq/messages.json +4 -0
  78. package/extensions/ublock/_locales/sr/messages.json +6 -2
  79. package/extensions/ublock/_locales/sv/messages.json +4 -0
  80. package/extensions/ublock/_locales/sw/messages.json +4 -0
  81. package/extensions/ublock/_locales/ta/messages.json +4 -0
  82. package/extensions/ublock/_locales/te/messages.json +4 -0
  83. package/extensions/ublock/_locales/th/messages.json +4 -0
  84. package/extensions/ublock/_locales/tr/messages.json +4 -0
  85. package/extensions/ublock/_locales/uk/messages.json +4 -0
  86. package/extensions/ublock/_locales/ur/messages.json +4 -0
  87. package/extensions/ublock/_locales/vi/messages.json +4 -0
  88. package/extensions/ublock/_locales/zh_CN/messages.json +4 -0
  89. package/extensions/ublock/_locales/zh_TW/messages.json +5 -1
  90. package/extensions/ublock/assets/assets.json +8 -6
  91. package/extensions/ublock/assets/resources/scriptlets.js +455 -301
  92. package/extensions/ublock/assets/thirdparties/easylist/easylist.txt +4441 -6643
  93. package/extensions/ublock/assets/thirdparties/easylist/easyprivacy.txt +401 -307
  94. package/extensions/ublock/assets/thirdparties/pgl.yoyo.org/as/serverlist +34 -29
  95. package/extensions/ublock/assets/thirdparties/publicsuffix.org/list/effective_tld_names.dat +682 -709
  96. package/extensions/ublock/assets/thirdparties/urlhaus-filter/urlhaus-filter-online.txt +2439 -1999
  97. package/extensions/ublock/assets/ublock/badlists.txt +7 -0
  98. package/extensions/ublock/assets/ublock/badware.min.txt +992 -552
  99. package/extensions/ublock/assets/ublock/filters.min.txt +1253 -864
  100. package/extensions/ublock/assets/ublock/privacy.min.txt +58 -31
  101. package/extensions/ublock/assets/ublock/quick-fixes.min.txt +118 -126
  102. package/extensions/ublock/assets/ublock/unbreak.min.txt +129 -109
  103. package/extensions/ublock/js/background.js +4 -3
  104. package/extensions/ublock/js/benchmarks.js +29 -29
  105. package/extensions/ublock/js/codemirror/ubo-static-filtering.js +1 -0
  106. package/extensions/ublock/js/contextmenu.js +20 -21
  107. package/extensions/ublock/js/devtools.js +137 -3
  108. package/extensions/ublock/js/filtering-context.js +98 -43
  109. package/extensions/ublock/js/logger-ui.js +1 -1
  110. package/extensions/ublock/js/messaging.js +57 -135
  111. package/extensions/ublock/js/pagestore.js +44 -31
  112. package/extensions/ublock/js/redirect-resources.js +14 -4
  113. package/extensions/ublock/js/scriptlet-filtering.js +4 -1
  114. package/extensions/ublock/js/static-filtering-parser.js +107 -37
  115. package/extensions/ublock/js/static-net-filtering.js +514 -250
  116. package/extensions/ublock/js/storage.js +2 -1
  117. package/extensions/ublock/js/traffic.js +8 -4
  118. package/extensions/ublock/js/vapi-background.js +1 -0
  119. package/extensions/ublock/js/vapi-common.js +1 -0
  120. package/extensions/ublock/logger-ui.html +2 -3
  121. package/extensions/ublock/manifest.json +2 -2
  122. package/extensions/ublock/support.html +1 -0
  123. package/extensions/ublock/web_accessible_resources/noop-vast2.xml +1 -0
  124. package/extensions/ublock/web_accessible_resources/noop-vast3.xml +1 -0
  125. package/extensions/ublock/web_accessible_resources/noop-vast4.xml +1 -0
  126. package/package.json +17 -17
  127. package/src/browserless.ts +3 -2
  128. package/src/browsers/index.ts +2 -0
  129. package/src/routes/chrome/tests/pdf.spec.ts +24 -12
  130. package/src/routes/chromium/tests/pdf.spec.ts +24 -12
  131. package/src/shared/pdf.http.ts +10 -6
  132. package/static/docs/swagger.json +10 -10
  133. package/static/docs/swagger.min.json +9 -9
  134. package/static/function/client.js +9 -9
  135. package/static/function/index.html +9 -9
  136. /package/extensions/ublock/web_accessible_resources/{noop-vmap1.0.xml → noop-vmap1.xml} +0 -0
@@ -172,6 +172,7 @@ export const NODE_TYPE_NET_OPTION_NAME_IMAGE = iota++;
172
172
  export const NODE_TYPE_NET_OPTION_NAME_IMPORTANT = iota++;
173
173
  export const NODE_TYPE_NET_OPTION_NAME_INLINEFONT = iota++;
174
174
  export const NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT = iota++;
175
+ export const NODE_TYPE_NET_OPTION_NAME_IPADDRESS = iota++;
175
176
  export const NODE_TYPE_NET_OPTION_NAME_MATCHCASE = iota++;
176
177
  export const NODE_TYPE_NET_OPTION_NAME_MEDIA = iota++;
177
178
  export const NODE_TYPE_NET_OPTION_NAME_METHOD = iota++;
@@ -190,11 +191,13 @@ export const NODE_TYPE_NET_OPTION_NAME_REPLACE = iota++;
190
191
  export const NODE_TYPE_NET_OPTION_NAME_SCRIPT = iota++;
191
192
  export const NODE_TYPE_NET_OPTION_NAME_SHIDE = iota++;
192
193
  export const NODE_TYPE_NET_OPTION_NAME_TO = iota++;
194
+ export const NODE_TYPE_NET_OPTION_NAME_URLSKIP = iota++;
193
195
  export const NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM = iota++;
194
196
  export const NODE_TYPE_NET_OPTION_NAME_XHR = iota++;
195
197
  export const NODE_TYPE_NET_OPTION_NAME_WEBRTC = iota++;
196
198
  export const NODE_TYPE_NET_OPTION_NAME_WEBSOCKET = iota++;
197
199
  export const NODE_TYPE_NET_OPTION_ASSIGN = iota++;
200
+ export const NODE_TYPE_NET_OPTION_QUOTE = iota++;
198
201
  export const NODE_TYPE_NET_OPTION_VALUE = iota++;
199
202
  export const NODE_TYPE_OPTION_VALUE_DOMAIN_LIST = iota++;
200
203
  export const NODE_TYPE_OPTION_VALUE_DOMAIN_RAW = iota++;
@@ -248,6 +251,7 @@ export const nodeTypeFromOptionName = new Map([
248
251
  [ 'important', NODE_TYPE_NET_OPTION_NAME_IMPORTANT ],
249
252
  [ 'inline-font', NODE_TYPE_NET_OPTION_NAME_INLINEFONT ],
250
253
  [ 'inline-script', NODE_TYPE_NET_OPTION_NAME_INLINESCRIPT ],
254
+ [ 'ipaddress', NODE_TYPE_NET_OPTION_NAME_IPADDRESS ],
251
255
  [ 'match-case', NODE_TYPE_NET_OPTION_NAME_MATCHCASE ],
252
256
  [ 'media', NODE_TYPE_NET_OPTION_NAME_MEDIA ],
253
257
  [ 'method', NODE_TYPE_NET_OPTION_NAME_METHOD ],
@@ -271,6 +275,7 @@ export const nodeTypeFromOptionName = new Map([
271
275
  [ 'shide', NODE_TYPE_NET_OPTION_NAME_SHIDE ],
272
276
  /* synonym */ [ 'specifichide', NODE_TYPE_NET_OPTION_NAME_SHIDE ],
273
277
  [ 'to', NODE_TYPE_NET_OPTION_NAME_TO ],
278
+ [ 'urlskip', NODE_TYPE_NET_OPTION_NAME_URLSKIP ],
274
279
  [ 'uritransform', NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM ],
275
280
  [ 'xhr', NODE_TYPE_NET_OPTION_NAME_XHR ],
276
281
  /* synonym */ [ 'xmlhttprequest', NODE_TYPE_NET_OPTION_NAME_XHR ],
@@ -575,6 +580,7 @@ export const preparserIfTokens = new Set([
575
580
  'env_mv3',
576
581
  'env_safari',
577
582
  'cap_html_filtering',
583
+ 'cap_ipaddress',
578
584
  'cap_user_stylesheet',
579
585
  'false',
580
586
  'ext_abp',
@@ -896,7 +902,9 @@ export class AstFilterParser {
896
902
  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]/;
897
903
  this.reBadCSP = /(?:^|[;,])\s*report-(?:to|uri)\b/i;
898
904
  this.reBadPP = /(?:^|[;,])\s*report-to\b/i;
905
+ this.reNetOption = /^(~?)([134a-z_-]+)(=?)/;
899
906
  this.reNoopOption = /^_+$/;
907
+ this.netOptionValueParser = new ArgListParser(',');
900
908
  this.scriptletArgListParser = new ArgListParser(',');
901
909
  }
902
910
 
@@ -1398,6 +1406,14 @@ export class AstFilterParser {
1398
1406
  modifierType = type;
1399
1407
  unredirectableTypeCount += 1;
1400
1408
  break;
1409
+ case NODE_TYPE_NET_OPTION_NAME_IPADDRESS: {
1410
+ const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_IPADDRESS);
1411
+ if ( /^\/.+\/$/.test(value) ) {
1412
+ try { void new RegExp(value); }
1413
+ catch(_) { realBad = true; }
1414
+ }
1415
+ break;
1416
+ }
1401
1417
  case NODE_TYPE_NET_OPTION_NAME_MATCHCASE:
1402
1418
  realBad = this.isRegexPattern() === false;
1403
1419
  break;
@@ -1427,6 +1443,7 @@ export class AstFilterParser {
1427
1443
  case NODE_TYPE_NET_OPTION_NAME_REDIRECT:
1428
1444
  case NODE_TYPE_NET_OPTION_NAME_REDIRECTRULE:
1429
1445
  case NODE_TYPE_NET_OPTION_NAME_REPLACE:
1446
+ case NODE_TYPE_NET_OPTION_NAME_URLSKIP:
1430
1447
  case NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM:
1431
1448
  realBad = isNegated || (isException || hasValue) === false ||
1432
1449
  modifierType !== 0;
@@ -1505,6 +1522,21 @@ export class AstFilterParser {
1505
1522
  }
1506
1523
  break;
1507
1524
  }
1525
+ case NODE_TYPE_NET_OPTION_NAME_URLSKIP: {
1526
+ realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount;
1527
+ if ( realBad ) { break; }
1528
+ if ( requiresTrustedSource() ) {
1529
+ this.astError = AST_ERROR_UNTRUSTED_SOURCE;
1530
+ realBad = true;
1531
+ break;
1532
+ }
1533
+ const value = this.getNetOptionValue(NODE_TYPE_NET_OPTION_NAME_URLSKIP);
1534
+ if ( value.startsWith('?') === false || value.length < 2 ) {
1535
+ this.astError = AST_ERROR_OPTION_BADVALUE;
1536
+ realBad = true;
1537
+ }
1538
+ break;
1539
+ }
1508
1540
  case NODE_TYPE_NET_OPTION_NAME_URLTRANSFORM: {
1509
1541
  realBad = abstractTypeCount || behaviorTypeCount || unredirectableTypeCount;
1510
1542
  if ( realBad ) { break; }
@@ -1959,16 +1991,17 @@ export class AstFilterParser {
1959
1991
  const head = this.allocHeadNode();
1960
1992
  let prev = head, next = 0;
1961
1993
  let optionBeg = 0, optionEnd = 0;
1962
- let emptyOption = false, badComma = false;
1963
1994
  while ( optionBeg !== optionsEnd ) {
1964
- optionEnd = this.endOfNetOption(s, optionBeg);
1965
1995
  next = this.allocTypedNode(
1966
1996
  NODE_TYPE_NET_OPTION_RAW,
1967
1997
  parentBeg + optionBeg,
1968
- parentBeg + optionEnd
1998
+ parentBeg + optionsEnd // open ended
1969
1999
  );
1970
- emptyOption = optionEnd === optionBeg;
1971
- this.linkDown(next, this.parseNetOption(next));
2000
+ const { node: down, len: optionLen } = this.parseNetOption(next);
2001
+ // set next's end to down's end
2002
+ optionEnd += optionLen;
2003
+ this.nodes[next+NODE_END_INDEX] = parentBeg + optionEnd;
2004
+ this.linkDown(next, down);
1972
2005
  prev = this.linkRight(prev, next);
1973
2006
  if ( optionEnd === optionsEnd ) { break; }
1974
2007
  optionBeg = optionEnd + 1;
@@ -1977,12 +2010,12 @@ export class AstFilterParser {
1977
2010
  parentBeg + optionEnd,
1978
2011
  parentBeg + optionBeg
1979
2012
  );
1980
- badComma = optionBeg === optionsEnd;
1981
- prev = this.linkRight(prev, next);
1982
- if ( emptyOption || badComma ) {
2013
+ if ( optionLen === 0 || optionBeg === optionsEnd ) {
1983
2014
  this.addNodeFlags(next, NODE_FLAG_ERROR);
1984
2015
  this.addFlags(AST_FLAG_HAS_ERROR);
1985
2016
  }
2017
+ prev = this.linkRight(prev, next);
2018
+ optionEnd = optionBeg;
1986
2019
  }
1987
2020
  this.linkRight(prev,
1988
2021
  this.allocSentinelNode(NODE_TYPE_NET_OPTION_SENTINEL, parentEnd)
@@ -1990,19 +2023,21 @@ export class AstFilterParser {
1990
2023
  return this.throwHeadNode(head);
1991
2024
  }
1992
2025
 
1993
- endOfNetOption(s, beg) {
1994
- const match = this.reNetOptionComma.exec(s.slice(beg));
1995
- return match !== null ? beg + match.index : s.length;
1996
- }
1997
-
1998
2026
  parseNetOption(parent) {
1999
2027
  const parentBeg = this.nodes[parent+NODE_BEG_INDEX];
2000
2028
  const s = this.getNodeString(parent);
2001
- const optionEnd = s.length;
2029
+ const match = this.reNetOption.exec(s) || [];
2030
+ if ( match.length === 0 ) {
2031
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2032
+ this.addFlags(AST_FLAG_HAS_ERROR);
2033
+ this.astError = AST_ERROR_OPTION_UNKNOWN;
2034
+ return { node: 0, len: s.length };
2035
+ }
2002
2036
  const head = this.allocHeadNode();
2003
2037
  let prev = head, next = 0;
2004
- let nameBeg = 0;
2005
- if ( s.charCodeAt(0) === 0x7E ) {
2038
+ const matchEnd = match && match[0].length || 0;
2039
+ const negated = match[1] === '~';
2040
+ if ( negated ) {
2006
2041
  this.addNodeFlags(parent, NODE_FLAG_IS_NEGATED);
2007
2042
  next = this.allocTypedNode(
2008
2043
  NODE_TYPE_NET_OPTION_NAME_NOT,
@@ -2010,11 +2045,11 @@ export class AstFilterParser {
2010
2045
  parentBeg+1
2011
2046
  );
2012
2047
  prev = this.linkRight(prev, next);
2013
- nameBeg += 1;
2014
2048
  }
2015
- const equalPos = s.indexOf('=');
2016
- const nameEnd = equalPos !== -1 ? equalPos : s.length;
2017
- const name = s.slice(nameBeg, nameEnd);
2049
+ const nameBeg = negated ? 1 : 0;
2050
+ const assigned = match[3] === '=';
2051
+ const nameEnd = matchEnd - (assigned ? 1 : 0);
2052
+ const name = match[2] || '';
2018
2053
  let nodeOptionType = nodeTypeFromOptionName.get(name);
2019
2054
  if ( nodeOptionType === undefined ) {
2020
2055
  nodeOptionType = this.reNoopOption.test(name)
@@ -2037,27 +2072,43 @@ export class AstFilterParser {
2037
2072
  this.addNodeToRegister(nodeOptionType, parent);
2038
2073
  }
2039
2074
  prev = this.linkRight(prev, next);
2040
- if ( equalPos === -1 ) {
2041
- return this.throwHeadNode(head);
2075
+ if ( assigned === false ) {
2076
+ return { node: this.throwHeadNode(head), len: matchEnd };
2042
2077
  }
2043
- const valueBeg = equalPos + 1;
2044
2078
  next = this.allocTypedNode(
2045
2079
  NODE_TYPE_NET_OPTION_ASSIGN,
2046
- parentBeg + equalPos,
2047
- parentBeg + valueBeg
2080
+ parentBeg + matchEnd - 1,
2081
+ parentBeg + matchEnd
2048
2082
  );
2049
2083
  prev = this.linkRight(prev, next);
2050
- if ( (equalPos+1) === optionEnd ) {
2051
- this.addNodeFlags(parent, NODE_FLAG_ERROR);
2052
- this.addFlags(AST_FLAG_HAS_ERROR);
2053
- return this.throwHeadNode(head);
2054
- }
2055
2084
  this.addNodeFlags(parent, NODE_FLAG_OPTION_HAS_VALUE);
2085
+ const details = this.netOptionValueParser.nextArg(s, matchEnd);
2086
+ if ( details.quoteBeg !== details.argBeg ) {
2087
+ next = this.allocTypedNode(
2088
+ NODE_TYPE_NET_OPTION_QUOTE,
2089
+ parentBeg + details.quoteBeg,
2090
+ parentBeg + details.argBeg
2091
+ );
2092
+ prev = this.linkRight(prev, next);
2093
+ } else {
2094
+ const argEnd = this.endOfNetOption(s, matchEnd);
2095
+ if ( argEnd !== details.argEnd ) {
2096
+ details.argEnd = details.quoteEnd = argEnd;
2097
+ }
2098
+ }
2056
2099
  next = this.allocTypedNode(
2057
2100
  NODE_TYPE_NET_OPTION_VALUE,
2058
- parentBeg + valueBeg,
2059
- parentBeg + optionEnd
2101
+ parentBeg + details.argBeg,
2102
+ parentBeg + details.argEnd
2060
2103
  );
2104
+ if ( details.argBeg === details.argEnd ) {
2105
+ this.addNodeFlags(parent, NODE_FLAG_ERROR);
2106
+ this.addFlags(AST_FLAG_HAS_ERROR);
2107
+ this.astError = AST_ERROR_OPTION_BADVALUE;
2108
+ } else if ( details.transform ) {
2109
+ const arg = s.slice(details.argBeg, details.argEnd);
2110
+ this.setNodeTransform(next, this.netOptionValueParser.normalizeArg(arg));
2111
+ }
2061
2112
  switch ( nodeOptionType ) {
2062
2113
  case NODE_TYPE_NET_OPTION_NAME_DENYALLOW:
2063
2114
  this.linkDown(next, this.parseDomainList(next, '|'), 0b00000);
@@ -2069,8 +2120,21 @@ export class AstFilterParser {
2069
2120
  default:
2070
2121
  break;
2071
2122
  }
2072
- this.linkRight(prev, next);
2073
- return this.throwHeadNode(head);
2123
+ prev = this.linkRight(prev, next);
2124
+ if ( details.quoteEnd !== details.argEnd ) {
2125
+ next = this.allocTypedNode(
2126
+ NODE_TYPE_NET_OPTION_QUOTE,
2127
+ parentBeg + details.argEnd,
2128
+ parentBeg + details.quoteEnd
2129
+ );
2130
+ this.linkRight(prev, next);
2131
+ }
2132
+ return { node: this.throwHeadNode(head), len: details.quoteEnd };
2133
+ }
2134
+
2135
+ endOfNetOption(s, beg) {
2136
+ const match = this.reNetOptionComma.exec(s.slice(beg));
2137
+ return match !== null ? beg + match.index : s.length;
2074
2138
  }
2075
2139
 
2076
2140
  getNetOptionValue(type) {
@@ -3069,6 +3133,7 @@ export const netOptionTokenDescriptors = new Map([
3069
3133
  [ 'important', { blockOnly: true } ],
3070
3134
  [ 'inline-font', { canNegate: true } ],
3071
3135
  [ 'inline-script', { canNegate: true } ],
3136
+ [ 'ipaddress', { mustAssign: true } ],
3072
3137
  [ 'match-case', { } ],
3073
3138
  [ 'media', { canNegate: true } ],
3074
3139
  [ 'method', { mustAssign: true } ],
@@ -3086,12 +3151,13 @@ export const netOptionTokenDescriptors = new Map([
3086
3151
  /* synonym */ [ 'rewrite', { mustAssign: true } ],
3087
3152
  [ 'redirect-rule', { mustAssign: true } ],
3088
3153
  [ 'removeparam', { } ],
3089
- [ 'replace', { mustAssign: true } ],
3090
3154
  /* synonym */ [ 'queryprune', { } ],
3155
+ [ 'replace', { mustAssign: true } ],
3091
3156
  [ 'script', { canNegate: true } ],
3092
3157
  [ 'shide', { } ],
3093
3158
  /* synonym */ [ 'specifichide', { } ],
3094
3159
  [ 'to', { mustAssign: true } ],
3160
+ [ 'urlskip', { mustAssign: true } ],
3095
3161
  [ 'uritransform', { mustAssign: true } ],
3096
3162
  [ 'xhr', { canNegate: true } ],
3097
3163
  /* synonym */ [ 'xmlhttprequest', { canNegate: true } ],
@@ -4289,6 +4355,7 @@ export const utils = (( ) => {
4289
4355
  [ 'env_safari', 'safari' ],
4290
4356
  [ 'cap_html_filtering', 'html_filtering' ],
4291
4357
  [ 'cap_user_stylesheet', 'user_stylesheet' ],
4358
+ [ 'cap_ipaddress', 'ipaddress' ],
4292
4359
  [ 'false', 'false' ],
4293
4360
  // Hoping ABP-only list maintainers can at least make use of it to
4294
4361
  // help non-ABP content blockers better deal with filters benefiting
@@ -4323,8 +4390,11 @@ export const utils = (( ) => {
4323
4390
  static evaluateExprToken(token, env = []) {
4324
4391
  const not = token.charCodeAt(0) === 0x21 /* ! */;
4325
4392
  if ( not ) { token = token.slice(1); }
4326
- const state = preparserTokens.get(token);
4327
- if ( state === undefined ) { return; }
4393
+ let state = preparserTokens.get(token);
4394
+ if ( state === undefined ) {
4395
+ if ( token.startsWith('cap_') === false ) { return; }
4396
+ state = 'false';
4397
+ }
4328
4398
  return state === 'false' && not || env.includes(state) !== not;
4329
4399
  }
4330
4400