@adguard/agtree 2.1.3 → 2.1.4

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/dist/agtree.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.1.3 (build date: Mon, 21 Oct 2024 08:22:25 GMT)
2
+ * AGTree v2.1.4 (build date: Mon, 25 Nov 2024 16:56:07 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -2357,9 +2357,11 @@ declare class FilterListParser extends ParserBase {
2357
2357
  * @param ast AST to generate
2358
2358
  * @param preferRaw If `true`, then the parser will use `raws.text` property of each rule
2359
2359
  * if it is available. Default is `false`.
2360
+ * @param tolerant If `true`, errors during rule generation will be logged to the console and invalid rules
2361
+ * will be skipped. If `false`, an error will be thrown on the first invalid rule. Default is `true`.
2360
2362
  * @returns Serialized filter list
2361
2363
  */
2362
- static generate(ast: FilterList, preferRaw?: boolean): string;
2364
+ static generate(ast: FilterList, preferRaw?: boolean, tolerant?: boolean): string;
2363
2365
  /**
2364
2366
  * Serializes a filter list node to binary format.
2365
2367
  *
package/dist/agtree.js CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.1.3 (build date: Mon, 21 Oct 2024 08:22:25 GMT)
2
+ * AGTree v2.1.4 (build date: Mon, 25 Nov 2024 16:56:07 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -1913,6 +1913,9 @@ class AgentCommentRuleParser extends ParserBase {
1913
1913
  static serialize(node, buffer) {
1914
1914
  buffer.writeUint8(BinaryTypeMap.AgentRuleNode);
1915
1915
  const count = node.children.length;
1916
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
1917
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
1918
+ // if there are no children in the binary data.
1916
1919
  if (count) {
1917
1920
  buffer.writeUint8(AgentRuleSerializationMap.Children);
1918
1921
  // note: we store the count, because re-construction of the array is faster if we know the length
@@ -1967,6 +1970,11 @@ class AgentCommentRuleParser extends ParserBase {
1967
1970
  }
1968
1971
  prop = buffer.readUint8();
1969
1972
  }
1973
+ // Maybe children are not present in the binary data,
1974
+ // in this case, we should initialize it as an empty array.
1975
+ if (!node.children) {
1976
+ node.children = [];
1977
+ }
1970
1978
  }
1971
1979
  }
1972
1980
 
@@ -2862,6 +2870,9 @@ class HintCommentRuleParser extends ParserBase {
2862
2870
  buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(exports.AdblockSyntax.Adg) ?? 0);
2863
2871
  }
2864
2872
  const count = node.children.length;
2873
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
2874
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
2875
+ // if there are no children in the binary data.
2865
2876
  if (count) {
2866
2877
  buffer.writeUint8(HintRuleSerializationMap.Children);
2867
2878
  // note: we store the count, because re-construction of the array is faster if we know the length
@@ -2915,6 +2926,11 @@ class HintCommentRuleParser extends ParserBase {
2915
2926
  }
2916
2927
  prop = buffer.readUint8();
2917
2928
  }
2929
+ // Maybe children are not present in the binary data,
2930
+ // in this case, we should initialize it as an empty array.
2931
+ if (!node.children) {
2932
+ node.children = [];
2933
+ }
2918
2934
  }
2919
2935
  }
2920
2936
 
@@ -5348,6 +5364,9 @@ class ModifierListParser extends ParserBase {
5348
5364
  static serialize(node, buffer) {
5349
5365
  buffer.writeUint8(BinaryTypeMap.ModifierListNode);
5350
5366
  const count = node.children.length;
5367
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
5368
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
5369
+ // if there are no children in the binary data.
5351
5370
  if (count) {
5352
5371
  buffer.writeUint8(ModifierListNodeSerializationMap.Children);
5353
5372
  // note: we store the count, because re-construction of the array is faster if we know the length
@@ -5399,6 +5418,11 @@ class ModifierListParser extends ParserBase {
5399
5418
  }
5400
5419
  prop = buffer.readUint8();
5401
5420
  }
5421
+ // Maybe children are not present in the binary data,
5422
+ // in this case, we should initialize it as an empty array.
5423
+ if (!node.children) {
5424
+ node.children = [];
5425
+ }
5402
5426
  }
5403
5427
  }
5404
5428
 
@@ -8611,10 +8635,16 @@ class NetworkRuleParser extends ParserBase {
8611
8635
  const pattern = ValueParser.parse(raw.slice(patternStart, patternEnd), options, baseOffset + patternStart);
8612
8636
  // Parse modifiers (if any)
8613
8637
  let modifiers;
8638
+ // Get a last non-whitespace index
8639
+ const lastNonWsIndex = StringUtils.skipWSBack(raw);
8614
8640
  // Find start and end index of the modifiers
8615
8641
  const modifiersStart = separatorIndex + 1;
8616
- const modifiersEnd = StringUtils.skipWSBack(raw) + 1;
8642
+ const modifiersEnd = lastNonWsIndex + 1;
8617
8643
  if (separatorIndex !== -1) {
8644
+ // Check for empty modifiers
8645
+ if (separatorIndex === lastNonWsIndex) {
8646
+ throw new AdblockSyntaxError('Empty modifiers are not allowed', baseOffset + separatorIndex, baseOffset + raw.length);
8647
+ }
8618
8648
  modifiers = ModifierListParser.parse(raw.slice(modifiersStart, modifiersEnd), options, baseOffset + modifiersStart);
8619
8649
  }
8620
8650
  // Throw error if there is no pattern and no modifiers
@@ -8933,6 +8963,9 @@ class HostRuleParser extends ParserBase {
8933
8963
  buffer.writeUint32(node.end);
8934
8964
  }
8935
8965
  const count = node.children.length;
8966
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
8967
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
8968
+ // if there are no children in the binary data.
8936
8969
  if (count) {
8937
8970
  // note: we store the count, because re-construction of the array is faster if we know the length
8938
8971
  if (count > UINT16_MAX) {
@@ -8976,6 +9009,11 @@ class HostRuleParser extends ParserBase {
8976
9009
  }
8977
9010
  prop = buffer.readUint8();
8978
9011
  }
9012
+ // Maybe children are not present in the binary data,
9013
+ // in this case, we should initialize it as an empty array.
9014
+ if (!node.children) {
9015
+ node.children = [];
9016
+ }
8979
9017
  }
8980
9018
  /**
8981
9019
  * Serializes a host rule node to binary format.
@@ -9743,9 +9781,11 @@ class FilterListParser extends ParserBase {
9743
9781
  * @param ast AST to generate
9744
9782
  * @param preferRaw If `true`, then the parser will use `raws.text` property of each rule
9745
9783
  * if it is available. Default is `false`.
9784
+ * @param tolerant If `true`, errors during rule generation will be logged to the console and invalid rules
9785
+ * will be skipped. If `false`, an error will be thrown on the first invalid rule. Default is `true`.
9746
9786
  * @returns Serialized filter list
9747
9787
  */
9748
- static generate(ast, preferRaw = false) {
9788
+ static generate(ast, preferRaw = false, tolerant = true) {
9749
9789
  let result = EMPTY;
9750
9790
  for (let i = 0; i < ast.children.length; i += 1) {
9751
9791
  const rule = ast.children[i];
@@ -9753,7 +9793,18 @@ class FilterListParser extends ParserBase {
9753
9793
  result += rule.raws.text;
9754
9794
  }
9755
9795
  else {
9756
- result += RuleParser.generate(rule);
9796
+ try {
9797
+ result += RuleParser.generate(rule);
9798
+ }
9799
+ catch (error) {
9800
+ if (tolerant) {
9801
+ // eslint-disable-next-line no-console
9802
+ console.error(`Error when generating: ${error}`);
9803
+ }
9804
+ else {
9805
+ throw new Error(String(error));
9806
+ }
9807
+ }
9757
9808
  }
9758
9809
  switch (rule.raws?.nl) {
9759
9810
  case 'crlf':
@@ -14700,7 +14751,7 @@ class RawFilterListConverter extends ConverterBase {
14700
14751
  return createConversionResult(rawFilterList, false);
14701
14752
  }
14702
14753
  // Otherwise, serialize the filter list and return the result
14703
- return createConversionResult(FilterListParser.generate(conversionResult.result), true);
14754
+ return createConversionResult(FilterListParser.generate(conversionResult.result, false, tolerant), true);
14704
14755
  }
14705
14756
  }
14706
14757
 
@@ -15648,7 +15699,7 @@ class RuleCategorizer {
15648
15699
  }
15649
15700
  }
15650
15701
 
15651
- const version = "2.1.3";
15702
+ const version = "2.1.4";
15652
15703
 
15653
15704
  /**
15654
15705
  * @file AGTree version
package/dist/agtree.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /*
2
- * AGTree v2.1.3 (build date: Mon, 21 Oct 2024 08:22:25 GMT)
2
+ * AGTree v2.1.4 (build date: Mon, 25 Nov 2024 16:56:07 GMT)
3
3
  * (c) 2024 Adguard Software Ltd.
4
4
  * Released under the MIT license
5
5
  * https://github.com/AdguardTeam/tsurlfilter/tree/master/packages/agtree#readme
@@ -1893,6 +1893,9 @@ class AgentCommentRuleParser extends ParserBase {
1893
1893
  static serialize(node, buffer) {
1894
1894
  buffer.writeUint8(BinaryTypeMap.AgentRuleNode);
1895
1895
  const count = node.children.length;
1896
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
1897
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
1898
+ // if there are no children in the binary data.
1896
1899
  if (count) {
1897
1900
  buffer.writeUint8(AgentRuleSerializationMap.Children);
1898
1901
  // note: we store the count, because re-construction of the array is faster if we know the length
@@ -1947,6 +1950,11 @@ class AgentCommentRuleParser extends ParserBase {
1947
1950
  }
1948
1951
  prop = buffer.readUint8();
1949
1952
  }
1953
+ // Maybe children are not present in the binary data,
1954
+ // in this case, we should initialize it as an empty array.
1955
+ if (!node.children) {
1956
+ node.children = [];
1957
+ }
1950
1958
  }
1951
1959
  }
1952
1960
 
@@ -2842,6 +2850,9 @@ class HintCommentRuleParser extends ParserBase {
2842
2850
  buffer.writeUint8(SYNTAX_SERIALIZATION_MAP.get(AdblockSyntax.Adg) ?? 0);
2843
2851
  }
2844
2852
  const count = node.children.length;
2853
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
2854
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
2855
+ // if there are no children in the binary data.
2845
2856
  if (count) {
2846
2857
  buffer.writeUint8(HintRuleSerializationMap.Children);
2847
2858
  // note: we store the count, because re-construction of the array is faster if we know the length
@@ -2895,6 +2906,11 @@ class HintCommentRuleParser extends ParserBase {
2895
2906
  }
2896
2907
  prop = buffer.readUint8();
2897
2908
  }
2909
+ // Maybe children are not present in the binary data,
2910
+ // in this case, we should initialize it as an empty array.
2911
+ if (!node.children) {
2912
+ node.children = [];
2913
+ }
2898
2914
  }
2899
2915
  }
2900
2916
 
@@ -5328,6 +5344,9 @@ class ModifierListParser extends ParserBase {
5328
5344
  static serialize(node, buffer) {
5329
5345
  buffer.writeUint8(BinaryTypeMap.ModifierListNode);
5330
5346
  const count = node.children.length;
5347
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
5348
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
5349
+ // if there are no children in the binary data.
5331
5350
  if (count) {
5332
5351
  buffer.writeUint8(ModifierListNodeSerializationMap.Children);
5333
5352
  // note: we store the count, because re-construction of the array is faster if we know the length
@@ -5379,6 +5398,11 @@ class ModifierListParser extends ParserBase {
5379
5398
  }
5380
5399
  prop = buffer.readUint8();
5381
5400
  }
5401
+ // Maybe children are not present in the binary data,
5402
+ // in this case, we should initialize it as an empty array.
5403
+ if (!node.children) {
5404
+ node.children = [];
5405
+ }
5382
5406
  }
5383
5407
  }
5384
5408
 
@@ -8591,10 +8615,16 @@ class NetworkRuleParser extends ParserBase {
8591
8615
  const pattern = ValueParser.parse(raw.slice(patternStart, patternEnd), options, baseOffset + patternStart);
8592
8616
  // Parse modifiers (if any)
8593
8617
  let modifiers;
8618
+ // Get a last non-whitespace index
8619
+ const lastNonWsIndex = StringUtils.skipWSBack(raw);
8594
8620
  // Find start and end index of the modifiers
8595
8621
  const modifiersStart = separatorIndex + 1;
8596
- const modifiersEnd = StringUtils.skipWSBack(raw) + 1;
8622
+ const modifiersEnd = lastNonWsIndex + 1;
8597
8623
  if (separatorIndex !== -1) {
8624
+ // Check for empty modifiers
8625
+ if (separatorIndex === lastNonWsIndex) {
8626
+ throw new AdblockSyntaxError('Empty modifiers are not allowed', baseOffset + separatorIndex, baseOffset + raw.length);
8627
+ }
8598
8628
  modifiers = ModifierListParser.parse(raw.slice(modifiersStart, modifiersEnd), options, baseOffset + modifiersStart);
8599
8629
  }
8600
8630
  // Throw error if there is no pattern and no modifiers
@@ -8913,6 +8943,9 @@ class HostRuleParser extends ParserBase {
8913
8943
  buffer.writeUint32(node.end);
8914
8944
  }
8915
8945
  const count = node.children.length;
8946
+ // If there are no children, we do not write any data related to them, to avoid using unnecessary storage,
8947
+ // but children is a required field, so during deserialization we should initialize it as an empty array,
8948
+ // if there are no children in the binary data.
8916
8949
  if (count) {
8917
8950
  // note: we store the count, because re-construction of the array is faster if we know the length
8918
8951
  if (count > UINT16_MAX) {
@@ -8956,6 +8989,11 @@ class HostRuleParser extends ParserBase {
8956
8989
  }
8957
8990
  prop = buffer.readUint8();
8958
8991
  }
8992
+ // Maybe children are not present in the binary data,
8993
+ // in this case, we should initialize it as an empty array.
8994
+ if (!node.children) {
8995
+ node.children = [];
8996
+ }
8959
8997
  }
8960
8998
  /**
8961
8999
  * Serializes a host rule node to binary format.
@@ -9723,9 +9761,11 @@ class FilterListParser extends ParserBase {
9723
9761
  * @param ast AST to generate
9724
9762
  * @param preferRaw If `true`, then the parser will use `raws.text` property of each rule
9725
9763
  * if it is available. Default is `false`.
9764
+ * @param tolerant If `true`, errors during rule generation will be logged to the console and invalid rules
9765
+ * will be skipped. If `false`, an error will be thrown on the first invalid rule. Default is `true`.
9726
9766
  * @returns Serialized filter list
9727
9767
  */
9728
- static generate(ast, preferRaw = false) {
9768
+ static generate(ast, preferRaw = false, tolerant = true) {
9729
9769
  let result = EMPTY;
9730
9770
  for (let i = 0; i < ast.children.length; i += 1) {
9731
9771
  const rule = ast.children[i];
@@ -9733,7 +9773,18 @@ class FilterListParser extends ParserBase {
9733
9773
  result += rule.raws.text;
9734
9774
  }
9735
9775
  else {
9736
- result += RuleParser.generate(rule);
9776
+ try {
9777
+ result += RuleParser.generate(rule);
9778
+ }
9779
+ catch (error) {
9780
+ if (tolerant) {
9781
+ // eslint-disable-next-line no-console
9782
+ console.error(`Error when generating: ${error}`);
9783
+ }
9784
+ else {
9785
+ throw new Error(String(error));
9786
+ }
9787
+ }
9737
9788
  }
9738
9789
  switch (rule.raws?.nl) {
9739
9790
  case 'crlf':
@@ -14680,7 +14731,7 @@ class RawFilterListConverter extends ConverterBase {
14680
14731
  return createConversionResult(rawFilterList, false);
14681
14732
  }
14682
14733
  // Otherwise, serialize the filter list and return the result
14683
- return createConversionResult(FilterListParser.generate(conversionResult.result), true);
14734
+ return createConversionResult(FilterListParser.generate(conversionResult.result, false, tolerant), true);
14684
14735
  }
14685
14736
  }
14686
14737
 
@@ -15628,7 +15679,7 @@ class RuleCategorizer {
15628
15679
  }
15629
15680
  }
15630
15681
 
15631
- const version = "2.1.3";
15682
+ const version = "2.1.4";
15632
15683
 
15633
15684
  /**
15634
15685
  * @file AGTree version
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adguard/agtree",
3
- "version": "2.1.3",
3
+ "version": "2.1.4",
4
4
  "description": "Tool set for working with adblock filter lists",
5
5
  "keywords": [
6
6
  "adblock",