re2js 2.1.1 → 2.2.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.
@@ -2,7 +2,7 @@
2
2
  * re2js
3
3
  * RE2JS is the JavaScript port of RE2, a regular expression engine that provides linear time matching
4
4
  *
5
- * @version v2.1.1
5
+ * @version v2.2.1
6
6
  * @author Alexey Vasiliev
7
7
  * @homepage https://github.com/le0pard/re2js#readme
8
8
  * @repository github:le0pard/re2js
@@ -46,6 +46,8 @@
46
46
  static UNICODE_GROUPS = 0x80;
47
47
  // Regexp END_TEXT was $, not \z. Internal use only.
48
48
  static WAS_DOLLAR = 0x100;
49
+ // Allow captureless Lookbehinds (?<=) and (?<!)
50
+ static LOOKBEHIND = 0x200;
49
51
  static MATCH_NL = RE2Flags.CLASS_NL | RE2Flags.DOT_NL;
50
52
  // As close to Perl as possible.
51
53
  static PERL = RE2Flags.CLASS_NL | RE2Flags.ONE_LINE | RE2Flags.PERL_X | RE2Flags.UNICODE_GROUPS;
@@ -57,12 +59,31 @@
57
59
  static ANCHOR_BOTH = 2;
58
60
  }
59
61
 
62
+ /**
63
+ * Public flags for RE2JS and RE2Set compilation.
64
+ */
65
+ const PublicFlags = {
66
+ CASE_INSENSITIVE: 1,
67
+ // case insensitive matching
68
+ DOTALL: 2,
69
+ // dot matches all characters, including newline
70
+ MULTILINE: 4,
71
+ // multiline matching
72
+ DISABLE_UNICODE_GROUPS: 8,
73
+ // unicode groups will be syntax errors
74
+ LONGEST_MATCH: 16,
75
+ // matches longest possible string
76
+ LOOKBEHINDS: 512 // enable linear-time captureless lookbehinds
77
+ };
78
+
60
79
  /**
61
80
  * Various constants and helper for unicode codepoints.
62
81
  */
63
82
  const ASCII_SIZE = 128;
64
83
  const ASCII_TO_UPPER = new Int32Array(ASCII_SIZE);
65
84
  const ASCII_TO_LOWER = new Int32Array(ASCII_SIZE);
85
+ // The highest legal Basic Multilingual Plane (BMP) value.
86
+ const MAX_BMP = 0xffff;
66
87
  for (let i = 0; i < ASCII_SIZE; i++) {
67
88
  if (i >= 97 && i <= 122) {
68
89
  // a-z
@@ -86,11 +107,13 @@
86
107
  static toUpperCase(codepoint) {
87
108
  if (codepoint < ASCII_SIZE) return ASCII_TO_UPPER[codepoint];
88
109
  const s = String.fromCodePoint(codepoint).toUpperCase();
89
- if (s.length > 1) {
110
+ const expectedLen = s.codePointAt(0) > MAX_BMP ? 2 : 1;
111
+ if (s.length > expectedLen) {
90
112
  return codepoint;
91
113
  }
92
114
  const sOrigin = String.fromCodePoint(s.codePointAt(0)).toLowerCase();
93
- if (sOrigin.length > 1 || sOrigin.codePointAt(0) !== codepoint) {
115
+ const originExpectedLen = sOrigin.codePointAt(0) > MAX_BMP ? 2 : 1;
116
+ if (sOrigin.length > originExpectedLen || sOrigin.codePointAt(0) !== codepoint) {
94
117
  return codepoint;
95
118
  }
96
119
  return s.codePointAt(0);
@@ -101,11 +124,13 @@
101
124
  static toLowerCase(codepoint) {
102
125
  if (codepoint < ASCII_SIZE) return ASCII_TO_LOWER[codepoint];
103
126
  const s = String.fromCodePoint(codepoint).toLowerCase();
104
- if (s.length > 1) {
127
+ const expectedLen = s.codePointAt(0) > MAX_BMP ? 2 : 1;
128
+ if (s.length > expectedLen) {
105
129
  return codepoint;
106
130
  }
107
131
  const sOrigin = String.fromCodePoint(s.codePointAt(0)).toUpperCase();
108
- if (sOrigin.length > 1 || sOrigin.codePointAt(0) !== codepoint) {
132
+ const originExpectedLen = sOrigin.codePointAt(0) > MAX_BMP ? 2 : 1;
133
+ if (sOrigin.length > originExpectedLen || sOrigin.codePointAt(0) !== codepoint) {
109
134
  return codepoint;
110
135
  }
111
136
  return s.codePointAt(0);
@@ -207,52 +232,52 @@
207
232
  static _CASE_ORBIT = null;
208
233
  static get CASE_ORBIT() {
209
234
  if (!this._CASE_ORBIT) {
210
- this._CASE_ORBIT = decodeOrbit('rCrDIzDYqpII-LiC8cQlHa+0HGrpI6EzClClOBmOBkOBoOBpOBnOBrOBsOBqOlByPBzPBxPyK5crCz+HCydD1dD4dB5dB6dC8dEgeBheCieDmeDpeHj-HCweD1fDxeB+9HBwfC1FE2eBxfBjeBjdD1eDmpIHycB0fEmdBgda6cBhdD4cB1cdyhBC0hBK+hBDhiBBiiBIqiBIgkHChkHKikHDjkHBkkHImkHYjjBBnkH9gGygBB0gBB+gBBhhBBlkHBihBBqhBBijBBqypB4OhzHB70H6BgzHD-GiHo8HBp8HBq8HBr8HBs8HBt8HBu8HBv8HBg8HBh8HBi8HBj8HBk8HBl8HBm8HBn8HB48HB58HB68HB78HB88HB98HB+8HB-8HBw8HBx8HBy8HBz8HB08HB18HB28HB38HBo9HBp9HBq9HBr9HBs9HBt9HBu9HBv9HBg9HBh9HBi9HBj9HBk9HBl9HBm9HBn9HE89HJz9HClaFs+HJj+HHwcQwdQ8-HJz-HqJpdErCBlG-ohBrypBBokH6lVm4+BBl4+B6nCohhCBphhCBqhhCBrhhCBshhCBthhCBuhhCBvhhCBwhhCBxhhCByhhCBzhhCB0hhCB1hhCB2hhCB3hhCB4hhCB5hhCB6hhCB7hhCB8hhCB9hhCB+hhCB-hhCBgihCBhihCBiihCBjihCBkihCBlihCBmihCBnihCBoihCBpihCBqihCBrihCBsihCBtihCBuihCBvihCBgghCBhghCBighCBjghCBkghCBlghCBmghCBnghCBoghCBpghCBqghCBrghCBsghCBtghCBughCBvghCBwghCBxghCByghCBzghCB0ghCB1ghCB2ghCB3ghCB4ghCB5ghCB6ghCB7ghCB8ghCB9ghCB+ghCB-ghCBghhCBhhhCBihhCBjhhCBkhhCBlhhCBmhhCBnhhChD4mhCB5mhCB6mhCB7mhCB8mhCB9mhCB+mhCB-mhCBgnhCBhnhCBinhCBjnhCBknhCBlnhCBmnhCBnnhCBonhCBpnhCBqnhCBrnhCBsnhCBtnhCBunhCBvnhCBwnhCBxnhCBynhCBznhCB0nhCB1nhCB2nhCB3nhCB4nhCB5nhCB6nhCB7nhCFwlhCBxlhCBylhCBzlhCB0lhCB1lhCB2lhCB3lhCB4lhCB5lhCB6lhCB7lhCB8lhCB9lhCB+lhCB-lhCBgmhCBhmhCBimhCBjmhCBkmhCBlmhCBmmhCBnmhCBomhCBpmhCBqmhCBrmhCBsmhCBtmhCBumhCBvmhCBwmhCBxmhCBymhCBzmhC1D3shCB4shCB5shCB6shCB7shCB8shCB9shCB+shCB-shCBgthCBhthCCjthCBkthCBlthCBmthCBnthCBothCBpthCBqthCBrthCBsthCBtthCButhCBvthCBwthCBxthCCzthCB0thCB1thCB2thCB3thCB4thCB5thCC7thCB8thCCwrhCBxrhCByrhCBzrhCB0rhCB1rhCB2rhCB3rhCB4rhCB5rhCB6rhCC8rhCB9rhCB+rhCB-rhCBgshCBhshCBishCBjshCBkshCBlshCBmshCBnshCBoshCBpshCBqshCCsshCBtshCBushCBvshCBwshCBxshCByshCC0shCB1shCk2BgmjCBhmjCBimjCBjmjCBkmjCBlmjCBmmjCBnmjCBomjCBpmjCBqmjCBrmjCBsmjCBtmjCBumjCBvmjCBwmjCBxmjCBymjCBzmjCB0mjCB1mjCB2mjCB3mjCB4mjCB5mjCB6mjCB7mjCB8mjCB9mjCB+mjCB-mjCBgnjCBhnjCBinjCBjnjCBknjCBlnjCBmnjCBnnjCBonjCBpnjCBqnjCBrnjCBsnjCBtnjCBunjCBvnjCBwnjCBxnjCBynjCOgkjCBhkjCBikjCBjkjCBkkjCBlkjCBmkjCBnkjCBokjCBpkjCBqkjCBrkjCBskjCBtkjCBukjCBvkjCBwkjCBxkjCBykjCBzkjCB0kjCB1kjCB2kjCB3kjCB4kjCB5kjCB6kjCB7kjCB8kjCB9kjCB+kjCB-kjCBgljCBhljCBiljCBjljCBkljCBlljCBmljCBnljCBoljCBpljCBqljCBrljCBsljCBtljCBuljCBvljCBwljCBxljCByljC+CwrjCBxrjCByrjCBzrjCB0rjCB1rjCB2rjCB3rjCB4rjCB5rjCB6rjCB7rjCB8rjCB9rjCB+rjCB-rjCBgsjCBhsjCBisjCBjsjCBksjCBlsjCLwqjCBxqjCByqjCBzqjCB0qjCB1qjCB2qjCB3qjCB4qjCB5qjCB6qjCB7qjCB8qjCB9qjCB+qjCB-qjCBgrjCBhrjCBirjCBjrjCBkrjCBlrjC74CgmmCBhmmCBimmCBjmmCBkmmCBlmmCBmmmCBnmmCBommCBpmmCBqmmCBrmmCBsmmCBtmmCBummCBvmmCBwmmCBxmmCBymmCBzmmCB0mmCB1mmCB2mmCB3mmCB4mmCB5mmCB6mmCB7mmCB8mmCB9mmCB+mmCB-mmCBglmCBhlmCBilmCBjlmCBklmCBllmCBmlmCBnlmCBolmCBplmCBqlmCBrlmCBslmCBtlmCBulmCBvlmCBwlmCBxlmCBylmCBzlmCB0lmCB1lmCB2lmCB3lmCB4lmCB5lmCB6lmCB7lmCB8lmCB9lmCB+lmCB-lmChrVgz7CBhz7CBiz7CBjz7CBkz7CBlz7CBmz7CBnz7CBoz7CBpz7CBqz7CBrz7CBsz7CBtz7CBuz7CBvz7CBwz7CBxz7CByz7CBzz7CB0z7CB1z7CB2z7CB3z7CB4z7CB5z7CB6z7CB7z7CB8z7CB9z7CB+z7CB-z7CBgy7CBhy7CBiy7CBjy7CBky7CBly7CBmy7CBny7CBoy7CBpy7CBqy7CBry7CBsy7CBty7CBuy7CBvy7CBwy7CBxy7CByy7CBzy7CB0y7CB1y7CB2y7CB3y7CB4y7CB5y7CB6y7CB7y7CB8y7CB9y7CB+y7CB-y7Ch0eip6DBjp6DBkp6DBlp6DBmp6DBnp6DBop6DBpp6DBqp6DBrp6DBsp6DBtp6DBup6DBvp6DBwp6DBxp6DByp6DBzp6DB0p6DB1p6DB2p6DB3p6DB4p6DB5p6DB6p6DB7p6DB8p6DB9p6DB+p6DB-p6DBgq6DBhq6DBiq6DBjq6DBgo6DBho6DBio6DBjo6DBko6DBlo6DBmo6DBno6DBoo6DBpo6DBqo6DBro6DBso6DBto6DBuo6DBvo6DBwo6DBxo6DByo6DBzo6DB0o6DB1o6DB2o6DB3o6DB4o6DB5o6DB6o6DB7o6DB8o6DB9o6DB+o6DB-o6DBgp6DBhp6D');
235
+ this._CASE_ORBIT = decodeOrbit('rCrDIzDYqpII-LiC8cQlHa+0HGrpI6EzClClOBmOBkOBoOBpOBnOBrOBsOBqOlByPBzPBxPyK5crCz+HCydD1dD4dB5dB6dC8dEgeBheCieDmeDpeHj-HCweD1fDxeB+9HBwfC1FE2eBxfBjeBjdD1eDmpIHycB0fEmdBgda6cBhdD4cB1cdyhBC0hBK+hBDhiBBiiBIqiBIgkHChkHKikHDjkHBkkHImkHYjjBBnkH9gGygBB0gBB+gBBhhBBlkHBihBBqhBBijBBqypB4OhzHB70H6BgzHD-GiHo8HBp8HBq8HBr8HBs8HBt8HBu8HBv8HBg8HBh8HBi8HBj8HBk8HBl8HBm8HBn8HB48HB58HB68HB78HB88HB98HB+8HB-8HBw8HBx8HBy8HBz8HB08HB18HB28HB38HBo9HBp9HBq9HBr9HBs9HBt9HBu9HBv9HBg9HBh9HBi9HBj9HBk9HBl9HBm9HBn9HE89HJz9HClaFs+HJj+HHwcQwdQ8-HJz-HqJpdErCBlG-ohBrypBBokH6lVm4+BBl4+B');
211
236
  }
212
237
  return this._CASE_ORBIT;
213
238
  }
214
239
  static _Print = null;
215
240
  static get Print() {
216
241
  if (!this._Print) {
217
- this._Print = new UnicodeRangeTable(decodeRanges('hB9CBjBLBCpWBDFBFGBCCCBSBCsMBClBBDxBBDCBC2BBJaBFFBSVBC-FBCvBBD6BBDkDBP6BBDwBBDOBCbBDCCBJBGeBJqCBCgFBCHBDBBDVBCGBCEEBCBDIBDBBDDBJFFBCCBDBDYBDCBCFBFBBDVBCGBCBBCBBCBBDCCBDBFBBDCBEIIBCBCIIBPBLCBCIBCCBCVBCGBCBBCEBDJBCCBCCBDQQBCBDLBIGBCCBCHBDBBDVBCGBCBBCEBDIBDBBDCBICBFBBCEBDRBLBBCFBECBCDBEBBCCCBEEBEEBBBELBFEBECBCDBDHHPUBGMBCCBCWBCPBDIBCCBCDBIBBCCBDDDBCBDJBIVBCCBCWBCJBCEBDIBCCBCDBIBBHBBCDBDJBCCBNMBCCBCyBBCCBCFBFPBDZBCCBCRBEXBCIBCDDBFBEFFBEBCCCBGBHJBDCBN5BBFcBmBBBCCCBDBCXBCCCBVBDEBCCCBFBCJBDDBhBnCBCjBBFmBBCjBBCOBCMBmBlGBCGGD4LBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBDfBEZBH1CBDFBD-TBCbBE4CBIVBKXBKTBNMBCCBCBBN9CBDJBHJBHNBCKBH4CBIqBBGlCBLeBCLBFLBFEEBoBBDEBMrBBFZBHKBE9BBDgCBCcBDKBHJBHNBDeByBsCBClFBJ7BBEOBE9BBGqBBDKBJqBBG1QBDFBDlBBDFBDHBCGCBdBD0BBCOBCNBDFBCSBDCBCIBSXBJuBBSBBDaBCMBEgBBQgBBQrEBF5UBXKBWz4BBDfBC8KBGsBBCGGD3BBIBBPXBKGBCGBCGBCGBCGBCGBCGBCGBC9DBjBZBC4CBN1GBbPBC+BBC1CBDmDBGqBBC9CBC1CBKvBBCszcBE2BBK7KBV3FBJtGBDBBCCCBGBW6BBEJBH3BBJlCBJLBHzDBMdBEtCBCKBFgBBC2BBKNBDJBDmDBZbBLFBDFBDFBKGBCGBC7BBF9DBDJBHj9KBNWBFwBBloItLBDpDBnBGBNEBGZBCEBCCCBCCBCCB7DBR8NBD1BBIhBhBBoBBHyBBCSBCDBFEBCmEBF9FBEFBDFBDFBDCBEGBCGBOBBDLBCZBCSBCBBCOBDNBjB6DBGCBFsBBE3CBCMBEwBwBBsBBjEcBEwBBQbBFjBBKdBGqBBGdBCkBBFNBrB9EBDJBHjBBFjBBFnBBJzBBMLBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBCnCBJIBxBSBCBBGgBBEaBGhChCB2BBFTBDxBBCBBGHBCCBCcBDCBFJBIIBI-BBhBmBBFLBK1BBEcBDaBGZBIDBNGBxCoCB4ByBBOyBBItBBJJBHlBBEcBJBBxGeBCpBBCCBDBBRCB4BrBBJpBBXZBnBbBVWBKtCBFjBBK9BBCEBOYBIJBH0BBCRBJmBBK-CBCTBMRBCuBB-BGBCCCBCBCOBCKBH6BBGJBHDBCHBDBBDVBCGBCBBCEBCJBDBBDCBDHHGGBDGBEEBMJBCDDClBBCJBCDDCDBCJBCBBJBBe7CBCEBfnCBJJBnF1BBDlBBjBkCBMJBHMBU5BBHJBHTBdaBDOBFWB6F7BBlDyCBNHBDDDBGBCBBCdBCBBDLBKJBnCHBDtBBDKBcnCBJyCBOoCBIJB3FhBBPJBHIBCsBBCNBLcBEfBDVBCNBqCGBCBBCrBBECCBCCBHBJJBHFBCBBCkBBCBBCFBIJB3JYBIQBCoBBEcB2CQQBwBBO6cBnDuDBCEBMjGBtyCiDBOvhBBRVBL68DBGmSB61G5BBn2B4RBIeBCJBFwCBCJBHdBDFBLlCBLJBCGBCUBGSBxN5BBnG6CBmDqCBF4BBIQBhCEBMBBP3-FBJ1mBBqBJBo3IDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBDDBh7D5HBHzNBtCtBBDWBKzDB9B1HBLmBBDpCBJvDBWlCB7DTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBD9VBQEBCOBxiBeBHFB2GGBCQBDGBCBBCEBG9BBiBxDxDBrBBENBDJBFBBhKeBS5BBGxOxOBoBB3GqBBFhPhPBFBCDBCBBCOBCkGBDPBqBrCBFJBFBByYjCBtC8BBjGDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBBvIrBBFjDBNOBDOBCOBCkBBLtFB5BcBOrBBFIBIBBPFB7E3eBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBClDBngB-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEBxq3VvHB', false));
242
+ this._Print = new UnicodeRangeTable(decodeRanges('hB9CBjBLBCpWBDFBFGBCCCBSBCsMBClBBDxBBDCBC2BBJaBFFBSVBC-FBCvBBD6BBDkDBP6BBDwBBDOBCbBDCCBJBGfBIqCBCgFBCHBDBBDVBCGBCEEBCBDIBDBBDDBJFFBCCBDBDYBDCBCFBFBBDVBCGBCBBCBBCBBDCCBDBFBBDCBEIIBCBCIIBPBLCBCIBCCBCVBCGBCBBCEBDJBCCBCCBDQQBCBDLBIGBCCBCHBDBBDVBCGBCBBCEBDIBDBBDCBICBFBBCEBDRBLBBCFBECBCDBEBBCCCBEEBEEBBBELBFEBECBCDBDHHPUBGMBCCBCWBCPBDIBCCBCDBIBBCCBCBBDDBDJBIVBCCBCWBCJBCEBDIBCCBCDBIBBGCBCDBDJBCCBNMBCCBCyBBCCBCFBFPBDZBCCBCRBEXBCIBCDDBFBEFFBEBCCCBGBHJBDCBN5BBFcBmBBBCCCBDBCXBCCCBVBDEBCCCBFBCJBDDBhBnCBCjBBFmBBCjBBCOBCMBmBlGBCGGD4LBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBDfBEZBH1CBDFBD-TBCbBE4CBIVBKXBKTBNMBCCBCBBN9CBDJBHJBHNBCKBH4CBIqBBGlCBLeBCLBFLBFEEBoBBDEBMrBBFZBHKBE9BBDgCBCcBDKBHJBHNBDtBBDLBVsCBClFBJ7BBEOBE9BBGqBBDKBJqBBG1QBDFBDlBBDFBDHBCGCBdBD0BBCOBCNBDFBCSBDCBCIBSXBJuBBSBBDaBCMBEhBBPgBBQrEBF5UBXKBWz4BBD9LBGsBBCGGD3BBIBBPXBKGBCGBCGBCGBCGBCGBCGBCGBC9DBjBZBC4CBN1GBbPBC+BBC1CBDmDBGqBBC9CBC1CBKvBBCszcBE2BBK7KBV3FBJ8GBV7BBEJBH3BBJlCBJLBHzDBMdBEtCBCKBFgBBC2BBKNBDJBDmDBZbBLFBDFBDFBKGBCGBC7BBF9DBDJBHj9KBNWBFwBBloItLBDpDBnBGBNEBGZBCEBCCCBCCBCCBoUBhBpBBHyBBCSBCDBFEBCmEBF9FBEFBDFBDFBDCBEGBCGBOBBDLBCZBCSBCBBCOBDNBjB6DBGCBFsBBE3CBCMBEwBwBBsBBjEcBEwBBQbBFjBBKdBGqBBGdBCkBBFNBrB9EBDJBHjBBFjBBFnBBJzBBMLBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBCnCBJIBxBSBCBBGgBBEaBGaBnB3BBFTBDxBBCBBGHBCCBCcBDCBFJBIIBI-BBhBmBBFLBK1BBEcBDaBGZBIDBNGBxCoCB4ByBBOyBBItBBJJBHlBBEcBJBBxGeBCpBBCCBDBBRFBJIBiBtBBJpBBXZBnBbBVWBKtCBFjBBK9BBCEBOYBIJBH0BBCRBJmBBK-CBCTBMRBCuBB-BGBCCCBCBCOBCKBH6BBGJBHDBCHBDBBDVBCGBCBBCEBCJBDBBDCBDHHGGBDGBEEBMJBCDDClBBCJBCDDCDBCJBCBBJBBe7CBCEBfnCBJJBnF1BBDlBBjBkCBMJBHMBU5BBHJBHTBdaBDOBFWB6F7BBlDyCBNHBDDDBGBCBBCdBCBBDLBKJBnCHBDtBBDKBcnCBJyCBOoCBIJB3CHB5ChBBPJBHIBCsBBCNBLcBEfBDVBCNBqCGBCBBCrBBECCBCCBHBJJBHFBCBBCkBBCBBCFBIJBHrBBFJB3HYBIQBCoBBEcB2CQQBwBBO6cBnDuDBCEBMjGBtyCiDBOvhBBRVBL68DBGmSB61G5BBn2B4RBIeBCJBFwCBCJBHdBDFBLlCBLJBCGBCUBGSBxN5BBnG6CBGYBDYBtBqCBF4BBIQBhCEBMGBK1mHBqBfBiDyDB+vIDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBDDBh7D8HBEzNBHWBQQBQtBBDWBKzDB9B1HBLmBBDpCBJvDBWlCB7DTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBD9VBQEBCOBxiBeBHFB2GGBCQBDGBCBBCEBG9BBiBxDxDBrBBENBDJBFBBhKeBS5BBGxOxOBoBB3GqBBFhGhGBdBCVBJBBhHGBCDBCBBCOBCkGBDPBqBrCBFJBFBByYjCBtC8BBjGDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBBvIrBBFjDBNOBDOBCOBCkBBLtFB5BcBOrBBFIBIBBPFB7E4eBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBBPIBoB3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBCmDBmgB-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIBnkzVvHB', false));
218
243
  }
219
244
  return this._Print;
220
245
  }
221
246
  static CATEGORIES = new LazyMap({
222
- C: () => new UnicodeRangeTable(decodeRanges('AfBgDgBBOrWrWBHHBCBICCVuMuMnBBBzBBBE4B4BBGBcDBHQBXhGhGxBBB8BBBmDNB8BBByBBBQddBCCMEBgBHBsCiFiFJBBDBBXIICCBFBBKBBDBBFHBCDBDGGBaaBEEHDBDBBXIIDGDBCCGDBDBBECBCGBFCCBFBSJBEKKEXXIDDGBBLIEBCCBNBFBBNGBIEEJBBDBBXIIDGGBKKBDDBEEBFBEDBDGGBTTBIBDHHBBBEFFBBBDCCDCBDCBECBNDBGCBEFFBCCBEBCNBWEBOEEYRRBKKEFFBFBDEEBCCBFFBLLBFBXEEYLLGBBKEEFGBDFBDFFBLLELBOEE0BEEHDBRBBbEETCBZKKCBBICBCDBHCCJFBLBBELB7BDBekBBDCCGZZCYYBGGCIILBBFfBpClBlBBCBoBlBlBQOOBjBBnGCCBDBCBB6LFFBIICFFBqBqBFBBiBFFBIICFFBQQ6BFFBkCkCBhBhBBBBbFB3CBBHBB+UCB6CGBXIBZIBVLBOEEDLB-CBBLFBLFBPMMBEB6CGBsBEBnCJBgBNNBCBNDBCCBrBBBGKBtBDBbFBMCB-BBBiCeeBMMBEBLFBPBBgBwBBuCnFnFBGB9BCBQCB-BEBsBBBMHBsBEB3QBBHBBnBBBHBBJGCgBBB2BQQPBBHUUBEEKMMBDBbEByBPBDBBcOOBBBiBOBiBOBtEDB7UVBMUB14BBBhB+K+KBDBuBCCBDBCBB5BGBDNBZIBI4BI-DhBBb6C6CBKB3GZBxC3C3CBoDoDBDBsB-C-C3CIBxBuzcuzcBBB4BIB9KTB5FHBvGBBDCCJUB8BCBLFB5BHBnCHBNFB1DKBfCBvCMMBCBiB4B4BBHBPBBLBBoDXBdJBHBBHBBHIBIII9BDB-DBBLFBl9KLBYDByBjoIBvLBBrDlBBILBGEBbGGCGD+DPB+NBB3BGBCfBrBFB0BUUFDBGoEoEBCB-FCBHBBHBBHBBECBIIIBLBDBBNbbUDDQBBPhBB8DEBEDBuBCB5COOBBBCuBBvBhEBeCByBOBdDBlBIBfEBsBEBfmBmBBCBPpBB-EBBLFBlBDBlBDBpBHB1BKBNQQIDDMQQIDDBBB1BLB4JIBXJBJXBHrBrBKkCBHBBCtBtBDCBCBBYpCpCBGBKvBBUDDBDBiBCBcEBC-BB5BDBVBBzBDDBDBJEEeBBEDBLGBKGBhCfBoBDBNIB3BCBeBBcEBbGBFLBIvCBqC2BB0BMB0BGBvBHBLFBnBCBeHBDvGBgBrBrBEBBDPBE2BBtBHBrBVBblBBdTBYIBvCDBlBIB-BGGBLBaGBLFB2BTTBGBoBIBhDVVBJBTwBwBB8BBICCFQQMFB8BEBLFBFJJBDDBXXIDDGLLBDDBEEBCCBEBCEBIBBICBGKBLCCBCCnBLLCBBCFFLDDBGBDcB9CGGBcBpCHBLlFB3BBBnBhBBmCKBLFBOSB7BFBLFBVbBcBBQDBY4FB9BjDB0CLBJBBCBBJDDfDDBNNBHBLlCBJBBvBBBMaBpCHB0CMBqCGBL1FBjBNBLFBKuBuBPJBeCBhBBBXPPBnCBIDDtBCBCDDKHBLFBHDDmBDDHGBL1JBaGBSqBqBBBBe0CBCOBzBMB8clDBwDGGBJBlGryCBkDMBxhBPBXJB88DEBoS41GB7Bl2BB6RGBgBLLBCByCLLBEBfBBHJBnCJBLIIWEBUvNB7BlGB8CkDBsCDB6BGBS-BBGKBDNB5-FHB3mBoBBLm3IBFIIDkJkJBNBCcBEBBCNBFHBtMjoCBsDEBOCBKGBLBBF-6DB7HFB1NrCBvBBBYIB1D7BB3HJBoBBBrCHBxDUBnC5DBVLBVLB4CIBamEB2CoCoCDBBCBBDBBFNNCIIiCFFBJJIddFGGCCBI1K1KBlJlJB-V-VBNBGQQBuiBBgBFBH0GBISSBIIDGGBDB-BgBBCvDBuBCBPBBLDBD-JBgBQB7BEBCvOBrB1GBsBDBC-OBIFFDQQmGBBRoBBtCDBLDBDwYBlCrCB+BhGBFccDCCBCCLFFCCCBEBCDBCECEDDCBBCICDCCBFFIKFCLLSEBEGGSzBBDtIBtBDBlDLBQBBQQQmBJBvF3BBeMBtBDBKGBDNBH5EB5eDBSCBOCB4DDBgDFBNDBCOBNDB5BHBLFBpBHBfBBNDBD9BB1KLBPBBOCBLEB5BGBQBBMFBKGB0EnDnDBkgBBh3pBfB7hEFB-GBBj0FNBypHOBvThtCB-QhvBBs6EEBhjEvq3VBxHvw-FB', false)),
247
+ C: () => new UnicodeRangeTable(decodeRanges('AfBgDgBBOrWrWBHHBCBICCVuMuMnBBBzBBBE4B4BBGBcDBHQBXhGhGxBBB8BBBmDNB8BBByBBBQddBCCMEBhBGBsCiFiFJBBDBBXIICCBFBBKBBDBBFHBCDBDGGBaaBEEHDBDBBXIIDGDBCCGDBDBBECBCGBFCCBFBSJBEKKEXXIDDGBBLIEBCCBNBFBBNGBIEEJBBDBBXIIDGGBKKBDDBEEBFBEDBDGGBTTBIBDHHBBBEFFBBBDCCDCBDCBECBNDBGCBEFFBCCBEBCNBWEBOEEYRRBKKEFFBFBDEEDBBFBBLGBXEEYLLGBBKEEFGBDEBEFFBLLELBOEE0BEEHDBRBBbEETCBZKKCBBICBCDBHCCJFBLBBELB7BDBekBBDCCGZZCYYBGGCIILBBFfBpClBlBBCBoBlBlBQOOBjBBnGCCBDBCBB6LFFBIICFFBqBqBFBBiBFFBIICFFBQQ6BFFBkCkCBhBhBBBBbFB3CBBHBB+UCB6CGBXIBZIBVLBOEEDLB-CBBLFBLFBPMMBEB6CGBsBEBnCJBgBNNBCBNDBCCBrBBBGKBtBDBbFBMCB-BBBiCeeBMMBEBLFBPBBvBBBNTBuCnFnFBGB9BCBQCB-BEBsBBBMHBsBEB3QBBHBBnBBBHBBJGCgBBB2BQQPBBHUUBEEKMMBDBbEByBPBDBBcOOBBBjBNBiBOBtEDB7UVBMUB14BBB-LEBuBCCBDBCBB5BGBDNBZIBI4BI-DhBBb6C6CBKB3GZBxC3C3CBoDoDBDBsB-C-C3CIBxBuzcuzcBBB4BIB9KTB5FHB+GTB9BCBLFB5BHBnCHBNFB1DKBfCBvCMMBCBiB4B4BBHBPBBLBBoDXBdJBHBBHBBHIBIII9BDB-DBBLFBl9KLBYDByBjoIBvLBBrDlBBILBGEBbGGCGDrUfBrBFB0BUUFDBGoEoEBCB-FCBHBBHBBHBBECBIIIBLBDBBNbbUDDQBBPhBB8DEBEDBuBCB5COOBBBCuBBvBhEBeCByBOBdDBlBIBfEBsBEBfmBmBBCBPpBB-EBBLFBlBDBlBDBpBHB1BKBNQQIDDMQQIDDBBB1BLB4JIBXJBJXBHrBrBKkCBHBBCtBtBDCBCBBYpCpCBGBKvBBUDDBDBiBCBcEBclBB5BDBVBBzBDDBDBJEEeBBEDBLGBKGBhCfBoBDBNIB3BCBeBBcEBbGBFLBIvCBqC2BB0BMB0BGBvBHBLFBnBCBeHBDvGBgBrBrBEBBDPBHHBKgBBvBHBrBVBblBBdTBYIBvCDBlBIB-BGGBLBaGBLFB2BTTBGBoBIBhDVVBJBTwBwBB8BBICCFQQMFB8BEBLFBFJJBDDBXXIDDGLLBDDBEEBCCBEBCEBIBBICBGKBLCCBCCnBLLCBBCFFLDDBGBDcB9CGGBcBpCHBLlFB3BBBnBhBBmCKBLFBOSB7BFBLFBVbBcBBQDBY4FB9BjDB0CLBJBBCBBJDDfDDBNNBHBLlCBJBBvBBBMaBpCHB0CMBqCGBL1CBJ3CBjBNBLFBKuBuBPJBeCBhBBBXPPBnCBIDDtBCBCDDKHBLFBHDDmBDDHGBLFBtBDBL1HBaGBSqBqBBBBe0CBCOBzBMB8clDBwDGGBJBlGryCBkDMBxhBPBXJB88DEBoS41GB7Bl2BB6RGBgBLLBCByCLLBEBfBBHJBnCJBLIIWEBUvNB7BlGB8CEBaBBarBBsCDB6BGBS-BBGKBIIB3mHoBBhBgDB0D8vIBFIIDkJkJBNBCcBEBBCNBFHBtMjoCBsDEBOCBKGBLBBF-6DB+HCB1NFBYOBSOBvBBBYIB1D7BB3HJBoBBBrCHBxDUBnC5DBVLBVLB4CIBamEB2CoCoCDBBCBBDBBFNNCIIiCFFBJJIddFGGCCBI1K1KBlJlJB-V-VBNBGQQBuiBBgBFBH0GBISSBIIDGGBDB-BgBBCvDBuBCBPBBLDBD-JBgBQB7BEBCvOBrB1GBsBDBC-FBgBXXBGBD-GBIFFDQQmGBBRoBBtCDBLDBDwYBlCrCB+BhGBFccDCCBCCLFFCCCBEBCDBCECEDDCBBCICDCCBFFIKFCLLSEBEGGSzBBDtIBtBDBlDLBQBBQQQmBJBvF3BBeMBtBDBKGBDNBH5EB6eCBSCBOCB7GFBNDBCOBNDB5BHBLFBpBHBfBBNDBDNBKmBB5KHBPBBOCBMCB6BCCBCBRBBNDBLGB0EoDoDBjgBBh3pBfB-oEBBv0FBBypHOBvThtCB-QhvBBs6EEBrpIlkzVBxHvw-FB', false)),
223
248
  Cc: () => new UnicodeRangeTable(decodeRanges('AfgDgB', true)),
224
249
  Cf: () => new UnicodeRangeTable(decodeRanges('tFzqBzqBBEBXhGhGyBhMhMBxCxCs5D9-B9-BBDBbEByBEBCJBw03B6H6HBBBimEQQj7IPBhjiBDBwmFHBn0rYffB+CB', false)),
225
- Cn: () => new UnicodeRangeTable(decodeRanges('4bBBHDBICCVuMuMnBBBzBBBE4B4BBGBcDBHKBvI9B9BBmDmDBMB8BBByBBBQddBCCMEBgBDDBDBuHJJBDDBXXICCBBBFBBKBBDBBFHBCDBDGGBaaBEEHDBDBBXIIDGDBCCGDBDBBECBCGBFCCBFBSJBEKKEXXIDDGBBLIEBCCBNBFBBNGBIEEJBBDBBXIIDGGBKKBDDBEEBFBEDBDGGBTTBIBDHHBBBEFFBBBDCCDCBDCBECBNDBGCBEFFBCCBEBCNBWEBOEEYRRBKKEFFBFBDEEBCCBFFBLLBFBXEEYLLGBBKEEFGBDFBDFFBLLELBOEE0BEEHDBRBBbEETCBZKKCBBICBCDBHCCJFBLBBELB7BDBekBBDCCGZZCYYBGGCIILBBFfBpClBlBBCBoBlBlBQOOBjBBnGCCBDBCBB6LFFBIICFFBqBqBFBBiBFFBIICFFBQQ6BFFBkCkCBhBhBBBBbFB3CBBHBB+UCB6CGBXIBZIBVLBOEEDLB-CBBLFBLFBbFB6CGBsBEBnCJBgBNNBCBNDBCCBrBBBGKBtBDBbFBMCB-BBBiCeeBMMBEBLFBPBBgBwBBuCnFnFBGB9BCBQCB-BEBsBBBMHBsBEB3QBBHBBnBBBHBBJGCgBBB2BQQPBBHUUBEEKmDmDNBBcOOBBBiBOBiBOBtEDB7UVBMUB14BBBhB+K+KBDBuBCCBDBCBB5BGBDNBZIBI4BI-DhBBb6C6CBKB3GZBxC3C3CBoDoDBDBsB-C-C3CIBxBuzcuzcBBB4BIB9KTB5FHBvGBBDCCJUB8BCBLFB5BHBnCHBNFB1DKBfCBvCMMBCBiB4B4BBHBPBBLBBoDXBdJBHBBHBBHIBIII9BDB-DBBLFBl9KLBYDByBDBvzIBBrDlBBILBGEBbGGCGD+DPB+NBB3BGBCfBrBFB0BUUFDBGoEoEBCC-FCBHBBHBBHBBECBIIIBIBGBBNbbUDDQBBPhBB8DEBEDBuBCB5COOBBBCuBBvBhEBeCByBOBdDBlBIBfEBsBEBfmBmBBCBPpBB-EBBLFBlBDBlBDBpBHB1BKBNQQIDDMQQIDDBBB1BLB4JIBXJBJXBHrBrBKkCBHBBCtBtBDCBCBBYpCpCBGBKvBBUDDBDBiBCBcEBC-BB5BDBVBBzBDDBDBJEEeBBEDBLGBKGBhCfBoBDBNIB3BCBeBBcEBbGBFLBIvCBqC2BB0BMB0BGBvBHBLFBnBCBeHBDvGBgBrBrBEBBDPBE2BBtBHBrBVBblBBdTBYIBvCDBlBIBlCJBCBBaGBLFB2BTTBGBoBIBhDVVBJBTwBwBB8BBICCFQQMFB8BEBLFBFJJBDDBXXIDDGLLBDDBEEBCCBEBCEBIBBICBGKBLCCBCCnBLLCBBCFFLDDBGBDcB9CGGBcBpCHBLlFB3BBBnBhBBmCKBLFBOSB7BFBLFBVbBcBBQDBY4FB9BjDB0CLBJBBCBBJDDfDDBNNBHBLlCBJBBvBBBMaBpCHB0CMBqCGBL1FBjBNBLFBKuBuBPJBeCBhBBBXPPBnCBIDDtBCBCDDKHBLFBHDDmBDDHGBL1JBaGBSqBqBBBBe0CBCOBzBMB8clDBwDGGBJBlGryCBkDMB3iBJB88DEBoS41GB7Bl2BB6RGBgBLLBCByCLLBEBfBBHJBnCJBLIIWEBUvNB7BlGB8CkDBsCDB6BGBS-BBGKBDNB5-FHB3mBoBBLm3IBFIIDkJkJBNBCcBEBBCNBFHBtMjoCBsDEBOCBKGBLBBJ76DB7HFB1NrCBvBBBYIB1D7BB3HJBoBBBjGUBnC5DBVLBVLB4CIBamEB2CoCoCDBBCBBDBBFNNCIIiCFFBJJIddFGGCCBI1K1KBlJlJB-V-VBNBGQQBuiBBgBFBH0GBISSBIIDGGBDB-BgBBCvDBuBCBPBBLDBD-JBgBQB7BEBCvOBrB1GBsBDBC-OBIFFDQQmGBBRoBBtCDBLDBDwYBlCrCB+BhGBFccDCCBCCLFFCCCBEBCDBCECEDDCBBCICDCCBFFIKFCLLSEBEGGSzBBDtIBtBDBlDLBQBBQQQmBJBvF3BBeMBtBDBKGBDNBH5EB5eDBSCBOCB4DDBgDFBNDBCOBNDB5BHBLFBpBHBfBBNDBD9BB1KLBPBBOCBLEB5BGBQBBMFBKGB0EnDnDBkgBBh3pBfB7hEFB-GBBj0FNBypHOBvThtCB-QhvBBs6EEBhjEwi3VBCdBhD-DBxHvw-BB---BBB---BBB', false)),
250
+ Cn: () => new UnicodeRangeTable(decodeRanges('4bBBHDBICCVuMuMnBBBzBBBE4B4BBGBcDBHKBvI9B9BBmDmDBMB8BBByBBBQddBCCMEBjBEBuHJJBDDBXXICCBBBFBBKBBDBBFHBCDBDGGBaaBEEHDBDBBXIIDGDBCCGDBDBBECBCGBFCCBFBSJBEKKEXXIDDGBBLIEBCCBNBFBBNGBIEEJBBDBBXIIDGGBKKBDDBEEBFBEDBDGGBTTBIBDHHBBBEFFBBBDCCDCBDCBECBNDBGCBEFFBCCBEBCNBWEBOEEYRRBKKEFFBFBDEEDBBFBBLGBXEEYLLGBBKEEFGBDEBEFFBLLELBOEE0BEEHDBRBBbEETCBZKKCBBICBCDBHCCJFBLBBELB7BDBekBBDCCGZZCYYBGGCIILBBFfBpClBlBBCBoBlBlBQOOBjBBnGCCBDBCBB6LFFBIICFFBqBqBFBBiBFFBIICFFBQQ6BFFBkCkCBhBhBBBBbFB3CBBHBB+UCB6CGBXIBZIBVLBOEEDLB-CBBLFBLFBbFB6CGBsBEBnCJBgBNNBCBNDBCCBrBBBGKBtBDBbFBMCB-BBBiCeeBMMBEBLFBPBBvBBBNTBuCnFnFBGB9BCBQCB-BEBsBBBMHBsBEB3QBBHBBnBBBHBBJGCgBBB2BQQPBBHUUBEEKmDmDNBBcOOBBBjBNBiBOBtEDB7UVBMUB14BBB-LEBuBCCBDBCBB5BGBDNBZIBI4BI-DhBBb6C6CBKB3GZBxC3C3CBoDoDBDBsB-C-C3CIBxBuzcuzcBBB4BIB9KTB5FHB+GTB9BCBLFB5BHBnCHBNFB1DKBfCBvCMMBCBiB4B4BBHBPBBLBBoDXBdJBHBBHBBHIBIII9BDB-DBBLFBl9KLBYDByBDBvzIBBrDlBBILBGEBbGGCGDrUfBrBFB0BUUFDBGoEoEBCC-FCBHBBHBBHBBECBIIIBIBGBBNbbUDDQBBPhBB8DEBEDBuBCB5COOBBBCuBBvBhEBeCByBOBdDBlBIBfEBsBEBfmBmBBCBPpBB-EBBLFBlBDBlBDBpBHB1BKBNQQIDDMQQIDDBBB1BLB4JIBXJBJXBHrBrBKkCBHBBCtBtBDCBCBBYpCpCBGBKvBBUDDBDBiBCBcEBclBB5BDBVBBzBDDBDBJEEeBBEDBLGBKGBhCfBoBDBNIB3BCBeBBcEBbGBFLBIvCBqC2BB0BMB0BGBvBHBLFBnBCBeHBDvGBgBrBrBEBBDPBHHBKgBBvBHBrBVBblBBdTBYIBvCDBlBIBlCJBCBBaGBLFB2BTTBGBoBIBhDVVBJBTwBwBB8BBICCFQQMFB8BEBLFBFJJBDDBXXIDDGLLBDDBEEBCCBEBCEBIBBICBGKBLCCBCCnBLLCBBCFFLDDBGBDcB9CGGBcBpCHBLlFB3BBBnBhBBmCKBLFBOSB7BFBLFBVbBcBBQDBY4FB9BjDB0CLBJBBCBBJDDfDDBNNBHBLlCBJBBvBBBMaBpCHB0CMBqCGBL1CBJ3CBjBNBLFBKuBuBPJBeCBhBBBXPPBnCBIDDtBCBCDDKHBLFBHDDmBDDHGBLFBtBDBL1HBaGBSqBqBBBBe0CBCOBzBMB8clDBwDGGBJBlGryCBkDMB3iBJB88DEBoS41GB7Bl2BB6RGBgBLLBCByCLLBEBfBBHJBnCJBLIIWEBUvNB7BlGB8CEBaBBarBBsCDB6BGBS-BBGKBIIB3mHoBBhBgDB0D8vIBFIIDkJkJBNBCcBEBBCNBFHBtMjoCBsDEBOCBKGBLBBJ76DB+HCB1NFBYOBSOBvBBBYIB1D7BB3HJBoBBBjGUBnC5DBVLBVLB4CIBamEB2CoCoCDBBCBBDBBFNNCIIiCFFBJJIddFGGCCBI1K1KBlJlJB-V-VBNBGQQBuiBBgBFBH0GBISSBIIDGGBDB-BgBBCvDBuBCBPBBLDBD-JBgBQB7BEBCvOBrB1GBsBDBC-FBgBXXBGBD-GBIFFDQQmGBBRoBBtCDBLDBDwYBlCrCB+BhGBFccDCCBCCLFFCCCBEBCDBCECEDDCBBCICDCCBFFIKFCLLSEBEGGSzBBDtIBtBDBlDLBQBBQQQmBJBvF3BBeMBtBDBKGBDNBH5EB6eCBSCBOCB7GFBNDBCOBNDB5BHBLFBpBHBfBBNDBDNBKmBB5KHBPBBOCBMCB6BCCBCBRBBNDBLGB0EoDoDBjgBBh3pBfB-oEBBv0FBBypHOBvThtCB-QhvBBs6EEBrpIm8yVBCdBhD-DBxHvw-BB---BBB---BBB', false)),
226
251
  Co: () => new UnicodeRangeTable(decodeRanges('gg4B-nGh4hc9--BD9--B', true)),
227
252
  Cs: () => new UnicodeRangeTable(decodeRanges('gg2B--B', true)),
228
- L: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBLLFGGBVBCeBCpOBFLBPEBICCiEEBCBBDDBCHHCCBCCCBSBCyCBCqEBJlFBClBBDHHBnBBoCaBFDBuBqBBkBBBCiDBCQQBIIBLLBBBDRRCdBe4CBMZZBfBKBBFGGBUBFKKEYYBXBIKBGXBCFBSpBB7B1BBETTIJBQPBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBDDDBffFHBCCBCWBCJBCEBEgBgBBCCBQQBSSBHBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNGB7BBBCCCBDBCXBCCCBIBCBBKDDBDBCWWBCBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNSSBkBBCGGDqBBCsKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPBR1CBDFBErTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBkBFFkC4CBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBzC+C+CBtBBSHB3BdBOBBLrBBbjBBqBCBLjBBDKBGqBBDCBqBDBCFBCBBEGGB+FBhC1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGB1DOORMBmDFFDJBCEEBDBHGCBCBCKBDDBGEBF1B1BB8zC8zCBjHBHDBEBBNlBBCGGD3BBIRRBVBKGBCGBCGBCGBCGBCGBCGBCGBxC2O2OBrBrBBDBGBBF1CBHCBC5CBCDBGqBBC9CBSfBxBPBhQ-tGBhCs0VBkCtBBDsIBEPBLBBVuBBReBDlCByBIBDmDBDiCBDBBCCCBGBWPBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBdRRBDBCJBLEBCoBBYCBCHBVWBEEEBwBBCEEBDDBDBDCCZCBDKBICBNFBDFBDFBKGBCGBCqBBCNBHyDBej9KBNWBFwBBloItLBDpDBnBGBNEBGCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBlBZBHZBM4CBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBxB9EBTjBBFjBBFnBBJzBBNKBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBnC3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4ByBBOyBBOjBBnBbBKWB7HpBBHBBRCB8BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB1D-BBgBHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPoKoKBRBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBBRDBgBUBGSBxNsBB0G-BBhEqCBGjCjCBLBhCBBCddB2-FBJ1mBBqBJBo3IDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBn7F0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BeBHFBmI9BBzEsBBLGBRiKiKBcBTrBBlPbBlHdBDwPwPBFBCDBCBBCOBCkGB8BjCBI1lB1lBBCBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEB', false)),
229
- LC: () => new UnicodeRangeTable(decodeRanges('hCZBHZB7BLLBVBCeBCiGBCDBFvGBCaBhGDBDBBECBCHHCCBCCCBSBCyCBCqEBJlFBClBBKoBB44ClBBCGGDqBBDCBhV1CBDFBjkCKBGqBBDCBhCrBBgCMBChBBmD1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGBmIFFDJBCEEBDBHGCBCBCFBFDDBCBGEBF1B1BB8zC8zCB6DBDmDBHDBEBBNlBBCGGzoetBBTbBnEtCBCWBEDBC9BBDBBCCCBGBZBBE2Z2ZBpBBGIBIvCBh6TGBNEBqgBZBHZBmlBvCBhDjBBFjBB1DKBCOBCGBCBBCKBCOBCGBCBBk2ByBBOyBB+CVBLVB74C-BBhrV-BBhsZ0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BJBCTBHFB2uCjCB', false)),
230
- Ll: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBC2BCBQCBuBCDECBBBDCCDEEBFFDEEBBBDDDCCCDCCBCCDEECDDBDDBBBHGDCOCBSCBDDCEEC4BCBFBDDDBCCFICBjCBCaBiGCCEEEBBBTccBhBBCBBECBCWCBDBCGDB0B0BBuBBCgBCK0BCDMCBgDCxBoBBo6CqBBDCB5XFBjkCIBC2D2DBqBBgCMBChBBnD0ECBHBCgDCBHBJFBLHBJHBJFBLHBJHBJNBDHBJHBJHBJEBCBBHEEBBBCBBJDBDBBJHBLCBCBBzIEEBEEcKFDBBJDBF2B2Bs1CvBBCEEBGCFCCBCCBEBGiDCBIICFFNlBBCGG0oesBCUaCoEMCBBBC+BCBGBCCCDICFCCDCCBBBCSCGGGCMCFCCDEECICbEE2ZqBBGIBIvCBh6TGBNEBqhBZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfB7sZZBbGBCRBbZBbDBCCCBFBCKBbZBbZBbZBbZBbZBbZBbZBbZBbbBdYBCFBbYBCFBbYBCFBbYBCFBbYBCFBC15B15BBIBCTBHFB4vChBB', false)),
231
- Lm: () => new UnicodeRangeTable(decodeRanges('wVRBFLBPEBICCmEGG-OnHnHlFBBuIBBFgBgBKEEhFoFoF1mBgEgE2R72B72BsDkTkTxOFBvF+BBOjBjBBjBByVOORMBg-CBByHgGgG2OsBsBBDBGiDiDB+C+CBBB34bjnBjnBBEBvIzDzDdBB6DIBxCYYqDCBEBB2OXXqEtDtDWBBoDDBKngVngVuBBBh-BFBCpBBCIB0sBhBhBxuXDB9PCBpBBBnRMBhCBBCtgQtgQBCBCGBCBByhM9BBqGGBudgjBgjB', false)),
232
- Lo: () => new UnicodeRangeTable(decodeRanges('qFQQhIFFBCBxG8Z8ZBZBFDBuBfBCJBkBBBCiDBCZZBLLBBBDRRCdBe4CBMZZBfBWVBrBYBIKBGXBCFBSoBB8B1BBETTIJBROBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBDDDBffFHBCCBCWBCJBCEBEgBgBBCCBQQBSSBHBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNFB8BBBCCCBDBCXBCCCBIBCBBKDDBDBYDBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNyDyDBnKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPByDrTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBpBkCkCBhBBC0BBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBxFuBBSHB3BdBOBBLrBBbjBBqBCBLdByDDBCFBCBBE7hB7hBBCB4-C3BBZWBKGBCGBCGBCGBCGBCGBCGBCGBoR2B2BF1CBJCCB4CBFGGBpBBC9CBSfBxBPBhQ-tGBhC0wUBC2jBBkCnBBJrIBFPBLBBjCyByBBkCBqFoDoDEGBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBuBEBDIBLEBCoBBYCBCHBVPBCFBEEEBwBBCEEBDDBDBDCCZBBEKBIPPBEBDFBDFBKGBCGByEiBBej9KBNWBFwBBloItLBDpDBkCCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBqDJBCsBBDeBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBhEtCBjDnBBJzBB9CzBBN2JBKVBLHB5EFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBnC3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4FjBBnBDBCxJxJBoBBHBBRCB8BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB0GHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPoKoKBRBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBB0BUBGSB0NnBB2MqCBGwFwFB2-FBJ1mBBqBJB43IiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBxzI2P2PBrBBiBiKiKBcBTrBBlPaBmHdBDwPwPBFBCDBCBBCOBCkGB8pBDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEB', false)),
253
+ L: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBLLFGGBVBCeBCpOBFLBPEBICCiEEBCBBDDBCHHCCBCCCBSBCyCBCqEBJlFBClBBDHHBnBBoCaBFDBuBqBBkBBBCiDBCQQBIIBLLBBBDRRCdBe4CBMZZBfBKBBFGGBUBFKKEYYBXBIKBGXBCGBRpBB7B1BBETTIJBQPBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBCBBDBBfFFBGBCCBCWBCJBCEBEffBBBCBBQBBSIBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNGB7BBBCCCBDBCXBCCCBIBCBBKDDBDBCWWBCBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNSSBkBBCGGDqBBCsKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPBR1CBDFBErTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBkBFFkC4CBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBzC+C+CBtBBSHB3BdBOBBLrBBbjBBqBCBLjBBDKBGqBBDCBqBDBCFBCBBEGGB+FBhC1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGB1DOORMBmDFFDJBCEEBDBHGCBCBCKBDDBGEBF1B1BB8zC8zCBjHBHDBEBBNlBBCGGD3BBIRRBVBKGBCGBCGBCGBCGBCGBCGBCGBxC2O2OBrBrBBDBGBBF1CBHCBC5CBCDBGqBBC9CBSfBxBPBhQ-tGBhCs0VBkCtBBDsIBEPBLBBVuBBReBDlCByBIBDmDBDxCBVQBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBdRRBDBCJBLEBCoBBYCBCHBVWBEEEBwBBCEEBDDBDBDCCZCBDKBICBNFBDFBDFBKGBCGBCqBBCNBHyDBej9KBNWBFwBBloItLBDpDBnBGBNEBGCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBlBZBHZBM4CBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBxB9EBTjBBFjBBFnBBJzBBNKBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBHZBnB3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4ByBBOyBBOjBBnBbBKWB7HpBBHBBRFB5BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB1D-BBgBHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPYYBqBBlISBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBBRDBgBUBGSBxNsBB0G-BBhBYBDYBtBqCBGjCjCBLBhCBBCPPBNNB0mHBqBfBiDyDB+vIDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBn7F0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BeBHFBmI9BBzEsBBLGBRiKiKBcBTrBBlPbBlHdBDwGwGBdBCCBCBBCGBDEBKBBhHGBCDBCBBCOBCkGB8BjCBI1lB1lBBCBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIB', false)),
254
+ LC: () => new UnicodeRangeTable(decodeRanges('hCZBHZB7BLLBVBCeBCiGBCDBFvGBDZBhGDBDBBECBCHHCCBCCCBSBCyCBCqEBJlFBClBBKoBB44ClBBCGGDqBBDCBhV1CBDFBjkCKBGqBBDCBhCrBBgCMBChBBmD1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGBmIFFDJBCEEBDBHGCBCBCFBFDDBCBGEBF1B1BB8zC8zCB6DBDmDBHDBEBBNlBBCGGzoetBBTbBnEtCBCWBEDBCsCBZBBE2Z2ZBpBBGIBIvCBh6TGBNEBqgBZBHZBmlBvCBhDjBBFjBB1DKBCOBCGBCBBCKBCOBCGBCBBk2ByBBOyBB+CVBLVB74C-BBhrV-BBhBYBDYBtpZ0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BJBCTBHFB2uCjCB', false)),
255
+ Ll: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBC2BCBQCBuBCDECBBBDCCDEEBFFDEEBBBDDDCCCDCCBCCDEECDDBDDBBBHGDCOCBSCBDDCEEC4BCBFBDDDBCCFICBjCBDZBiGCCEEEBBBTccBhBBCBBECBCWCBDBCGDB0B0BBuBBCgBCK0BCDMCBgDCxBoBBo6CqBBDCB5XFBjkCIBC2D2DBqBBgCMBChBBnD0ECBHBCgDCBHBJFBLHBJHBJFBLHBJHBJNBDHBJHBJHBJEBCBBHEEBBBCBBJDBDBBJHBLCBCBBzIEEBEEcKFDBBJDBF2B2Bs1CvBBCEEBGCFCCBCCBEBGiDCBIICFFNlBBCGG0oesBCUaCoEMCBBBC+BCBGBCCCDICFCCDCCBBBCSCGGGCMCFCCDOCbEE2ZqBBGIBIvCBh6TGBNEBqhBZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfB8BYBnqZZBbGBCRBbZBbDBCCCBFBCKBbZBbZBbZBbZBbZBbZBbZBbZBbbBdYBCFBbYBCFBbYBCFBbYBCFBbYBCFBC15B15BBIBCTBHFB4vChBB', false)),
256
+ Lm: () => new UnicodeRangeTable(decodeRanges('wVRBFLBPEBICCmEGG-OnHnHlFBBuIBBFgBgBKEEhFoFoF1mBgEgE2R72B72BsDkTkTxOFBvF+BBOjBjBBjBByVOORMBg-CBByHgGgG2OsBsBBDBGiDiDB+C+CBBB34bjnBjnBBEBvIzDzDdBB6DIBxCYYpDDBEBB2OXXqEtDtDWBBoDDBKngVngVuBBBh-BFBCpBBCIB0sBhBhB2K04D04DnrTDB9PCBpBBBnRMBhCBBCPPB9-P9-PBCBCGBCBByhM9BBqGGBud0Q0QsSAB', false)),
257
+ Lo: () => new UnicodeRangeTable(decodeRanges('qFQQhIFFBCBxGBB7ZaBFDBuBfBCJBkBBBCiDBCZZBLLBBBDRRCdBe4CBMZZBfBWVBrBYBIKBGXBCGBRoBB8B1BBETTIJBROBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBCBBDBBfFFBGBCCBCWBCJBCEBEffBBBCBBQBBSIBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNFB8BBBCCCBDBCXBCCCBIBCBBKDDBDBYDBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNyDyDBnKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPByDrTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBpBkCkCBhBBC0BBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBxFuBBSHB3BdBOBBLrBBbjBBqBCBLdByDDBCFBCBBE7hB7hBBCB4-C3BBZWBKGBCGBCGBCGBCGBCGBCGBCGBoR2B2BF1CBJCCB4CBFGGBpBBC9CBSfBxBPBhQ-tGBhC0wUBC2jBBkCnBBJrIBFPBLBBjCyByBBkCBqFoDoDEGBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBuBEBDIBLEBCoBBYCBCHBVPBCFBEEEBwBBCEEBDDBDBDCCZBBEKBIPPBEBDFBDFBKGBCGByEiBBej9KBNWBFwBBloItLBDpDBkCCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBqDJBCsBBDeBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBhEtCBjDnBBJzBB9CzBBN2JBKVBLHB5EFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBHZBnB3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4FjBBnBDBCxJxJBoBBHBBRCBCBB5BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB0GHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPYYBnBBCBBlISBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBB0BUBGSB0NnBB2MqCBGwFwFB0mHBqBfBiDyDBuwIiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBxzI2P2PBrBBiBiKiKBcBTrBBlPaBmHdBDwGwGBdBCCBCBBCGBDEBKiHiHBFBCDBCBBCOBCkGB8pBDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIB', false)),
233
258
  Lt: () => new UnicodeRangeTable(decodeRanges('lOGDnB2sH2sHBGBJHBJHBNQQwBAB', false)),
234
- Lu: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiB2BCDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIJDCMCDQCDDDCCBC4BCIBBCBBDCCBCBCGCiJCCEJJHCCBBBCCCBCCBPBCIBkBDDBBBEWCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBpCDBNDBNDBNEBMDBnIFFECBDCBDEEBDBHGCBCBDDBLBBG+B+B9zCvBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBEEGGCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBhtZZBbZBbZBbCCBGDBDDBCBCHBbZBbBBCDBDHBCGBcBBCDBCEBCEEBFBcZBbZBbZBbZBbZBbZBfYBiBYBiBYBiBYBiBYBiB2pE2pEBgBB', false)),
235
- M: () => new UnicodeRangeTable(decodeRanges('gYvDB0IGBoIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCgBB3BCBCRBCGBLBBeCB5BCCBFBDBBDCBKLLBbbDCB5BCCBDBFBBDCBEffBEEMCB5BCCBGBCCBCCBVBBXFBCCB5BCCBFBDBBDCBICBLBBf8B8BBDBECBCDBKpBpBBDB4BCCBFBCCBCDBIBBMBBeCB5BCCBFBCCBCDBIBBMBBQNNBCB4BBBCGBCCBCDBKLLBeeBBBnCFFBEBCCCBGBTBB+BDDBFBNHBjDDDBHBMGBqCBBcECFBByBTBCBBGKBCjBBKlDlDBSBYDBFCBCCBDGBEDBOLBCLLBCBgWCBzdDBdCBeBBfBBhCfBKuBuBBBBC2D2DBjBjB3DLBFLB8GEB6BJBCcBDxBxBBdByBEBwBQBnBIBNCBfMB5BNBxBTB5ECBCUBFHHDCBnG-BBxWgBB--CCBuEhDhDBeBrRFBqDBB1udDBCJBhBBBxCBBxIEEFYYBDBF0C0CBzBzBBQBbRBOnBnBBGBaMBtBDBwBNBlBkCkCBMBNJJBuBuBBBBzBCCBBBDBBGBBCqBqBBDBGBBtHHBCBBx5TiXiXBOBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBwCDBnCKByBDB7DCB2BOBqBDDBLLBCBuBKBI+B+BBBBlBNBRBBtBNNBBBxBNBJDBCBB9CLBHDD+ELBWDB4BBBCGBDBBDCBKLLBDDBFBEEBkCIBCDDCDBCEBCPPBzCzCBQBYyCyCBSBsHGBDIBcBBzCQBrDMBmDOBhIOB2HFBCBBDDBCCCBuEuEBFBDGBEddBIBpBGBCDBJKKBJBvBPB2MHBCHBzCVBCNB7DFBECCBCCBFBCjCjCBDBCBBCEB8KDBKBBCxBxBBFBEEBYmnFmnFHOBpmLRBhuCEB8BGB5gBCCB1BBIDByCMMBslTslTBizEizEBsBBDWB-QEBEFBJHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBBhXGBuDGB29lYvHB', false)),
236
- Mc: () => new UnicodeRangeTable(decodeRanges('joC4B4BDCBJDBCBBzBBB7BCBHBBDBBLsBsB7BCBjC7B7BBBBJCCB2B2BB7B7BCHHBDDBLLnDBBCBBECBCCBLqBqBBBB+BDB+BBB7BCCBDBDBBCBBKBBdPPB7B7BBBBGCBCCBLrBrBBsCsCBBBHHBTBBrKBBgCsFsFBFFHDDBaaBLLBBBDGBWBBDFBDLLBBB5zBffiEIIBGBCBB7KDBDCBFBBCFBhHBB7BCCKCCBJJBEByExBxBGCCBDBCBB+BffFBBD9B9BDCBCEEBxBxBBGBJBBsFWW35EBB0-dBBD5C5CBzBzBBOBvEBBwBxBxBBFFBDDBBBvDBBDBBZuBuBCuDuDDBBGuHuHBCCBCCBCC0gZCCgEuBuBBBBFBB0DZZB8B8BxBCBKBBO+C+CBBBEBBCrFrFBBBgBBB7BBBCDBDBBDCBKLLB1C1CBBBIDDCDBCBBCmDmDBBBJBBErDrDBBBHCCBCBDuHuHBBBHDBDyDyDBBBJBBCuDuDCBBHoDoDCBBFmImIBBBK4H4HBEBCBBFDDCvEvEBBBJDBF1C1CeBB-B4M4MPrDrDIDD2GEBFBBC-K-KBNNxBBBJBBCpvQpvQBBBlxD2BBpDBB0rYBBHFB', false)),
259
+ Lu: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiB2BCDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIJDCMCDQCDDDCCBC4BCIBBCBBDCCBCBCGCiJCCEJJHCCBBBCCCBCCBPBCIBkBDDBBBEWCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBpCDBNDBNDBNEBMDBnIFFECBDCBDEEBDBHGCBCBDDBLBBG+B+B9zCvBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBQCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBhCYBoqZZBbZBbZBbCCBGDBDDBCBCHBbZBbBBCDBDHBCGBcBBCDBCEBCEEBFBcZBbZBbZBbZBbZBbZBfYBiBYBiBYBiBYBiBYBiB2pE2pEBgBB', false)),
260
+ M: () => new UnicodeRangeTable(decodeRanges('gYvDB0IGBoIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCgBB3BCBCRBCGBLBBeCB5BCCBFBDBBDCBKLLBbbDCB5BCCBDBFBBDCBEffBEEMCB5BCCBGBCCBCCBVBBXFBCCB5BCCBFBDBBDCBICBLBBf8B8BBDBECBCDBKpBpBBDB4BCCBFBCCBCDBIBBMBBeCB5BCCBFBCCBCDBIBBMBBQNNBCB4BBBCGBCCBCDBKLLBeeBBBnCFFBEBCCCBGBTBB+BDDBFBNHBjDDDBHBMGBqCBBcECFBByBTBCBBGKBCjBBKlDlDBSBYDBFCBCCBDGBEDBOLBCLLBCBgWCBzdDBdCBeBBfBBhCfBKuBuBBBBC2D2DBjBjB3DLBFLB8GEB6BJBCcBDxBxBBsBBDLBVEBwBQBnBIBNCBfMB5BNBxBTB5ECBCUBFHHDCBnG-BBxWgBB--CCBuEhDhDBeBrRFBqDBB1udDBCJBhBBBxCBBxIEEFYYBDBF0C0CBzBzBBQBbRBOnBnBBGBaMBtBDBwBNBlBkCkCBMBNJJBuBuBBBBzBCCBBBDBBGBBCqBqBBDBGBBtHHBCBBx5TiXiXBOBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBuCFBnCKByBDB7DCB2BOBqBDDBLLBCBuBKBI+B+BBBBlBNBRBBtBNNBBBxBNBJDBCBB9CLBHDD+ELBWDB4BBBCGBDBBDCBKLLBDDBFBEEBkCIBCDDCDBCEBCPPBzCzCBQBYyCyCBSBsHGBDIBcBBzCQBrDMBmDOBhIOB2HFBCBBDDBCCCBuEuEBFBDGBEddBIBpBGBCDBJKKBJBvBPBnGHBoGHBCHBzCVBCNB7DFBECCBCCBFBCjCjCBDBCBBCEB8KDBKBBCxBxBBFBEEBYmnFmnFHOBpmLRBhuCEB8BGB5gBCCB1BBIDByCMMBslTslTBizEizEBsBBDWB-QEBEFBJHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBB0HDDIBBG7O7OBFBuDGB29lYvHB', false)),
261
+ Mc: () => new UnicodeRangeTable(decodeRanges('joC4B4BDCBJDBCBBzBBB7BCBHBBDBBLsBsB7BCBjC7B7BBBBJCCB2B2BB7B7BCHHBDDBLLnDBBCBBECBCCBLqBqBBBB+BDB+BBB7BCCBDBDBBCBBKBBdPPB7B7BBBBGCBCCBLrBrBBsCsCBBBHHBTBBrKBBgCsFsFBFFHDDBaaBLLBBBDGBWBBDFBDLLBBB5zBffiEIIBGBCBB7KDBDCBFBBCFBhHBB7BCCKCCBJJBEByExBxBGCCBDBCBB+BffFBBD9B9BDCBCEEBxBxBBGBJBBsFWW35EBB0-dBBD5C5CBzBzBBOBvEBBwBxBxBBFFBDDBBBvDBBDBBZuBuBCuDuDDBBGuHuHBCCBCCBCC0gZCCgEuBuBBBBFBB0DZZB8B8BxBCBKBBO+C+CBBBEBBCrFrFBBBgBBB7BBBCDBDBBDCBKLLB1C1CBBBIDDCDBCBBCmDmDBBBJBBErDrDBBBHCCBCBDuHuHBBBHDBDyDyDBBBJBBCuDuDCBBHoDoDCBBFmImIBBBK4H4HBEBCBBFDDCvEvEBBBJDBF1C1CeBB-BqGqGECCoGPPrDIID2G2GBDBFBBC-K-KBNNxBBBJBBCpvQpvQBBBlxD2BBpDBB0rYBBHFB', false)),
237
262
  Me: () => new UnicodeRangeTable(decodeRanges('okBBB1xF-wB-wBBCBCCBsshBCB', false)),
238
- Mn: () => new UnicodeRangeTable(decodeRanges('gYvDB0IEBqIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCfB4BCCFHBFEEBFBLBBe7B7BFDBJVVBbbDBB6BFFBFFBDDBBBEffBEEMBB6BFFBDBCBBFVVBXXBEBC7B7BDCCBCBJIIBMMBff+BNNzBEE4BCCBBBGCBCDBIBBMBBe7B7BDHHGBBVBBdBB6BBBFDBJVVBeepCIIBBBC7C7CDGBNHBjDDDBHBMGBqCBBcEC4BNBCEBCBBGKBCjBBKnDnDBCBCFBCBBDBBaBBFCBRDBODDBHHQgWgWBBBzdCBeBBfBBfBBhCBBCGBJDDBJBKuBuBBBBC2D2DBjBjB3DCBFBBKHHBBB8GBBD7B7BCGBCCCDHBHJBDxBxBBMBCPByBDBxBCCBDBCGGpBIBNBBhBDBDBBCCB5BCCBEECCB7BHBDBB5ECBCMBCGBFHHEBBnG-BBxWMBFEEBKB--CCBuEhDhDBeBrRDBsDBB1udFFBIBhBBBxCBBxIEEFaaBGG4EBBbRBOnBnBBGBaKBvBCBxBDDBCBDBBoBkCkCBEBDBBDBBNJJwB0B0BCCBDBBGBBCrBrBBJJvHDDFx5Tx5TiXPBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBwCDBnCKByBDB8D3B3BBNBqBDDBLLBBByBDBDBBI+B+BBBBlBEBCHB-BNNB1B1BBHBLDBDgDgDBBBDCCBHHD+E+EEHBWBB6BBBEmBmBBFBEEBnCFBOECPBB2CHBDCBCYY1CFBCFFBCCBvHvHBCBHBBCBBcBB2CHBDCCBrDrDCDDBEBCmDmDCDDBCBCEBkIIBCBBhIBBCFFxEDBDBBFhBhBBIBpBFBDDBJKKBEBDCBvBMBCBB3MGBCFBCzCzCBUBDGBCBBCBB7DFBECCBCCBFBCpCpCBEEC8K8KBMMB1B1BBDBGCCYmnFmnFHOBpmLLBECBhuCEB8BGB5gBgCgCBCByC5lT5lTBizEizEBsBBDWBhRCBSHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBBhXGBuDGB29lYvHB', false)),
239
- N: () => new UnicodeRangeTable(decodeRanges('wBJB5DBBGDDBBBitBJBnEJBnGJB9MJB3DJBFFBtDJB3DJB3DJBDFBvDMB0DJBJGBoDJBpDGBISBuDJBhDJB3DJBnCTBtIJBnCJBwWTBybCBwHJBHJBXJBtJJBhEKBmFJBHJB3FJB3CJBnEJBHJB3gBEEBEBHJBnGyBBDEB3W7BBvCVB3TdBqrBqYqYaIBPCB4KDBrEJBfHBCOBhBJBoBOBh7cJB9FJBhKFB7EJBnBJBnGJBXJB3CJB3MJB34UJBuPsBBN4BBSBB2KaBlBDBeJJnEEBrGJBvdHBaGBoBIBsCEBXFBhFBBDPBDtBBhCIB1BBBfCBsCEBpDHBZHBqBGBrKFBxBJBHJB3IeB-EJBrBDBxDGBnEdBhEJB9BJBxEJBITB8HJB3KJB3DJB3LJBnDJBHTBtCLBlNSB+CJB3UJB3CcBkHJBnCJBnNJBnDUBshBuDBimPJBnpCJB3CJBnEJBCGBvQJBnIWB6yXJBnuBTBNTBtDYB2iBxBBhqCJBnNJB3PJB4HJBtWIBhEJB4Y6BBCCBCDBtCsBBCOBjeMBk3CJB', false)),
240
- Nd: () => new UnicodeRangeTable(decodeRanges('wBJnxBJnEJnGJ9MJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJhDJ3DJnCJ3IJnCJn6BJnBJtJJhEJnFJHJ3FJ3CJnEJHJnuiBJnVJnBJnGJXJ3CJ3MJ34UJnsBJnkCJHJ9YJhEJ9BJxEJ3IJ3KJ3DJ3LJnDJHTtCJnNJnDJ3UJ3CJ3HJnCJnNJ3uQJnpCJ3CJnEJ3QJ37XJ12CxBhqCJnNJ3PJ4HJ2aJ30EJ', true)),
241
- Nl: () => new UnicodeRangeTable(decodeRanges('u3FCBwzCiBBDDB-zDaaBHBPCBs1dJBxyW0BBtOJJnEEBrhIuDB', false)),
263
+ Mn: () => new UnicodeRangeTable(decodeRanges('gYvDB0IEBqIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCfB4BCCFHBFEEBFBLBBe7B7BFDBJVVBbbDBB6BFFBFFBDDBBBEffBEEMBB6BFFBDBCBBFVVBXXBEBC7B7BDCCBCBJIIBMMBff+BNNzBEE4BCCBBBGCBCDBIBBMBBe7B7BDHHGBBVBBdBB6BBBFDBJVVBeepCIIBBBC7C7CDGBNHBjDDDBHBMGBqCBBcEC4BNBCEBCBBGKBCjBBKnDnDBCBCFBCBBDBBaBBFCBRDBODDBHHQgWgWBBBzdCBeBBfBBfBBhCBBCGBJDDBJBKuBuBBBBC2D2DBjBjB3DCBFBBKHHBBB8GBBD7B7BCGBCCCDHBHJBDxBxBBMBCeBDLBVDBxBCCBDBCGGpBIBNBBhBDBDBBCCB5BCCBEECCB7BHBDBB5ECBCMBCGBFHHEBBnG-BBxWMBFEEBKB--CCBuEhDhDBeBrRDBsDBB1udFFBIBhBBBxCBBxIEEFaaBGG4EBBbRBOnBnBBGBaKBvBCBxBDDBCBDBBoBkCkCBEBDBBDBBNJJwB0B0BCCBDBBGBBCrBrBBJJvHDDFx5Tx5TiXPBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBuCFBnCKByBDB8D3B3BBNBqBDDBLLBBByBDBDBBI+B+BBBBlBEBCHB-BNNB1B1BBHBLDBDgDgDBBBDCCBHHD+E+EEHBWBB6BBBEmBmBBFBEEBnCFBOECPBB2CHBDCBCYY1CFBCFFBCCBvHvHBCBHBBCBBcBB2CHBDCCBrDrDCDDBEBCmDmDCDDBCBCEBkIIBCBBhIBBCFFxEDBDBBFhBhBBIBpBFBDDBJKKBEBDCBvBMBCBBnGCCBBBCqGqGBFBCFBCzCzCBUBDGBCBBCBB7DFBECCBCCBFBCpCpCBEEC8K8KBMMB1B1BBDBGCCYmnFmnFHOBpmLLBECBhuCEB8BGB5gBgCgCBCByC5lT5lTBizEizEBsBBDWBhRCBSHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBB0HDDIBBG7O7OBFBuDGB29lYvHB', false)),
264
+ N: () => new UnicodeRangeTable(decodeRanges('wBJB5DBBGDDBBBitBJBnEJBnGJB9MJB3DJBFFBtDJB3DJB3DJBDFBvDMB0DJBJGBoDJBpDGBISBuDJBhDJB3DJBnCTBtIJBnCJBwWTBybCBwHJBHJBXJBtJJBhEKBmFJBHJB3FJB3CJBnEJBHJB3gBEEBEBHJBnGyBBDEB3W7BBvCVB3TdBqrBqYqYaIBPCB4KDBrEJBfHBCOBhBJBoBOBh7cJB9FJBhKFB7EJBnBJBnGJBXJB3CJB3MJB34UJBuPsBBN4BBSBB2KaBlBDBeJJnEEBrGJBvdHBaGBoBIBsCEBXFBhFBBDPBDtBBhCIB1BBBfCBsCEBpDHBZHBqBGBrKFBxBJBHJB3IeB-EJBrBDBxDGBnEdBhEJB9BJBxEJBITB8HJB3KJB3DJB3LJBnDJBHTBtCLBlNSB+CJB3UJB3CcBkHJBnCJB3BJBnLJBnDUBshBuDBimPJBnpCJB3CJBnEJBCGBvQJBnIWB+KCB6nXJBnuBTBNTBtDYB2iBxBBhqCJBnNJB3PJB4HJBtWIBhEJB4Y6BBCCBCDBtCsBBCOBjeMBk3CJB', false)),
265
+ Nd: () => new UnicodeRangeTable(decodeRanges('wBJnxBJnEJnGJ9MJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJhDJ3DJnCJ3IJnCJn6BJnBJtJJhEJnFJHJ3FJ3CJnEJHJnuiBJnVJnBJnGJXJ3CJ3MJ34UJnsBJnkCJHJ9YJhEJ9BJxEJ3IJ3KJ3DJ3LJnDJHTtCJnNJnDJ3UJ3CJ3HJnCJ3BJnLJ3uQJnpCJ3CJnEJ3QJ37XJ12CxBhqCJnNJ3PJ4HJ2aJ30EJ', true)),
266
+ Nl: () => new UnicodeRangeTable(decodeRanges('u3FCBwzCiBBDDB-zDaaBHBPCBs1dJBxyW0BBtOJJnEEBrhIuDBm8SCB', false)),
242
267
  No: () => new UnicodeRangeTable(decodeRanges('yFBBGDDBBB2pCFB5LFB5DCBmEGB6GGBSIByNJB2hBTB0jBJBhP20B20BEFBHJBnGPBqB3W3WB6BBvCVB3TdBqrB1kB1kBBCBrEJBfHBCOBhBJBoBOBxrdFBymWsBBiCDBSBB2KaBlBDB1pBHBaGBoBIBsCEBXFBhFBBDPBDtBBhCIB1BBBfCBsCEBpDHBZHBqBGBrKFBhLeB-EJBrBDBxDGBnETB8LTBmqBBBvNIBobSB0aUBn8SGB-YWBqhZTBNTBtDYBvqFIBid6BBCCBCDBtCsBBCOBjeMB', false)),
243
- P: () => new UnicodeRangeTable(decodeRanges('hBCBCFBCDBLBBEBBbCBCccCkBkBGEELBBEEE-VJJzOFBqBBB0BCCDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCmBmBBCBoCrCrCBDBFBBwDFBsFlTlTBHB4EuTuTtBBBvCCBoCBB+ECBCCBmBKB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBM9Z9ZBWBJTBCMBCLBfBBPBB6TDBeBB+hBNBwCBBgBJB0MVBgCDBhBBB8XDBCBBxDwEwEBtBBCfBDLBkNCBFJBDLBRNNjD7C7CjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HzqUzqUBxGxGBIBXiBBCNBCFFCBB2ECBCFBCDBLBBEBBbCBCccCCCBFB7MCB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDByO-J-JoFEBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
268
+ P: () => new UnicodeRangeTable(decodeRanges('hBCBCFBCDBLBBEBBbCBCccCkBkBGEELBBEEE-VJJzOFBqBBB0BCCDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCmBmBBCBoCrCrCBDBFBBwDFBsFlTlTBHB4EuTuTtBBBvCCBoCBB+ECBCCBmBKB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBM9Z9ZBWBJTBCMBCLBfBBPBB6TDBeBB+hBNBwCBBgBJB0MVBgCDBhBBB8XDBCBBxDwEwEBtBBCfBDLBkNCBFJBDLBRNNjD7C7CjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HzqUzqUBxGxGBIBXiBBCNBCFFCBB2ECBCFBCDBLBBEBBbCBCccCCCBFB7MCB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDByO-J-JjBlElEBDBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
244
269
  Pc: () => new UnicodeRangeTable(decodeRanges('-Cg-Hg-HBUU-u3BBBZCBwHAB', false)),
245
270
  Pd: () => new UnicodeRangeTable(decodeRanges('tB9qB9qB0BiyDiyDmgBqgCqgCBEBiwDDDgBBBFdd-NUUwDxszBxszBBmBmBLqFqFhzD-J-J', false)),
246
271
  Pe: () => new UnicodeRangeTable(decodeRanges('pB0B0BgB+1D+1DC-6B-6BqtC4B4BQ7T7TCff-hBMCxChBhBCGC1MUChCCCiBmhBmhBCECtBGCtNICEGCDBB-ozB6G6GeOCESSCCCrF0B0BgBGD', false)),
247
272
  Pf: () => new UnicodeRangeTable(decodeRanges('7F+6H+6HEddpuDCCFDDQEE', false)),
248
273
  Pi: () => new UnicodeRangeTable(decodeRanges('rFt7Ht7HDBBDaapuDCCFDDQEE', false)),
249
- Po: () => new UnicodeRangeTable(decodeRanges('hBCBCCBDECBLLBEEBcclCGGPBBI-V-VJzOzOBEBqB3B3BDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCxDxDrCEBFBBwDFBsFlTlTBHBmY9D9DBBBoCBB+ECBCCBmBFBCDB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBMjajaBJJBGBJIBDDBDCBEKBCCCBIB7kDDBCBBxDwEwEBFFBBBDDDBHBCBBCDDBLLBDBCJBDDBCCCBLBDCBtNCB6B+F+FjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HlxUlxUBFBDXXVBBDDBECBCDBICBHCCB2E2EBBBCCBDECBLLBEEBcclBDDB7M7MBBB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDB5dEBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
274
+ Po: () => new UnicodeRangeTable(decodeRanges('hBCBCCBDECBLLBEEBcclCGGPBBI-V-VJzOzOBEBqB3B3BDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCxDxDrCEBFBBwDFBsFlTlTBHBmY9D9DBBBoCBB+ECBCCBmBFBCDB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBMjajaBJJBGBJIBDDBDCBEKBCCCBIB7kDDBCBBxDwEwEBFFBBBDDDBHBCBBCDDBLLBDBCJBDDBCCCBLBDCBtNCB6B+F+FjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HlxUlxUBFBDXXVBBDDBECBCDBICBHCCB2E2EBBBCCBDECBLLBEEBcclBDDB7M7MBBB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDB0ZlElEBDBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
250
275
  Ps: () => new UnicodeRangeTable(decodeRanges('oBzBzBgB-1D-1DC-6B-6B-rCEEnB4B4BQ7T7TCff-hBMCxChBhBCGC1MUChCCCiBmhBmhBCECaTTCECtNICEGCDipzBipzB4GeeCMCESSCCCrFzBzBgBEEDAB', false)),
251
- S: () => new UnicodeRangeTable(decodeRanges('kBHHRCBgBCCcCCkBEBCBBDCCBCBDEEfgBgBrODBNNBGGBCCCBPB2DPPBxDxDsErIrIBBB3DCBDDDBvGvGLUUB4H4HIBBpEqLqLBHHB2H2H-DjEjEBGBlEwGwGqBmGmGiGCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WuLuLlL+E+EBgBBiLJBKIBhiBCCBBBMCBOCBOCBOBBmCOOoBCBOCBUgBBgCBBCDBCBBLCCBBBGFBCECFMMBFFBDBGDBC7B7BBFFB2LBFcBD+HBXKByCtCBXnTBtBwBBDeBLyMBX+BBFfBD1LBDfBCoDBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBB8CBB0HBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BB6RWBKBBoDBB+EDBLDB+RCBiHPPB+9T+9TpEQB+LPBgEtBtBBCBjDCCBBBD7E7EHRRBBBgBCCcCCiEGBCGBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwSmWmWBwtCwtC2kCcBr6SDBG3qU3qUk7DvHBRzNB9EzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBrbaagBaagBaagBaagBaa9B-PB4BDBzBHBCNBCBBp2BwNwNttCEE+DiOiOBvIvIBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E3eBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBC7CB', false)),
252
- Sc: () => new UnicodeRangeTable(decodeRanges('kB+D+DBCBqnB8D8DzPBBzPBBI2H2HoImSmS8sClmClmCBfB47hBkuVkuVtD7E7E8GBBEBB3-HDB-4wBxtCxtC', false)),
276
+ S: () => new UnicodeRangeTable(decodeRanges('kBHHRCBgBCCcCCkBEBCBBDCCBCBDEEfgBgBrODBNNBGGBCCCBPB2DPPBxDxDsErIrIBBB3DCBDDDBvGvGLUUB4H4HIBBpEqLqLBHHB2H2H-DjEjEBGBlEwGwGqBmGmGiGCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WuLuLlL+E+EBgBBiLJBKIBhiBCCBBBMCBOCBOCBOBBmCOOoBCBOCBUhBB-BBBCDBCBBLCCBBBGFBCECFMMBFFBDBGDBC7B7BBFFB2LBFcBD+HBXKByCtCBXnTBtBwBBDeBLyMBX+BBFfBD1LBDpEBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBB8CBB0HBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BB6RWBKBBoDBB+EDBLDB+RCBiHPPB+9T+9TpEgBBuLPBhCBB3BHBtBDBjDCCBBBD7E7EHRRBBBgBCCcCCiEGBCGBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwSmWmWBiKiKBGBnjC2kC2kCBbBr6SDBG3qU3qUk7DvHBLCBEzNBHWBQQBgDzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBrbaagBaagBaagBaagBaa9B-PB4BDBzBHBCNBCBBp2BwNwNttCEE+DiOiOBvIvIBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E4eBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBBPIBoB3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBC7CBLAB', false)),
277
+ Sc: () => new UnicodeRangeTable(decodeRanges('kB+D+DBCBqnB8D8DzPBBzPBBI2H2HoImSmS8sClmClmCBgBB37hBkuVkuVtD7E7E8GBBEBB3-HDB-4wBxtCxtC', false)),
253
278
  Sk: () => new UnicodeRangeTable(decodeRanges('+CCCoCHHFEEqQDBNNBGGBCCCBPB2DPPBjoBjoB15FCCBBBMCBOCBOCBOBB9kEBBkzdWBKBBoDBBxePPBniUniUBPB8bCCjF4g9B4g9BBDB', false)),
254
- Sm: () => new UnicodeRangeTable(decodeRanges('rBRRBBB+BCCuBFFmBgBgB-XwQwQBBB8xGOOoBCBOCBsEoBoBBDBHlClCBDBGBBFGDIgBgBBDDCgBgBBqIBhBBB7CffBXBpBFB2OKK3BHBwDxKxKBDBDeBLPBhIiEBX+BBFfBDhIBxBUBDFB9+zB5Z5ZCCBlFRRBBB+BCCkEHHBCBitDBBypyBaagBaagBaagBaagBaat5FBB', false)),
255
- So: () => new UnicodeRangeTable(decodeRanges('mFDDFCCyerIrIBgEgEBvGvGLUUB4H4HkQ2L2LjEFBClElEwGqBqBoMCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WzWzW+EhBBiLJBKIBksBBBCDBCBBLCCBHHBEBCECFMMBPPCBBC7B7BBKKBDBDDBCBBCBBCGBCeBDBBCCCBdBtIHBFTBDGBDwCBCdBanBBHnCBXKByCtCBX2FBCIBC1BBJuDBC3HBtBrBBhC-HBhQvBBWBBHmBBDfBCoDBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBBxKBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BBibDBLBBC+R+RBBBn2UPBgEuBuBBBBlPEEFBBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwS3jD3jD2kCHBFQBr6SDBG3qU3qUk7DvHBRzNB9EzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBqlB-PB4BDBzBHBCNBCBBp2B96C96CiEyWyWBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E6HBG3WBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBC7CB', false)),
279
+ Sm: () => new UnicodeRangeTable(decodeRanges('rBRRBBB+BCCuBFFmBgBgB-XwQwQBBB8xGOOoBCBOCBsEoBoBBDBHlClCBDBGBBFGDIgBgBBDDCgBgBBqIBhBBB7CffBXBpBFB2OKK3BHBwDxKxKBDBDeBLPBhIiEBX+BBFfBDhIBxBUBDFB9+zB5Z5ZCCBlFRRBBB+BCCkEHHBCBitDBBhrwBx+Bx+BagBgBagBgBagBgBagBgBat5Ft5FB-uC-uCBHB', false)),
280
+ So: () => new UnicodeRangeTable(decodeRanges('mFDDFCCyerIrIBgEgEBvGvGLUUB4H4HkQ2L2LjEFBClElEwGqBqBoMCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WzWzW+EhBBiLJBKIBksBBBCDBCBBLCCBHHBEBCECFMMBPPCBBC7B7BBKKBDBDDBCBBCBBCGBCeBDBBCCCBdBtIHBFTBDGBDwCBCdBanBBHnCBXKByCtCBX2FBCIBC1BBJuDBC3HBtBrBBhC-HBhQvBBWBBHmBBDpEBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBBxKBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BBibDBLBBC+R+RBBBqqUPBuLPBhCBB3BHBuBCBlPEEFBBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwSpgBpgBBGBnjC2kC2kCBGBFQBr6SDBG3qU3qUk7DvHBLCBEzNBHWBQPBhDzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBqlB-PB4BDBzBHBCNBCBBp2B96C96CiEyWyWBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E6HBG4WBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-B3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBC7CBLAB', false)),
256
281
  Z: () => new UnicodeRangeTable(decodeRanges('gBgEgEgvFgsCgsCBJBeBBGwBwBh9DAB', false)),
257
282
  Zl: () => new UnicodeRangeTable(decodeRanges('ohIA', true)),
258
283
  Zp: () => new UnicodeRangeTable(decodeRanges('phIA', true)),
@@ -265,7 +290,7 @@
265
290
  Adlam: () => new UnicodeRangeTable(decodeRanges('go6DrCFJFB', true)),
266
291
  Ahom: () => new UnicodeRangeTable(decodeRanges('g4lCaDOFW', true)),
267
292
  Anatolian_Hieroglyphs: () => new UnicodeRangeTable(decodeRanges('ggxCmS', true)),
268
- Arabic: () => new UnicodeRangeTable(decodeRanges('gwBEBCFBCNBCCBCfBCJBMZBCrDBChBBxCvBBxHeBCBBGqCBCcBxy8ByDBRqLBDvCBD1BBIhBhBBOBxDEBCmEBk7DeBkCCB4BDBh43BDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBB', false)),
293
+ Arabic: () => new UnicodeRangeTable(decodeRanges('gwBEBCFBCNBCCBCfBCJBMZBCrDBChBBxCvBBxHhBBGqCBCcBxy8BtPBDvEBhBPBxDEBCmEBk7DeBkCFBJIBiBFBh43BDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBB', false)),
269
294
  Armenian: () => new UnicodeRangeTable(decodeRanges('xpBlBDxBDCks9BE', true)),
270
295
  Avestan: () => new UnicodeRangeTable(decodeRanges('g4iC1BEG', true)),
271
296
  Balinese: () => new UnicodeRangeTable(decodeRanges('g4GsCCxB', true)),
@@ -273,6 +298,7 @@
273
298
  Bassa_Vah: () => new UnicodeRangeTable(decodeRanges('w26CdDF', true)),
274
299
  Batak: () => new UnicodeRangeTable(decodeRanges('g+GzBJD', true)),
275
300
  Bengali: () => new UnicodeRangeTable(decodeRanges('gsCDBCHBDBBDVBCGBCEEBCBDIBDBBDDBJFFBCCBDBDYB', false)),
301
+ Beria_Erfe: () => new UnicodeRangeTable(decodeRanges('g17CYDY', true)),
276
302
  Bhaiksuki: () => new UnicodeRangeTable(decodeRanges('ggnCICsBCNLc', true)),
277
303
  Bopomofo: () => new UnicodeRangeTable(decodeRanges('qXB6wLqBxDf', true)),
278
304
  Brahmi: () => new UnicodeRangeTable(decodeRanges('ggkCtCFjBKA', true)),
@@ -286,7 +312,7 @@
286
312
  Cham: () => new UnicodeRangeTable(decodeRanges('gwqB2BKNDJDD', true)),
287
313
  Cherokee: () => new UnicodeRangeTable(decodeRanges('g9E1CDFz7lBvC', true)),
288
314
  Chorasmian: () => new UnicodeRangeTable(decodeRanges('w9jCb', true)),
289
- Common: () => new UnicodeRangeTable(decodeRanges('AgCBbFBbuBBCOBCEBYgBgBiOmBBGEBDTB1DKKHCC+THHPEEhB9E9ElQiEiEB6mB6mB2MDBjJwvBwvBBBBoCBBsGBBCumBumBOIIBCBCFBCCBDmYmYBKBD2CBCKBEKBCOBSgBBgClBBCCBDFBCaBCQBqBCBF5UBXKBW-cBhIzTBDfBCoDBhQ9CBzMUBCCCBXBQHBFDB8CBBE7C7CB0E0EBOBhBlBBKxBxBB+BBgBwCBwB5C5CBmFBhuG-BBhoWhBBnDCBmFJB1HhFhFsMPPBzuUzuUBxGxGBIBXiBBCSBCDB0ECCBeBbFBbKBLuBuBBhChCBFBCGBLEBjICBFsBBEIBxCMB0BsBBlHaBltuBDB96D5HBHzNB9EzDB9B1HBLmBBD9BBEQBJBBIdBF8BB2GTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBDxBByjFjCBtC8BBjWrBBFjDBNOBDOBCOBCkBBLtFB5BZBCBBOrBBFIBIBBPFB7E3eBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBClDBoghYffB+CB', false)),
315
+ Common: () => new UnicodeRangeTable(decodeRanges('AgCBbFBbuBBCOBCEBYgBgBiOmBBGEBDTB1DKKHCC+THHPEEhB9E9ElQiEiEB6mB6mB2MDBjJwvBwvBBBBoCBBsGBBCumBumBOIIBCBCFBCCBDmYmYBKBD2CBCKBEKBCOBShBB-BlBBCCBDFBCaBCQBqBCBF5UBXKBW-cBhIzTBDpEBhQ9CBzMUBCCCBXBQHBFDB8CBBE7C7CB0E0EBOBhBlBBKxBxBB+BBgBwCBwB5C5CBmFBhuG-BBhoWhBBnDCBmFJB1HhFhFsMPPBzuUzuUBxGxGBIBXiBBCSBCDB0ECCBeBbFBbKBLuBuBBhChCBFBCGBLEBjICBFsBBEIBxCMB0BsBBlHaBltuBDB96D8HBEzNBHWBQQBgDzDB9B1HBLmBBD9BBEQBJBBIdBF8BB2GTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBDxBByjFjCBtC8BBjWrBBFjDBNOBDOBCOBCkBBLtFB5BZBCBBOrBBFIBIBBPFB7E4eBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBBPIBoB3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBCmDBnghYffB+CB', false)),
290
316
  Coptic: () => new UnicodeRangeTable(decodeRanges('ifNxkKzDGG', true)),
291
317
  Cuneiform: () => new UnicodeRangeTable(decodeRanges('ggoC5cnDuDCEMjG', true)),
292
318
  Cypriot: () => new UnicodeRangeTable(decodeRanges('ggiCFBDCCBqBBCBBEDD', false)),
@@ -311,7 +337,7 @@
311
337
  Gunjala_Gondi: () => new UnicodeRangeTable(decodeRanges('grnCFCBCkBCBCFIJ', true)),
312
338
  Gurmukhi: () => new UnicodeRangeTable(decodeRanges('hwCCBCFBFBBDVBCGBCBBCBBCBBDCCBDBFBBDCBEIIBCBCIIBPB', false)),
313
339
  Gurung_Khema: () => new UnicodeRangeTable(decodeRanges('go4C5B', true)),
314
- Han: () => new UnicodeRangeTable(decodeRanges('g0LZBC4CBN1GBwBCCaIBPDBle-tGBhC-vUBhoWtLBDpDBpodBBNBBvgkB-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEB', false)),
340
+ Han: () => new UnicodeRangeTable(decodeRanges('g0LZBC4CBN1GBwBCCaIBPDBle-tGBhC-vUBhoWtLBDpDBpodBBNGBqgkB-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIB', false)),
315
341
  Hangul: () => new UnicodeRangeTable(decodeRanges('goE-HvxHBiI9CyDeiCei3dckUj9KNWFwBl9JeEFDFDFDC', true)),
316
342
  Hanifi_Rohingya: () => new UnicodeRangeTable(decodeRanges('gojCnBJJ', true)),
317
343
  Hanunoo: () => new UnicodeRangeTable(decodeRanges('g5FU', true)),
@@ -319,12 +345,12 @@
319
345
  Hebrew: () => new UnicodeRangeTable(decodeRanges('xsB2BBJaBFFBpp9BZBCEBCCCBCCBCCBIB', false)),
320
346
  Hiragana: () => new UnicodeRangeTable(decodeRanges('hiM1CBHCBi7-C+IBTeeBBBulQAB', false)),
321
347
  Imperial_Aramaic: () => new UnicodeRangeTable(decodeRanges('giiCVCI', true)),
322
- Inherited: () => new UnicodeRangeTable(decodeRanges('gYvDB2IBBlOKBbhXhXBCB8qEeBiQCBCMBCGBFHHEBBnG-BBtQBBjGgBB65DDBsDBBmrzBPBRNBwejHjH7iEl+uBl+uBBsBBDWBhRCBSHBDGBfDBz6rYvHB', false)),
348
+ Inherited: () => new UnicodeRangeTable(decodeRanges('gYvDB2IBBlOKBbhXhXBCB8qEtBBDLBlPCBCMBCGBFHHEBBnG-BBtQBBjGgBB65DDBsDBBmrzBPBRNBwejHjH7iEl+uBl+uBBsBBDWBhRCBSHBDGBfDBz6rYvHB', false)),
323
349
  Inscriptional_Pahlavi: () => new UnicodeRangeTable(decodeRanges('g7iCSGH', true)),
324
350
  Inscriptional_Parthian: () => new UnicodeRangeTable(decodeRanges('g6iCVDH', true)),
325
351
  Javanese: () => new UnicodeRangeTable(decodeRanges('gsqBtCDJFB', true)),
326
352
  Kaithi: () => new UnicodeRangeTable(decodeRanges('gkkCiCLA', true)),
327
- Kannada: () => new UnicodeRangeTable(decodeRanges('gkDMCCCWCJCEDICCCDIBHBCDDJCC', true)),
353
+ Kannada: () => new UnicodeRangeTable(decodeRanges('gkDMCCCWCJCEDICCCDIBGCCDDJCC', true)),
328
354
  Katakana: () => new UnicodeRangeTable(decodeRanges('hlM5CBDCBxHPBxGuBBC3CBvgzBJBCsBBzisBDBCGBCBBCgJgJBBBzBPPBCB', false)),
329
355
  Kawi: () => new UnicodeRangeTable(decodeRanges('g4nCQCoBEc', true)),
330
356
  Kayah_Li: () => new UnicodeRangeTable(decodeRanges('goqBtBCA', true)),
@@ -335,7 +361,7 @@
335
361
  Khudawadi: () => new UnicodeRangeTable(decodeRanges('w1kC6BGJ', true)),
336
362
  Kirat_Rai: () => new UnicodeRangeTable(decodeRanges('gq7C5B', true)),
337
363
  Lao: () => new UnicodeRangeTable(decodeRanges('h0DBBCCCBDBCXBCCCBVBDEBCCCBFBCJBDDB', false)),
338
- Latin: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBQQGWBCeBCgOBoBEB8wGlBBHwBBGDBGMBClCBiC-HByLOORMBuEBBHccSoBB42CfBj1elDBEiCBDBBCCCBGBWNBxZqBBCIBCDB38TGB7gBZBHZBmhCFBCpBBCIBm61BeBHFB', false)),
364
+ Latin: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBQQGWBCeBCgOBoBEB8wGlBBHwBBGDBGMBClCBiC-HByLOORMBuEBBHccSoBB42CfBj1elDBExCBVOBxZqBBCIBCDB38TGB7gBZBHZBmhCFBCpBBCIBm61BeBHFB', false)),
339
365
  Lepcha: () => new UnicodeRangeTable(decodeRanges('ggH3BEOEC', true)),
340
366
  Limbu: () => new UnicodeRangeTable(decodeRanges('goGeBCLBFLBFEEBKB', false)),
341
367
  Linear_A: () => new UnicodeRangeTable(decodeRanges('gwhC2JKVLH', true)),
@@ -394,9 +420,10 @@
394
420
  Runic: () => new UnicodeRangeTable(decodeRanges('g1FqCEK', true)),
395
421
  Samaritan: () => new UnicodeRangeTable(decodeRanges('ggCtBDO', true)),
396
422
  Saurashtra: () => new UnicodeRangeTable(decodeRanges('gkqBlCJL', true)),
397
- Sharada: () => new UnicodeRangeTable(decodeRanges('gskC-C', true)),
423
+ Sharada: () => new UnicodeRangeTable(decodeRanges('gskC-ChsCH', true)),
398
424
  Shavian: () => new UnicodeRangeTable(decodeRanges('wihCvB', true)),
399
425
  Siddham: () => new UnicodeRangeTable(decodeRanges('gslC1BDlB', true)),
426
+ Sidetic: () => new UnicodeRangeTable(decodeRanges('gqiCZ', true)),
400
427
  SignWriting: () => new UnicodeRangeTable(decodeRanges('gg2DrUQECO', true)),
401
428
  Sinhala: () => new UnicodeRangeTable(decodeRanges('hsDCBCRBEXBCIBCDDBFBEFFBEBCCCBGBHJBDCBt-gCTB', false)),
402
429
  Sogdian: () => new UnicodeRangeTable(decodeRanges('w5jCpB', true)),
@@ -411,21 +438,23 @@
411
438
  Tai_Le: () => new UnicodeRangeTable(decodeRanges('wqGdDE', true)),
412
439
  Tai_Tham: () => new UnicodeRangeTable(decodeRanges('gxG+BCcDKHJHN', true)),
413
440
  Tai_Viet: () => new UnicodeRangeTable(decodeRanges('g0qBiCZE', true)),
441
+ Tai_Yo: () => new UnicodeRangeTable(decodeRanges('g25DeCVJB', true)),
414
442
  Takri: () => new UnicodeRangeTable(decodeRanges('g0lC5BHJ', true)),
415
443
  Tamil: () => new UnicodeRangeTable(decodeRanges('i8CBBCFBECBCDBEBBCCCBEEBEEBBBELBFEBECBCDBDHHPUBm+kCxBBOAB', false)),
416
444
  Tangsa: () => new UnicodeRangeTable(decodeRanges('wz6CuCCJ', true)),
417
- Tangut: () => new UnicodeRangeTable(decodeRanges('g-7CgBgBB2-FBJ-XBhQIB', false)),
418
- Telugu: () => new UnicodeRangeTable(decodeRanges('ggDMBCCBCWBCPBDIBCCBCDBIBBCCBDDDBCBDJBIIB', false)),
445
+ Tangut: () => new UnicodeRangeTable(decodeRanges('g-7CgBgBB+3GBhQeBiDyDB', false)),
446
+ Telugu: () => new UnicodeRangeTable(decodeRanges('ggDMCCCWCPDICCCDIBCCCBDDDJII', true)),
419
447
  Thaana: () => new UnicodeRangeTable(decodeRanges('g8BxB', true)),
420
448
  Thai: () => new UnicodeRangeTable(decodeRanges('hwD5BGb', true)),
421
449
  Tibetan: () => new UnicodeRangeTable(decodeRanges('g4DnCCjBFmBCjBCOCGFB', true)),
422
450
  Tifinagh: () => new UnicodeRangeTable(decodeRanges('wpL3BIBPA', true)),
423
451
  Tirhuta: () => new UnicodeRangeTable(decodeRanges('gklCnCJJ', true)),
424
452
  Todhri: () => new UnicodeRangeTable(decodeRanges('guhCzB', true)),
453
+ Tolong_Siki: () => new UnicodeRangeTable(decodeRanges('wtnCrBFJ', true)),
425
454
  Toto: () => new UnicodeRangeTable(decodeRanges('w04De', true)),
426
455
  Tulu_Tigalari: () => new UnicodeRangeTable(decodeRanges('g8kCJBCDDClBBCJBCDDCDBCJBCBBJBB', false)),
427
456
  Ugaritic: () => new UnicodeRangeTable(decodeRanges('g8gCdCA', true)),
428
- Unknown: () => new UnicodeRangeTable(decodeRanges('4bBBHDBICCVuMuMnBBBzBBBE4B4BBGBcDBHKBvI9B9BBmDmDBMB8BBByBBBQddBCCMEBgBDDBDBuHJJBDDBXXICCBBBFBBKBBDBBFHBCDBDGGBaaBEEHDBDBBXIIDGDBCCGDBDBBECBCGBFCCBFBSJBEKKEXXIDDGBBLIEBCCBNBFBBNGBIEEJBBDBBXIIDGGBKKBDDBEEBFBEDBDGGBTTBIBDHHBBBEFFBBBDCCDCBDCBECBNDBGCBEFFBCCBEBCNBWEBOEEYRRBKKEFFBFBDEEBCCBFFBLLBFBXEEYLLGBBKEEFGBDFBDFFBLLELBOEE0BEEHDBRBBbEETCBZKKCBBICBCDBHCCJFBLBBELB7BDBekBBDCCGZZCYYBGGCIILBBFfBpClBlBBCBoBlBlBQOOBjBBnGCCBDBCBB6LFFBIICFFBqBqBFBBiBFFBIICFFBQQ6BFFBkCkCBhBhBBBBbFB3CBBHBB+UCB6CGBXIBZIBVLBOEEDLB-CBBLFBLFBbFB6CGBsBEBnCJBgBNNBCBNDBCCBrBBBGKBtBDBbFBMCB-BBBiCeeBMMBEBLFBPBBgBwBBuCnFnFBGB9BCBQCB-BEBsBBBMHBsBEB3QBBHBBnBBBHBBJGCgBBB2BQQPBBHUUBEEKmDmDNBBcOOBBBiBOBiBOBtEDB7UVBMUB14BBBhB+K+KBDBuBCCBDBCBB5BGBDNBZIBI4BI-DhBBb6C6CBKB3GZBxC3C3CBoDoDBDBsB-C-C3CIBxBuzcuzcBBB4BIB9KTB5FHBvGBBDCCJUB8BCBLFB5BHBnCHBNFB1DKBfCBvCMMBCBiB4B4BBHBPBBLBBoDXBdJBHBBHBBHIBIII9BDB-DBBLFBl9KLBYDByBjoIBvLBBrDlBBILBGEBbGGCGD+DPB+NBB3BGBCfBrBFB0BUUFDBGoEoEBCC-FCBHBBHBBHBBECBIIIBIBGBBNbbUDDQBBPhBB8DEBEDBuBCB5COOBBBCuBBvBhEBeCByBOBdDBlBIBfEBsBEBfmBmBBCBPpBB-EBBLFBlBDBlBDBpBHB1BKBNQQIDDMQQIDDBBB1BLB4JIBXJBJXBHrBrBKkCBHBBCtBtBDCBCBBYpCpCBGBKvBBUDDBDBiBCBcEBC-BB5BDBVBBzBDDBDBJEEeBBEDBLGBKGBhCfBoBDBNIB3BCBeBBcEBbGBFLBIvCBqC2BB0BMB0BGBvBHBLFBnBCBeHBDvGBgBrBrBEBBDPBE2BBtBHBrBVBblBBdTBYIBvCDBlBIBlCJBCBBaGBLFB2BTTBGBoBIBhDVVBJBTwBwBB8BBICCFQQMFB8BEBLFBFJJBDDBXXIDDGLLBDDBEEBCCBEBCEBIBBICBGKBLCCBCCnBLLCBBCFFLDDBGBDcB9CGGBcBpCHBLlFB3BBBnBhBBmCKBLFBOSB7BFBLFBVbBcBBQDBY4FB9BjDB0CLBJBBCBBJDDfDDBNNBHBLlCBJBBvBBBMaBpCHB0CMBqCGBL1FBjBNBLFBKuBuBPJBeCBhBBBXPPBnCBIDDtBCBCDDKHBLFBHDDmBDDHGBL1JBaGBSqBqBBBBe0CBCOBzBMB8clDBwDGGBJBlGryCBkDMB3iBJB88DEBoS41GB7Bl2BB6RGBgBLLBCByCLLBEBfBBHJBnCJBLIIWEBUvNB7BlGB8CkDBsCDB6BGBS-BBGKBDNB5-FHB3mBoBBLm3IBFIIDkJkJBNBCcBEBBCNBFHBtMjoCBsDEBOCBKGBLBBJ76DB7HFB1NrCBvBBBYIB1D7BB3HJBoBBBjGUBnC5DBVLBVLB4CIBamEB2CoCoCDBBCBBDBBFNNCIIiCFFBJJIddFGGCCBI1K1KBlJlJB-V-VBNBGQQBuiBBgBFBH0GBISSBIIDGGBDB-BgBBCvDBuBCBPBBLDBD-JBgBQB7BEBCvOBrB1GBsBDBC-OBIFFDQQmGBBRoBBtCDBLDBDwYBlCrCB+BhGBFccDCCBCCLFFCCCBEBCDBCECEDDCBBCICDCCBFFIKFCLLSEBEGGSzBBDtIBtBDBlDLBQBBQQQmBJBvF3BBeMBtBDBKGBDNBH5EB5eDBSCBOCB4DDBgDFBNDBCOBNDB5BHBLFBpBHBfBBNDBD9BB1KLBPBBOCBLEB5BGBQBBMFBKGB0EnDnDBkgBBh3pBfB7hEFB-GBBj0FNBypHOBvThtCB-QhvBBs6EEBhjEwi3VBCdBhD-DBxHvw-FB', false)),
457
+ Unknown: () => new UnicodeRangeTable(decodeRanges('4bBBHDBICCVuMuMnBBBzBBBE4B4BBGBcDBHKBvI9B9BBmDmDBMB8BBByBBBQddBCCMEBjBEBuHJJBDDBXXICCBBBFBBKBBDBBFHBCDBDGGBaaBEEHDBDBBXIIDGDBCCGDBDBBECBCGBFCCBFBSJBEKKEXXIDDGBBLIEBCCBNBFBBNGBIEEJBBDBBXIIDGGBKKBDDBEEBFBEDBDGGBTTBIBDHHBBBEFFBBBDCCDCBDCBECBNDBGCBEFFBCCBEBCNBWEBOEEYRRBKKEFFBFBDEEDBBFBBLGBXEEYLLGBBKEEFGBDEBEFFBLLELBOEE0BEEHDBRBBbEETCBZKKCBBICBCDBHCCJFBLBBELB7BDBekBBDCCGZZCYYBGGCIILBBFfBpClBlBBCBoBlBlBQOOBjBBnGCCBDBCBB6LFFBIICFFBqBqBFBBiBFFBIICFFBQQ6BFFBkCkCBhBhBBBBbFB3CBBHBB+UCB6CGBXIBZIBVLBOEEDLB-CBBLFBLFBbFB6CGBsBEBnCJBgBNNBCBNDBCCBrBBBGKBtBDBbFBMCB-BBBiCeeBMMBEBLFBPBBvBBBNTBuCnFnFBGB9BCBQCB-BEBsBBBMHBsBEB3QBBHBBnBBBHBBJGCgBBB2BQQPBBHUUBEEKmDmDNBBcOOBBBjBNBiBOBtEDB7UVBMUB14BBB-LEBuBCCBDBCBB5BGBDNBZIBI4BI-DhBBb6C6CBKB3GZBxC3C3CBoDoDBDBsB-C-C3CIBxBuzcuzcBBB4BIB9KTB5FHB+GTB9BCBLFB5BHBnCHBNFB1DKBfCBvCMMBCBiB4B4BBHBPBBLBBoDXBdJBHBBHBBHIBIII9BDB-DBBLFBl9KLBYDByBjoIBvLBBrDlBBILBGEBbGGCGDrUfBrBFB0BUUFDBGoEoEBCC-FCBHBBHBBHBBECBIIIBIBGBBNbbUDDQBBPhBB8DEBEDBuBCB5COOBBBCuBBvBhEBeCByBOBdDBlBIBfEBsBEBfmBmBBCBPpBB-EBBLFBlBDBlBDBpBHB1BKBNQQIDDMQQIDDBBB1BLB4JIBXJBJXBHrBrBKkCBHBBCtBtBDCBCBBYpCpCBGBKvBBUDDBDBiBCBcEBclBB5BDBVBBzBDDBDBJEEeBBEDBLGBKGBhCfBoBDBNIB3BCBeBBcEBbGBFLBIvCBqC2BB0BMB0BGBvBHBLFBnBCBeHBDvGBgBrBrBEBBDPBHHBKgBBvBHBrBVBblBBdTBYIBvCDBlBIBlCJBCBBaGBLFB2BTTBGBoBIBhDVVBJBTwBwBB8BBICCFQQMFB8BEBLFBFJJBDDBXXIDDGLLBDDBEEBCCBEBCEBIBBICBGKBLCCBCCnBLLCBBCFFLDDBGBDcB9CGGBcBpCHBLlFB3BBBnBhBBmCKBLFBOSB7BFBLFBVbBcBBQDBY4FB9BjDB0CLBJBBCBBJDDfDDBNNBHBLlCBJBBvBBBMaBpCHB0CMBqCGBL1CBJ3CBjBNBLFBKuBuBPJBeCBhBBBXPPBnCBIDDtBCBCDDKHBLFBHDDmBDDHGBLFBtBDBL1HBaGBSqBqBBBBe0CBCOBzBMB8clDBwDGGBJBlGryCBkDMB3iBJB88DEBoS41GB7Bl2BB6RGBgBLLBCByCLLBEBfBBHJBnCJBLIIWEBUvNB7BlGB8CEBaBBarBBsCDB6BGBS-BBGKBIIB3mHoBBhBgDB0D8vIBFIIDkJkJBNBCcBEBBCNBFHBtMjoCBsDEBOCBKGBLBBJ76DB+HCB1NFBYOBSOBvBBBYIB1D7BB3HJBoBBBjGUBnC5DBVLBVLB4CIBamEB2CoCoCDBBCBBDBBFNNCIIiCFFBJJIddFGGCCBI1K1KBlJlJB-V-VBNBGQQBuiBBgBFBH0GBISSBIIDGGBDB-BgBBCvDBuBCBPBBLDBD-JBgBQB7BEBCvOBrB1GBsBDBC-FBgBXXBGBD-GBIFFDQQmGBBRoBBtCDBLDBDwYBlCrCB+BhGBFccDCCBCCLFFCCCBEBCDBCECEDDCBBCICDCCBFFIKFCLLSEBEGGSzBBDtIBtBDBlDLBQBBQQQmBJBvF3BBeMBtBDBKGBDNBH5EB6eCBSCBOCB7GFBNDBCOBNDB5BHBLFBpBHBfBBNDBDNBKmBB5KHBPBBOCBMCB6BCCBCBRBBNDBLGB0EoDoDBjgBBh3pBfB-oEBBv0FBBypHOBvThtCB-QhvBBs6EEBrpIm8yVBCdBhD-DBxHvw-FB', false)),
429
458
  Vai: () => new UnicodeRangeTable(decodeRanges('gopBrJ', true)),
430
459
  Vithkuqi: () => new UnicodeRangeTable(decodeRanges('wrhCKCOCGCBCKCOCGCB', true)),
431
460
  Wancho: () => new UnicodeRangeTable(decodeRanges('g24D5BGA', true)),
@@ -435,22 +464,18 @@
435
464
  Zanabazar_Square: () => new UnicodeRangeTable(decodeRanges('gwmCnC', true))
436
465
  });
437
466
  static FOLD_CATEGORIES = new LazyMap({
438
- C: () => new UnicodeRangeTable(decodeRanges('z+pBCC', false)),
439
- Cn: () => new UnicodeRangeTable(decodeRanges('z+pBCC', false)),
440
- L: () => new UnicodeRangeTable(decodeRanges('latkpBtkpBCAB', false)),
441
- LC: () => new UnicodeRangeTable(decodeRanges('latkpBtkpBCAB', false)),
442
- Ll: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiBuBCEECDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIBBCBBCBBCOCDQCDBBCCCBBBC4BCIBBCBBDCCBCBCGC3HrBrBCEEJHHCCBCCCBCCBPBCIBkBJJCUCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBZHBJHBJHBJEBMEBMDBNEBMEBqJEEBHHxC9zC9zCBuBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBEECKCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBh1ehBB', false)),
467
+ L: () => new UnicodeRangeTable(decodeRanges('laA', true)),
468
+ LC: () => new UnicodeRangeTable(decodeRanges('laA', true)),
469
+ Ll: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiBuBCEECDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIBBCBBCBBCOCDQCDBBCCCBBBC4BCIBBCBBDCCBCBCGC3HrBrBCEEJHHCCBCCCBCCBPBCIBkBJJCUCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBZHBJHBJHBJEBMEBMDBNEBMEBqJEEBHHxC9zC9zCBuBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBQCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBhCYBoyehBB', false)),
443
470
  Lt: () => new UnicodeRangeTable(decodeRanges('kOCCBCCBCClBCCtsHHBJHBJHBMQQwBAB', false)),
444
- Lu: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBCuBCEECDOCDsBCDECBBBDCCDEEGDDECBDDDCCCDFFDEECDDECCGBBCBBCBBCOCBSCDBBCEECkBCEQCJDDBCCFICBEBCBBCCCBEEBCCBCBCEBDCCBDDIDDCBBEFBGLLBnFnFsBCCEEEBBBvBDBCdBCBBECBCWCBDBCGD1BvBBCgBCK0BCDMCBgDCyBlBBq6CqBBDCB5XFBjkCIBCvHvHERRzD0ECGGGC8CCBHBJFBLHBJHBJFBMGCJHBJNBzBBBNSSBPPBEEpL2B2Bs1CvBBCEEBGCHDDLiDCJCCFNNBkBBCGG0oesBCUaCoEMCE8BCLCCDICFFFCBBDSCMOCFCCDEEGECb9a9advCBi8UZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfBj1ehBB', false)),
471
+ Lu: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBCuBCEECDOCDsBCDECBBBDCCDEEGDDECBDDDCCCDFFDEECDDECCGBBCBBCBBCOCBSCDBBCEECkBCEQCJDDBCCFICBEBCBBCCCBEEBCCBCBCEBDCCBDDIDDCBBEFBGLLBnFnFsBCCEEEBBBvBDBCdBCBBECBCWCBDBCGD1BvBBCgBCK0BCDMCBgDCyBlBBq6CqBBDCB5XFBjkCIBCvHvHERRzD0ECGGGC8CCBHBJFBLHBJHBJFBMGCJHBJNBzBBBNSSBPPBEEpL2B2Bs1CvBBCEEBGCHDDLiDCJCCFNNBkBBCGG0oesBCUaCoEMCE8BCLCCDICFFFCBBDSCMOCFCCDOCb9a9advCBi8UZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfB8BYBvyehBB', false)),
445
472
  M: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false)),
446
473
  Mn: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false))
447
474
  });
448
475
  static FOLD_SCRIPT = new LazyMap({
449
476
  Common: () => new UnicodeRangeTable(decodeRanges('8cgBgB', false)),
450
477
  Greek: () => new UnicodeRangeTable(decodeRanges('1FwUwU', false)),
451
- Inherited: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false)),
452
- Latin: () => new UnicodeRangeTable(decodeRanges('y+pBCC', false)),
453
- Unknown: () => new UnicodeRangeTable(decodeRanges('z+pBCC', false))
478
+ Inherited: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false))
454
479
  });
455
480
  }
456
481
 
@@ -579,11 +604,16 @@
579
604
  // to compare it to |r2|.
580
605
  // -1 is interpreted as the end-of-file mark.
581
606
  static equalsIgnoreCase(r1, r2) {
582
- // Runes already match, or one of them is EOF
583
- if (r1 < 0 || r2 < 0 || r1 === r2) {
607
+ // Runes already match
608
+ if (r1 === r2) {
584
609
  return true;
585
610
  }
586
611
 
612
+ // Safely fail if either is EOF (and they didn't explicitly match above)
613
+ if (r1 < 0 || r2 < 0) {
614
+ return false;
615
+ }
616
+
587
617
  // Fast path for the common case where both runes are ASCII characters.
588
618
  // Coerces both runes to lowercase if applicable.
589
619
  if (r1 <= this.MAX_ASCII && r2 <= this.MAX_ASCII) {
@@ -836,7 +866,7 @@
836
866
  // Encoding[(Encoding['UTF_16'] = 0)] = 'UTF_16'
837
867
  // Encoding[(Encoding['UTF_8'] = 1)] = 'UTF_8'
838
868
  const createEnum = (values = [], initNum = 0) => {
839
- const enumObject = {};
869
+ const enumObject = Object.create(null);
840
870
  for (let i = 0; i < values.length; i++) {
841
871
  const val = values[i];
842
872
  const keyVal = initNum + i;
@@ -978,6 +1008,9 @@
978
1008
  hasString() {
979
1009
  return false;
980
1010
  }
1011
+ hasAnyString() {
1012
+ return false;
1013
+ }
981
1014
 
982
1015
  // Helper for the exact-literal fast-path execution router
983
1016
  prefixLength() {
@@ -1003,6 +1036,13 @@
1003
1036
  return idx !== -1 && idx <= this.end - target.length;
1004
1037
  }
1005
1038
 
1039
+ // Executes a high-speed, single - pass search for multiple literal strings
1040
+ // simultaneously using an Aho-Corasick automaton.
1041
+ hasAnyString(prefilter, pos) {
1042
+ if (!prefilter.ac8) return false;
1043
+ return prefilter.ac8.searchUTF8(this.bytes, this.start + pos, this.end);
1044
+ }
1045
+
1006
1046
  // Returns the rune at the specified index; the units are
1007
1047
  // unspecified, but could be UTF-8 byte, UTF-16 char, or rune
1008
1048
  // indices. Returns the width (in the same units) of the rune in
@@ -1021,17 +1061,23 @@
1021
1061
  return c << 3 | 1;
1022
1062
  } else if (c >= 0xc2 && c <= 0xdf && pos + 1 < this.end) {
1023
1063
  const c1 = this.bytes[pos + 1] & 0xff;
1064
+ if ((c1 & 0xc0) !== 0x80) return c << 3 | 1;
1024
1065
  const rune = (c & 0x1f) << 6 | c1 & 0x3f;
1025
1066
  return rune << 3 | 2;
1026
1067
  } else if (c >= 0xe0 && c <= 0xef && pos + 2 < this.end) {
1027
1068
  const c1 = this.bytes[pos + 1] & 0xff;
1069
+ if ((c1 & 0xc0) !== 0x80) return c << 3 | 1;
1028
1070
  const c2 = this.bytes[pos + 2] & 0xff;
1071
+ if ((c2 & 0xc0) !== 0x80) return c << 3 | 1;
1029
1072
  const rune = (c & 0x0f) << 12 | (c1 & 0x3f) << 6 | c2 & 0x3f;
1030
1073
  return rune << 3 | 3;
1031
1074
  } else if (c >= 0xf0 && c <= 0xf4 && pos + 3 < this.end) {
1032
1075
  const c1 = this.bytes[pos + 1] & 0xff;
1076
+ if ((c1 & 0xc0) !== 0x80) return c << 3 | 1;
1033
1077
  const c2 = this.bytes[pos + 2] & 0xff;
1078
+ if ((c2 & 0xc0) !== 0x80) return c << 3 | 1;
1034
1079
  const c3 = this.bytes[pos + 3] & 0xff;
1080
+ if ((c3 & 0xc0) !== 0x80) return c << 3 | 1;
1035
1081
  const rune = (c & 0x07) << 18 | (c1 & 0x3f) << 12 | (c2 & 0x3f) << 6 | c3 & 0x3f;
1036
1082
  return rune << 3 | 4;
1037
1083
  } else {
@@ -1110,6 +1156,13 @@
1110
1156
  return idx !== -1 && idx <= this.end - prefilter.str.length;
1111
1157
  }
1112
1158
 
1159
+ // Executes a high-speed, single - pass search for multiple literal strings
1160
+ // simultaneously using an Aho-Corasick automaton.
1161
+ hasAnyString(prefilter, pos) {
1162
+ if (!prefilter.ac16) return false;
1163
+ return prefilter.ac16.searchUTF16(this.charSequence, this.start + pos, this.end);
1164
+ }
1165
+
1113
1166
  // Returns the rune at the specified index; the units are
1114
1167
  // unspecified, but could be UTF-8 byte, UTF-16 char, or rune
1115
1168
  // indices. Returns the width (in the same units) of the rune in
@@ -1555,7 +1608,15 @@
1555
1608
  if (this.hasMatch) {
1556
1609
  start = this.groups[1];
1557
1610
  if (this.groups[0] === this.groups[1]) {
1558
- start++;
1611
+ // Safely calculate structural encoding width to avoid sequence corruption
1612
+ const machineInput = this.matcherInput.isUTF16Encoding() ? MachineInput.fromUTF16(this.matcherInput.asCharSequence(), 0, this.matcherInputLength) : MachineInput.fromUTF8(this.matcherInput.asBytes(), 0, this.matcherInputLength);
1613
+ const r = machineInput.step(start);
1614
+ if (r < 0) {
1615
+ // EOF
1616
+ start++; // Advance past length to force loop exit
1617
+ } else {
1618
+ start += r & 7; // Advance by safely decoded width
1619
+ }
1559
1620
  }
1560
1621
  }
1561
1622
  return this.genMatch(start, RE2Flags.UNANCHORED);
@@ -1569,14 +1630,16 @@
1569
1630
  * @private
1570
1631
  */
1571
1632
  genMatch(startByte, anchor) {
1572
- const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
1633
+ const hasLookbehinds = this.patternInput.re2().prog.numLb > 0;
1634
+ const ngroup = hasLookbehinds ? 1 + this.patternGroupCount : 1;
1635
+ const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, ngroup);
1573
1636
  const ok = res[0];
1574
1637
  if (!ok) {
1575
1638
  return false;
1576
1639
  }
1577
1640
  this.groups = res[1];
1578
1641
  this.hasMatch = true;
1579
- this.hasGroups = false;
1642
+ this.hasGroups = hasLookbehinds || this.patternGroupCount === 0;
1580
1643
  this.anchorFlag = anchor;
1581
1644
  return true;
1582
1645
  }
@@ -1692,6 +1755,8 @@
1692
1755
  const groupName = replacement.substring(i + 1, j);
1693
1756
  res += this.group(groupName);
1694
1757
  last = j + 1;
1758
+ i = j;
1759
+ continue;
1695
1760
  }
1696
1761
  }
1697
1762
  }
@@ -1771,6 +1836,7 @@
1771
1836
  if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get('>')) {
1772
1837
  res += replacement.substring(i - 1, j + 1);
1773
1838
  last = j + 1;
1839
+ i = j;
1774
1840
  continue;
1775
1841
  }
1776
1842
  const groupName = replacement.substring(i + 1, j);
@@ -1780,6 +1846,8 @@
1780
1846
  res += `$<${groupName}>`;
1781
1847
  }
1782
1848
  last = j + 1;
1849
+ i = j;
1850
+ continue;
1783
1851
  }
1784
1852
  }
1785
1853
  }
@@ -1863,6 +1931,8 @@
1863
1931
  static RUNE1 = 9;
1864
1932
  static RUNE_ANY = 10;
1865
1933
  static RUNE_ANY_NOT_NL = 11;
1934
+ static LB_WRITE = 12;
1935
+ static LB_CHECK = 13;
1866
1936
  static isRuneOp(op) {
1867
1937
  return Inst.RUNE <= op && op <= Inst.RUNE_ANY_NOT_NL;
1868
1938
  }
@@ -1902,6 +1972,8 @@
1902
1972
  return r === r0;
1903
1973
  }
1904
1974
  const len = this.runes.length;
1975
+ if (len === 0) return false;
1976
+
1905
1977
  // If the array is exactly 2, 4, 6, or 8 items, DO NOT fall through to binary search
1906
1978
  if (len === 2 || len === 4 || len === 6 || len === 8) {
1907
1979
  for (let j = 0; j < len; j += 2) {
@@ -1915,22 +1987,19 @@
1915
1987
  return false; // Stop here
1916
1988
  }
1917
1989
 
1918
- // Otherwise binary search.
1919
- let lo = 0;
1920
- let hi = this.runes.length / 2 | 0;
1921
- while (lo < hi) {
1922
- const m = lo + hi >> 1; // native cpu instruction for "lo + (((hi - lo) / 2) | 0)"
1923
- const c = this.runes[2 * m];
1924
- if (c <= r) {
1925
- if (r <= this.runes[2 * m + 1]) {
1926
- return true;
1927
- }
1928
- lo = m + 1;
1929
- } else {
1930
- hi = m;
1931
- }
1990
+ // Branchless Binary Search (Lower Bound)
1991
+ // Compiles to optimal conditional move (cmov) machine code, preventing
1992
+ // branch mispredictions on large, chaotic Unicode arrays
1993
+ let base = 0;
1994
+ let n = len >> 1;
1995
+ while (n > 1) {
1996
+ const half = n >> 1;
1997
+ base += this.runes[base + half << 1] <= r ? half : 0;
1998
+ n -= half;
1932
1999
  }
1933
- return false;
2000
+ base += this.runes[base << 1] <= r ? 1 : 0;
2001
+ const m = base - 1;
2002
+ return m >= 0 && r <= this.runes[m << 1 | 1];
1934
2003
  }
1935
2004
 
1936
2005
  // matchRunePos checks whether the instruction matches (and consumes) r.
@@ -1945,6 +2014,7 @@
1945
2014
  return r === r0 ? 0 : -1;
1946
2015
  }
1947
2016
  const len = this.runes.length;
2017
+ if (len === 0) return -1;
1948
2018
  if (len === 2 || len === 4 || len === 6 || len === 8) {
1949
2019
  for (let j = 0; j < len; j += 2) {
1950
2020
  if (r < this.runes[j]) return -1;
@@ -1952,19 +2022,18 @@
1952
2022
  }
1953
2023
  return -1;
1954
2024
  }
1955
- let lo = 0;
1956
- let hi = Math.floor(len / 2);
1957
- while (lo < hi) {
1958
- const m = lo + hi >> 1;
1959
- const c = this.runes[2 * m];
1960
- if (c <= r) {
1961
- if (r <= this.runes[2 * m + 1]) return m;
1962
- lo = m + 1;
1963
- } else {
1964
- hi = m;
1965
- }
2025
+
2026
+ // Branchless Binary Search (Lower Bound)
2027
+ let base = 0;
2028
+ let n = len >> 1;
2029
+ while (n > 1) {
2030
+ const half = n >> 1;
2031
+ base += this.runes[base + half << 1] <= r ? half : 0;
2032
+ n -= half;
1966
2033
  }
1967
- return -1;
2034
+ base += this.runes[base << 1] <= r ? 1 : 0;
2035
+ const m = base - 1;
2036
+ return m >= 0 && r <= this.runes[m << 1 | 1] ? m : -1;
1968
2037
  }
1969
2038
  /**
1970
2039
  *
@@ -1986,6 +2055,10 @@
1986
2055
  return 'fail';
1987
2056
  case Inst.NOP:
1988
2057
  return `nop -> ${this.out}`;
2058
+ case Inst.LB_WRITE:
2059
+ return `lbwrite ${this.lb} -> ${this.out}`;
2060
+ case Inst.LB_CHECK:
2061
+ return `lbcheck ${this.lb} -> ${this.out}, ${this.arg}`;
1989
2062
  case Inst.RUNE:
1990
2063
  if (this.runes === null) {
1991
2064
  return 'rune <null>';
@@ -2059,6 +2132,7 @@
2059
2132
  //
2060
2133
  // Called by RE2.doExecute.
2061
2134
  class Machine {
2135
+ static THREADS_CHUNK_SIZE = 128;
2062
2136
  static fromRE2(re2) {
2063
2137
  const m = new Machine();
2064
2138
  m.prog = re2.prog;
@@ -2085,21 +2159,29 @@
2085
2159
  } else {
2086
2160
  this.resetCap();
2087
2161
  }
2162
+
2163
+ // Initialize the Lookbehind tracking table
2164
+ if (this.prog.numLb > 0) {
2165
+ if (!this.lbTable || this.lbTable.length < this.prog.numLb + 1) {
2166
+ this.lbTable = new Int32Array(this.prog.numLb + 1);
2167
+ }
2168
+ this.lbTable.fill(-1);
2169
+ }
2088
2170
  }
2089
2171
 
2090
2172
  // Wipes existing typed array memory without reallocating
2091
2173
  resetCap() {
2092
2174
  for (let i = 0; i < this.poolSize; i++) {
2093
2175
  const t = this.pool[i];
2094
- t.cap.fill(0);
2176
+ t.cap.fill(-1);
2095
2177
  }
2096
2178
  }
2097
2179
  initNewCap(ncap) {
2098
2180
  for (let i = 0; i < this.poolSize; i++) {
2099
2181
  const t = this.pool[i];
2100
- t.cap = new Int32Array(ncap);
2182
+ t.cap = new Int32Array(ncap).fill(-1);
2101
2183
  }
2102
- this.matchcap = new Int32Array(ncap);
2184
+ this.matchcap = new Int32Array(ncap).fill(-1);
2103
2185
  }
2104
2186
  submatches() {
2105
2187
  if (this.ncap === 0) {
@@ -2112,14 +2194,21 @@
2112
2194
  // alloc() allocates a new thread with the given instruction.
2113
2195
  // It uses the free pool if possible.
2114
2196
  alloc(inst) {
2115
- let t;
2116
- if (this.poolSize > 0) {
2117
- this.poolSize--;
2118
- t = this.pool[this.poolSize];
2119
- } else {
2120
- t = new Thread();
2121
- t.cap = new Int32Array(this.matchcap.length);
2197
+ if (this.poolSize === 0) {
2198
+ const capLen = this.matchcap.length;
2199
+
2200
+ // Bulk allocate threads in a tight loop so the V8 engine
2201
+ // places them adjacently in the young generation heap
2202
+ for (let i = 0; i < Machine.THREADS_CHUNK_SIZE; i++) {
2203
+ const t = new Thread();
2204
+ t.cap = new Int32Array(capLen);
2205
+ this.pool[this.poolSize++] = t;
2206
+ }
2122
2207
  }
2208
+
2209
+ // Pop a thread from the top of the pool stack
2210
+ this.poolSize--;
2211
+ const t = this.pool[this.poolSize];
2123
2212
  t.inst = inst;
2124
2213
  return t;
2125
2214
  }
@@ -2172,10 +2261,16 @@
2172
2261
  if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) {
2173
2262
  break;
2174
2263
  }
2264
+ if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2265
+ break;
2266
+ }
2175
2267
  if (this.matched) {
2176
2268
  break;
2177
2269
  }
2178
- if (!(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
2270
+ // Disable Prefix Acceleration if the regex contains lookbehinds
2271
+ // Fast-forwarding the string pointer will skip over the positions where
2272
+ // the parallel lookbehind automata need to be spawned.
2273
+ if (this.prog.numLb === 0 && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
2179
2274
  const advance = input.index(this.re2, pos);
2180
2275
  if (advance < 0) {
2181
2276
  break;
@@ -2193,6 +2288,10 @@
2193
2288
  if (this.ncap > 0) {
2194
2289
  this.matchcap[0] = pos;
2195
2290
  }
2291
+ // Spawn Lookbehind threads BEFORE the main pattern
2292
+ for (let i = 0; i < this.prog.lbStarts.length; i++) {
2293
+ this.add(runq, this.prog.lbStarts[i], pos, this.matchcap, flag, null);
2294
+ }
2196
2295
  this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
2197
2296
  }
2198
2297
  const nextPos = pos + width;
@@ -2242,8 +2341,15 @@
2242
2341
  while (true) {
2243
2342
  if (runq.isEmpty()) {
2244
2343
  if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) break;
2344
+ if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2345
+ break;
2346
+ }
2245
2347
  }
2246
2348
  if (pos === 0 || anchor === RE2Flags.UNANCHORED) {
2349
+ // Spawn Lookbehind threads BEFORE the main pattern
2350
+ for (let i = 0; i < this.prog.lbStarts.length; i++) {
2351
+ this.add(runq, this.prog.lbStarts[i], pos, this.matchcap, flag, null);
2352
+ }
2247
2353
  this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
2248
2354
  }
2249
2355
  const nextPos = pos + width;
@@ -2353,63 +2459,83 @@
2353
2459
  runq.clear();
2354
2460
  }
2355
2461
  add(q, pc, pos, cap, cond, t) {
2356
- if (pc === 0) {
2357
- return t;
2358
- }
2359
- if (q.contains(pc)) {
2360
- return t;
2361
- }
2362
- const d = q.add(pc);
2363
- const inst = this.prog.inst[pc];
2364
- switch (inst.op) {
2365
- case Inst.FAIL:
2366
- break;
2367
- case Inst.ALT:
2368
- case Inst.ALT_MATCH:
2369
- t = this.add(q, inst.out, pos, cap, cond, t);
2370
- t = this.add(q, inst.arg, pos, cap, cond, t);
2371
- break;
2372
- case Inst.EMPTY_WIDTH:
2373
- if ((inst.arg & ~cond) === 0) {
2374
- t = this.add(q, inst.out, pos, cap, cond, t);
2375
- }
2376
- break;
2377
- case Inst.NOP:
2378
- t = this.add(q, inst.out, pos, cap, cond, t);
2379
- break;
2380
- case Inst.CAPTURE:
2381
- if (inst.arg < this.ncap) {
2382
- const opos = cap[inst.arg];
2383
- cap[inst.arg] = pos;
2384
- this.add(q, inst.out, pos, cap, cond, null);
2385
- cap[inst.arg] = opos;
2386
- } else {
2462
+ while (true) {
2463
+ if (pc === 0) {
2464
+ return t;
2465
+ }
2466
+ if (q.contains(pc)) {
2467
+ return t;
2468
+ }
2469
+ const d = q.add(pc);
2470
+ const inst = this.prog.inst[pc];
2471
+ switch (inst.op) {
2472
+ case Inst.FAIL:
2473
+ return t;
2474
+ case Inst.ALT:
2475
+ case Inst.ALT_MATCH:
2387
2476
  t = this.add(q, inst.out, pos, cap, cond, t);
2388
- }
2389
- break;
2390
- case Inst.MATCH:
2391
- case Inst.RUNE:
2392
- case Inst.RUNE1:
2393
- case Inst.RUNE_ANY:
2394
- case Inst.RUNE_ANY_NOT_NL:
2395
- if (t === null) {
2396
- t = this.alloc(inst);
2397
- } else {
2398
- t.inst = inst;
2399
- }
2400
- if (this.ncap > 0 && t.cap !== cap) {
2401
- // Direct assignment utilizing Typed Array performance
2402
- for (let c = 0; c < this.ncap; c++) {
2403
- t.cap[c] = cap[c];
2477
+ pc = inst.arg; // Flattened tail recursion
2478
+ continue;
2479
+ case Inst.EMPTY_WIDTH:
2480
+ if ((inst.arg & ~cond) === 0) {
2481
+ pc = inst.out; // Flattened tail recursion
2482
+ continue;
2404
2483
  }
2405
- }
2406
- q.denseThreads[d] = t;
2407
- t = null;
2408
- break;
2409
- default:
2410
- throw new Error('unhandled');
2484
+ return t;
2485
+ case Inst.NOP:
2486
+ pc = inst.out; // Flattened tail recursion
2487
+ continue;
2488
+ case Inst.CAPTURE:
2489
+ if (inst.arg < this.ncap) {
2490
+ const opos = cap[inst.arg];
2491
+ cap[inst.arg] = pos;
2492
+ this.add(q, inst.out, pos, cap, cond, null);
2493
+ cap[inst.arg] = opos;
2494
+ return t;
2495
+ } else {
2496
+ pc = inst.out; // Flattened tail recursion
2497
+ continue;
2498
+ }
2499
+ case Inst.LB_WRITE:
2500
+ this.lbTable[Math.abs(inst.lb)] = pos;
2501
+ pc = inst.out;
2502
+ continue;
2503
+ case Inst.LB_CHECK:
2504
+ if (inst.lb > 0) {
2505
+ // Positive Lookbehind
2506
+ if (this.lbTable[inst.lb] === pos) {
2507
+ pc = inst.out; // Flattened tail recursion
2508
+ continue;
2509
+ }
2510
+ } else if (this.lbTable[-inst.lb] !== pos) {
2511
+ // Negative Lookbehind
2512
+ pc = inst.out; // Flattened tail recursion
2513
+ continue;
2514
+ }
2515
+ return t;
2516
+ case Inst.MATCH:
2517
+ case Inst.RUNE:
2518
+ case Inst.RUNE1:
2519
+ case Inst.RUNE_ANY:
2520
+ case Inst.RUNE_ANY_NOT_NL:
2521
+ if (t === null) {
2522
+ t = this.alloc(inst);
2523
+ } else {
2524
+ t.inst = inst;
2525
+ }
2526
+ if (this.ncap > 0 && t.cap !== cap) {
2527
+ // Direct assignment utilizing Typed Array performance
2528
+ for (let c = 0; c < this.ncap; c++) {
2529
+ t.cap[c] = cap[c];
2530
+ }
2531
+ }
2532
+ q.denseThreads[d] = t;
2533
+ t = null;
2534
+ return t;
2535
+ default:
2536
+ throw new Error('unhandled');
2537
+ }
2411
2538
  }
2412
- return t;
2413
2539
  }
2414
2540
  }
2415
2541
 
@@ -2437,8 +2563,15 @@
2437
2563
  this.nfaStates = nfaStates; // Int32Array of Instruction PCs
2438
2564
  this.isMatch = isMatch; // Boolean
2439
2565
  this.matchIDs = matchIDs; // Array of integers indicating which Set patterns matched
2440
- this.nextAscii = new Array(Unicode.MAX_ASCII + 1).fill(null); // Flat array for blisteringly fast ASCII lookups
2441
- this.nextMap = new Map(); // Cache of Char -> DFAState
2566
+
2567
+ // Latin-1 (Unicode.MAX_LATIN1 + 1) flat arrays for blisteringly fast O(1) lookups
2568
+ // completely covering standard English, European languages, and 1-byte encodings.
2569
+ this.nextLatin1 = new Array(Unicode.MAX_LATIN1 + 1).fill(null); // Flat array for blisteringly fast ASCII lookups
2570
+ this.nextLatin1Anchored = new Array(Unicode.MAX_LATIN1 + 1).fill(null); // Flat array for blisteringly fast ASCII lookups
2571
+ // 2 arrays used as hash map for V8 optimization (N is small number, so O(n) faster than Map O(1))
2572
+ this.transKeys = [];
2573
+ this.transVals = [];
2574
+ this.lastSeen = 0; // Track when this state was last used for LRU eviction
2442
2575
  }
2443
2576
  }
2444
2577
  class DFA {
@@ -2451,6 +2584,7 @@
2451
2584
  this.stateLimit = 10000; // Prevent memory explosion (ReDoS protection)
2452
2585
  this.cacheClears = 0; // Track thrashing
2453
2586
  this.failed = false; // mark if DFA cannot work with provided prog
2587
+ this.clock = 0; // Global clock for LRU eviction
2454
2588
  }
2455
2589
 
2456
2590
  // Follows epsilon (empty) transitions to find all reachable states without consuming a char
@@ -2481,6 +2615,8 @@
2481
2615
  // Bailing out on complex empty-width assertions to keep DFA fast.
2482
2616
  // Engine will seamlessly fall back to the NFA.
2483
2617
  case Inst.EMPTY_WIDTH:
2618
+ case Inst.LB_WRITE:
2619
+ case Inst.LB_CHECK:
2484
2620
  return null;
2485
2621
  }
2486
2622
  }
@@ -2508,6 +2644,7 @@
2508
2644
  for (let i = 0; i < bucket.length; i++) {
2509
2645
  const state = bucket[i];
2510
2646
  if (arraysEqual(state.nfaStates, sortedPCs)) {
2647
+ state.lastSeen = ++this.clock;
2511
2648
  return state;
2512
2649
  }
2513
2650
  }
@@ -2520,40 +2657,99 @@
2520
2657
  if (this.failed) return null;
2521
2658
 
2522
2659
  // Safety: prevent memory exhaustion from state explosion
2523
- // We flush the cache and return null, which seamlessly routes execution to the NFA
2660
+ // We prune the cache to keep the newest 50%
2524
2661
  if (this.stateCount >= this.stateLimit) {
2525
- this.stateCache.clear();
2526
- this.stateCount = 0;
2527
- this.startState = null;
2528
2662
  this.cacheClears++;
2529
2663
 
2530
2664
  // If this regex causes continuous cache thrashing, permanently fall back to NFA
2531
2665
  // to avoid spending CPU cycles constantly rebuilding the DFA tree.
2532
2666
  if (this.cacheClears >= DFA.MAX_CACHE_CLEARS) {
2533
2667
  this.failed = true;
2668
+ this.stateCache.clear();
2669
+ this.stateCount = 0;
2670
+ this.startState = null;
2671
+ return null;
2672
+ }
2673
+ this.evictCache();
2674
+
2675
+ // After eviction, the bucket reference might be stale or empty.
2676
+ // We must re-fetch or re-create the bucket.
2677
+ bucket = this.stateCache.get(hash);
2678
+ if (!bucket) {
2679
+ bucket = [];
2680
+ this.stateCache.set(hash, bucket);
2534
2681
  }
2535
- return null;
2536
2682
  }
2537
2683
 
2538
2684
  // State not found, create it and add to bucket
2539
2685
  const state = new DFAState(sortedPCs, closureResult.isMatch, closureResult.matchIDs);
2686
+ state.lastSeen = ++this.clock;
2540
2687
  bucket.push(state);
2541
2688
  this.stateCount++;
2542
2689
  return state;
2543
2690
  }
2691
+ evictCache() {
2692
+ const allStates = [];
2693
+ for (const bucket of this.stateCache.values()) {
2694
+ for (let i = 0; i < bucket.length; i++) {
2695
+ allStates.push(bucket[i]);
2696
+ }
2697
+ }
2698
+
2699
+ // Sort ascending by lastSeen (oldest first)
2700
+ allStates.sort((a, b) => a.lastSeen - b.lastSeen);
2701
+
2702
+ // Keep the newest 50%
2703
+ const keepCount = Math.max(1, Math.floor(this.stateLimit / 2));
2704
+ const startIndex = allStates.length - keepCount;
2705
+ const survivorsArray = allStates.slice(startIndex);
2706
+ const survivors = new Set(survivorsArray);
2707
+ this.stateCache.clear();
2708
+ this.stateCount = 0;
2709
+ for (let i = 0; i < survivorsArray.length; i++) {
2710
+ const state = survivorsArray[i];
2711
+
2712
+ // Sever ties to all states to prevent memory leaks and dangling pointers
2713
+ state.nextLatin1.fill(null);
2714
+ state.nextLatin1Anchored.fill(null);
2715
+ // zero-allocation cleanup
2716
+ state.transKeys.length = 0;
2717
+ state.transVals.length = 0;
2718
+ const hash = hashPCs(state.nfaStates);
2719
+ let bucket = this.stateCache.get(hash);
2720
+ if (!bucket) {
2721
+ bucket = [];
2722
+ this.stateCache.set(hash, bucket);
2723
+ }
2724
+ bucket.push(state);
2725
+ this.stateCount++;
2726
+ }
2727
+
2728
+ // Start state must either be preserved or nullified so it gets re-created
2729
+ if (this.startState && !survivors.has(this.startState)) {
2730
+ this.startState = null;
2731
+ }
2732
+ }
2544
2733
 
2545
2734
  // Compute the next DFA state given a current state and a character
2546
2735
  step(state, charCode, anchor) {
2547
- // OPTIMIZATION: ASCII Fast-Path
2548
- if (anchor === RE2Flags.UNANCHORED && charCode <= Unicode.MAX_ASCII) {
2549
- const next = state.nextAscii[charCode];
2550
- if (next !== null) {
2551
- return next;
2736
+ // OPTIMIZATION: Latin-1 Array Fast-Path
2737
+ if (charCode <= Unicode.MAX_LATIN1) {
2738
+ if (anchor === RE2Flags.UNANCHORED) {
2739
+ const next = state.nextLatin1[charCode];
2740
+ if (next !== null) return next;
2741
+ } else {
2742
+ const next = state.nextLatin1Anchored[charCode];
2743
+ if (next !== null) return next;
2552
2744
  }
2553
2745
  } else {
2746
+ // Dense Array Linear Search fallback for Runes > 255
2554
2747
  const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
2555
- if (state.nextMap.has(key)) {
2556
- return state.nextMap.get(key);
2748
+ // get [key] -> nextState
2749
+ const keys = state.transKeys;
2750
+ const len = keys.length;
2751
+ for (let i = 0; i < len; i++) {
2752
+ if (keys[i] === key) return state.transVals[i];
2557
2753
  }
2558
2754
  }
2559
2755
  const nextPCs = [];
@@ -2570,11 +2766,17 @@
2570
2766
  const nextState = this.getState(nextPCs);
2571
2767
 
2572
2768
  // Cache the result
2573
- if (anchor === RE2Flags.UNANCHORED && charCode <= Unicode.MAX_ASCII) {
2574
- state.nextAscii[charCode] = nextState;
2769
+ if (charCode <= Unicode.MAX_LATIN1) {
2770
+ if (anchor === RE2Flags.UNANCHORED) {
2771
+ state.nextLatin1[charCode] = nextState;
2772
+ } else {
2773
+ state.nextLatin1Anchored[charCode] = nextState;
2774
+ }
2575
2775
  } else {
2576
2776
  const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
2577
- state.nextMap.set(key, nextState);
2777
+ // store key -> nextState
2778
+ state.transKeys.push(key);
2779
+ state.transVals.push(nextState);
2578
2780
  }
2579
2781
  return nextState;
2580
2782
  }
@@ -2607,10 +2809,11 @@
2607
2809
  if (width === 0) {
2608
2810
  break;
2609
2811
  }
2610
- currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_ASCII && currentState.nextAscii[rune] || this.step(currentState, rune, anchor);
2812
+ currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_LATIN1 && currentState.nextLatin1[rune] || this.step(currentState, rune, anchor);
2611
2813
 
2612
2814
  // If we hit an unrecoverable DFA error or bailout, signal fallback
2613
2815
  if (currentState === null) return null;
2816
+ currentState.lastSeen = ++this.clock;
2614
2817
  if (currentState.isMatch) {
2615
2818
  if (anchor === RE2Flags.ANCHOR_BOTH) {
2616
2819
  if (i + width === endPos) return true;
@@ -2658,9 +2861,10 @@
2658
2861
  const rune = r >> 3;
2659
2862
  const width = r & 7;
2660
2863
  if (width === 0) break;
2661
- currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_ASCII && currentState.nextAscii[rune] || this.step(currentState, rune, anchor);
2864
+ currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_LATIN1 && currentState.nextLatin1[rune] || this.step(currentState, rune, anchor);
2662
2865
  if (currentState === null) return null; // Bailout to NFA
2663
2866
 
2867
+ currentState.lastSeen = ++this.clock;
2664
2868
  i += width;
2665
2869
  checkMatch(currentState, i);
2666
2870
  if (currentState.nfaStates.length === 0) {
@@ -2698,7 +2902,7 @@
2698
2902
  // Bitwise shift (>>> 5) instead of Math.floor( / 32)
2699
2903
  const visitedSize = prog.numInst() * (end + 1) + VISITED_BITS - 1 >>> 5;
2700
2904
  if (this.visited.length < visitedSize) {
2701
- this.visited = new Uint32Array(Math.floor(MAX_BACKTRACK_VECTOR / VISITED_BITS));
2905
+ this.visited = new Uint32Array(visitedSize);
2702
2906
  } else {
2703
2907
  this.visited.fill(0, 0, visitedSize);
2704
2908
  }
@@ -2784,11 +2988,12 @@
2784
2988
  const outInst = re2.prog.getInst(inst.out);
2785
2989
  if (Inst.isRuneOp(outInst.op)) {
2786
2990
  this.push(re2, inst.arg, currentPos, false);
2787
- currentPc = inst.out;
2991
+ currentPc = inst.arg;
2992
+ currentPos = this.end;
2788
2993
  continue;
2789
2994
  }
2790
2995
  this.push(re2, inst.out, this.end, false);
2791
- currentPc = inst.arg;
2996
+ currentPc = inst.out;
2792
2997
  continue;
2793
2998
  }
2794
2999
  case Inst.RUNE:
@@ -2869,6 +3074,11 @@
2869
3074
  if (currentPos === this.end) return true;
2870
3075
  break;
2871
3076
  }
3077
+ case Inst.LB_WRITE:
3078
+ case Inst.LB_CHECK:
3079
+ {
3080
+ throw new RE2JSInternalException('Backtracker cannot evaluate Lookbehind instructions');
3081
+ }
2872
3082
  default:
2873
3083
  {
2874
3084
  throw new RE2JSInternalException('bad inst');
@@ -3226,6 +3436,8 @@
3226
3436
  class OnePass {
3227
3437
  static compile(prog) {
3228
3438
  if (prog.start === 0) return null;
3439
+ // OnePass cannot evaluate Lookbehinds
3440
+ if (prog.numLb > 0) return null;
3229
3441
  const startInst = prog.inst[prog.start];
3230
3442
  // onepass regexps must be strictly anchored
3231
3443
  if (startInst.op !== Inst.EMPTY_WIDTH || (startInst.arg & Utils.EMPTY_BEGIN_TEXT) === 0) {
@@ -3303,6 +3515,10 @@
3303
3515
  switch (inst.op) {
3304
3516
  case Inst.MATCH:
3305
3517
  {
3518
+ // Verify ANCHOR_BOTH constraint before accepting the match
3519
+ if (anchor === RE2Flags.ANCHOR_BOTH && pos !== input.endPos()) {
3520
+ return null;
3521
+ }
3306
3522
  matched = true;
3307
3523
  if (matchcap.length > 0) {
3308
3524
  matchcap[0] = 0;
@@ -3405,6 +3621,10 @@
3405
3621
  // Matches concatenation of subs[]
3406
3622
  'ALTERNATE',
3407
3623
  // Matches union of subs[]
3624
+ 'PLB',
3625
+ // Positive LookBehind
3626
+ 'NLB',
3627
+ // Negative LookBehind
3408
3628
  // Pseudo ops, used internally by Parser for parsing stack:
3409
3629
  'LEFT_PAREN', 'VERTICAL_BAR']);
3410
3630
  static isPseudoOp(op) {
@@ -3429,6 +3649,7 @@
3429
3649
  regex.max = re.max;
3430
3650
  regex.name = re.name;
3431
3651
  regex.namedGroups = re.namedGroups;
3652
+ regex.lb = re.lb; // Track lookbehind index
3432
3653
  return regex;
3433
3654
  }
3434
3655
  constructor(op) {
@@ -3443,6 +3664,7 @@
3443
3664
  this.cap = 0; // capturing index, for CAPTURE
3444
3665
  this.name = null; // capturing name, for CAPTURE
3445
3666
  this.namedGroups = Object.create(null); // map of group name -> capturing index
3667
+ this.lb = 0; // Lookbehind index tracking
3446
3668
  }
3447
3669
  reinit() {
3448
3670
  this.flags = 0;
@@ -3453,6 +3675,7 @@
3453
3675
  this.max = 0;
3454
3676
  this.name = null;
3455
3677
  this.namedGroups = Object.create(null);
3678
+ this.lb = 0;
3456
3679
  }
3457
3680
  toString() {
3458
3681
  return this.appendTo();
@@ -3543,6 +3766,12 @@
3543
3766
  case Regexp.Op.ANY_CHAR:
3544
3767
  out += '(?s:.)';
3545
3768
  break;
3769
+ case Regexp.Op.PLB:
3770
+ out += `(?<=${this.subs[0].appendTo()})`;
3771
+ break;
3772
+ case Regexp.Op.NLB:
3773
+ out += `(?<!${this.subs[0].appendTo()})`;
3774
+ break;
3546
3775
  case Regexp.Op.CAPTURE:
3547
3776
  if (this.name === null || this.name.length === 0) {
3548
3777
  out += '(';
@@ -3707,11 +3936,101 @@
3707
3936
  }
3708
3937
  break;
3709
3938
  }
3939
+ case Regexp.Op.PLB:
3940
+ case Regexp.Op.NLB:
3941
+ {
3942
+ if (this.lb !== that.lb || !this.subs[0].equals(that.subs[0])) {
3943
+ return false;
3944
+ }
3945
+ break;
3946
+ }
3710
3947
  }
3711
3948
  return true;
3712
3949
  }
3713
3950
  }
3714
3951
 
3952
+ // High-speed, single-pass Aho-Corasick string matcher optimized for V8.
3953
+ // Builds a trie with failure links to search for multiple prefixes simultaneously.
3954
+ class AhoCorasick {
3955
+ constructor(wordArrays) {
3956
+ this.next = [Object.create(null)];
3957
+ this.fail = [0];
3958
+ this.match = [false];
3959
+
3960
+ // Build Trie
3961
+ for (const word of wordArrays) {
3962
+ let node = 0;
3963
+ for (let i = 0; i < word.length; i++) {
3964
+ const val = word[i];
3965
+ if (!(val in this.next[node])) {
3966
+ this.next.push(Object.create(null));
3967
+ this.fail.push(0);
3968
+ this.match.push(false);
3969
+ this.next[node][val] = this.next.length - 1;
3970
+ }
3971
+ node = this.next[node][val];
3972
+ }
3973
+ this.match[node] = true;
3974
+ }
3975
+
3976
+ // Build Failure Links (BFS)
3977
+ const queue = [];
3978
+ for (const val in this.next[0]) {
3979
+ if (Object.prototype.hasOwnProperty.call(this.next[0], val)) {
3980
+ const child = this.next[0][val];
3981
+ this.fail[child] = 0;
3982
+ queue.push(child);
3983
+ }
3984
+ }
3985
+ while (queue.length > 0) {
3986
+ const curr = queue.shift();
3987
+ for (const val in this.next[curr]) {
3988
+ if (Object.prototype.hasOwnProperty.call(this.next[curr], val)) {
3989
+ const child = this.next[curr][val];
3990
+ let failNode = this.fail[curr];
3991
+ while (failNode !== 0 && !(val in this.next[failNode])) {
3992
+ failNode = this.fail[failNode];
3993
+ }
3994
+ if (val in this.next[failNode]) {
3995
+ this.fail[child] = this.next[failNode][val];
3996
+ } else {
3997
+ this.fail[child] = 0;
3998
+ }
3999
+ this.match[child] = this.match[child] || this.match[this.fail[child]];
4000
+ queue.push(child);
4001
+ }
4002
+ }
4003
+ }
4004
+ }
4005
+ searchUTF16(charSeq, start, end) {
4006
+ let node = 0;
4007
+ for (let i = start; i < end; i++) {
4008
+ const val = charSeq.charCodeAt(i);
4009
+ while (node !== 0 && !(val in this.next[node])) {
4010
+ node = this.fail[node];
4011
+ }
4012
+ if (val in this.next[node]) {
4013
+ node = this.next[node][val];
4014
+ }
4015
+ if (this.match[node]) return true;
4016
+ }
4017
+ return false;
4018
+ }
4019
+ searchUTF8(bytes, start, end) {
4020
+ let node = 0;
4021
+ for (let i = start; i < end; i++) {
4022
+ const val = bytes[i];
4023
+ while (node !== 0 && !(val in this.next[node])) {
4024
+ node = this.fail[node];
4025
+ }
4026
+ if (val in this.next[node]) {
4027
+ node = this.next[node][val];
4028
+ }
4029
+ if (this.match[node]) return true;
4030
+ }
4031
+ return false;
4032
+ }
4033
+ }
3715
4034
  class Prefilter {
3716
4035
  static Type = {
3717
4036
  NONE: 0,
@@ -3724,6 +4043,8 @@
3724
4043
  this.subs = [];
3725
4044
  this.str = '';
3726
4045
  this.bytes = null;
4046
+ this.ac16 = null;
4047
+ this.ac8 = null;
3727
4048
  }
3728
4049
  eval(input, pos) {
3729
4050
  switch (this.type) {
@@ -3737,6 +4058,10 @@
3737
4058
  }
3738
4059
  return true;
3739
4060
  case Prefilter.Type.OR:
4061
+ // Exploit Aho-Corasick if it was successfully built
4062
+ if (this.ac16 && this.ac8) {
4063
+ return input.hasAnyString(this, pos);
4064
+ }
3740
4065
  for (let i = 0; i < this.subs.length; i++) {
3741
4066
  if (this.subs[i].eval(input, pos)) return true;
3742
4067
  }
@@ -3754,6 +4079,8 @@
3754
4079
  static fromRegexp(re) {
3755
4080
  if (!re) return new Prefilter(Prefilter.Type.NONE);
3756
4081
  switch (re.op) {
4082
+ case Regexp.Op.PLB:
4083
+ case Regexp.Op.NLB:
3757
4084
  case Regexp.Op.NO_MATCH:
3758
4085
  case Regexp.Op.EMPTY_MATCH:
3759
4086
  case Regexp.Op.BEGIN_LINE:
@@ -3825,7 +4152,9 @@
3825
4152
  const s = PrefilterTree.simplify(sub);
3826
4153
  if (s.type !== Prefilter.Type.NONE) {
3827
4154
  if (s.type === Prefilter.Type.AND) {
3828
- newSubs.push(...s.subs);
4155
+ for (let j = 0; j < s.subs.length; j++) {
4156
+ newSubs.push(s.subs[j]);
4157
+ }
3829
4158
  } else {
3830
4159
  newSubs.push(s);
3831
4160
  }
@@ -3867,6 +4196,27 @@
3867
4196
  }
3868
4197
  }
3869
4198
  pf.subs = uniqueSubs;
4199
+
4200
+ // Build an Aho-Corasick automaton if all children are exact matches
4201
+ let allExact = true;
4202
+ for (const sub of uniqueSubs) {
4203
+ if (sub.type !== Prefilter.Type.EXACT) {
4204
+ allExact = false;
4205
+ break;
4206
+ }
4207
+ }
4208
+ if (allExact && uniqueSubs.length > 1) {
4209
+ const words16 = uniqueSubs.map(s => {
4210
+ const arr = [];
4211
+ for (let i = 0; i < s.str.length; i++) {
4212
+ arr.push(s.str.charCodeAt(i));
4213
+ }
4214
+ return arr;
4215
+ });
4216
+ pf.ac16 = new AhoCorasick(words16);
4217
+ const words8 = uniqueSubs.map(s => s.bytes);
4218
+ pf.ac8 = new AhoCorasick(words8);
4219
+ }
3870
4220
  return pf;
3871
4221
  }
3872
4222
  return pf;
@@ -3904,6 +4254,8 @@
3904
4254
  // number of CAPTURE insts in re
3905
4255
  // 2 => implicit ( and ) for whole match $0
3906
4256
  this.numCap = 2;
4257
+ this.lbStarts = []; // Track starting PCs of lookbehind automata
4258
+ this.numLb = 0; // Total number of lookbehinds
3907
4259
  }
3908
4260
 
3909
4261
  // Returns the instruction at the specified pc.
@@ -4236,6 +4588,26 @@
4236
4588
  }
4237
4589
  return f;
4238
4590
  }
4591
+ lookBehind(a, lb) {
4592
+ const id = this.newInst(Inst.LB_WRITE);
4593
+ this.prog.getInst(id.i).lb = lb;
4594
+
4595
+ // Create the prefix wildcard `.*` for the lookbehind automaton
4596
+ const any = this.rune(Compiler.ANY_RUNE(), 0);
4597
+ const dotStar = this.star(any, true); // nongreedy = true
4598
+ const lbAutomaton = this.cat(dotStar, a);
4599
+ this.prog.patch(lbAutomaton.out, id.i);
4600
+ const checkId = this.newInst(Inst.LB_CHECK);
4601
+ this.prog.getInst(checkId.i).lb = lb;
4602
+
4603
+ // Save the starting point of this lookbehind automaton
4604
+ this.prog.lbStarts.push(lbAutomaton.i);
4605
+ if (Math.abs(lb) > this.prog.numLb) {
4606
+ this.prog.numLb = Math.abs(lb);
4607
+ }
4608
+ checkId.out = new PatchList(checkId.i << 1, checkId.i << 1);
4609
+ return checkId;
4610
+ }
4239
4611
  compile(re) {
4240
4612
  switch (re.op) {
4241
4613
  case Regexp.Op.NO_MATCH:
@@ -4271,6 +4643,9 @@
4271
4643
  return this.empty(Utils.EMPTY_WORD_BOUNDARY);
4272
4644
  case Regexp.Op.NO_WORD_BOUNDARY:
4273
4645
  return this.empty(Utils.EMPTY_NO_WORD_BOUNDARY);
4646
+ case Regexp.Op.PLB:
4647
+ case Regexp.Op.NLB:
4648
+ return this.lookBehind(this.compile(re.subs[0]), re.lb);
4274
4649
  case Regexp.Op.CAPTURE:
4275
4650
  {
4276
4651
  const bra = this.cap(re.cap << 1);
@@ -4330,6 +4705,8 @@
4330
4705
  return null;
4331
4706
  }
4332
4707
  switch (re.op) {
4708
+ case Regexp.Op.PLB:
4709
+ case Regexp.Op.NLB:
4333
4710
  case Regexp.Op.CAPTURE:
4334
4711
  {
4335
4712
  const sub = Simplify.simplify(re.subs[0]);
@@ -4366,7 +4743,9 @@
4366
4743
  // Flatten nested concatenations
4367
4744
  if (nsub.op === Regexp.Op.CONCAT) {
4368
4745
  changed = true;
4369
- newSubs.push(...nsub.subs);
4746
+ for (let j = 0; j < nsub.subs.length; j++) {
4747
+ newSubs.push(nsub.subs[j]);
4748
+ }
4370
4749
  continue;
4371
4750
  }
4372
4751
  } else if (re.op === Regexp.Op.ALTERNATE) {
@@ -4378,7 +4757,9 @@
4378
4757
  // Flatten nested alternations
4379
4758
  if (nsub.op === Regexp.Op.ALTERNATE) {
4380
4759
  changed = true;
4381
- newSubs.push(...nsub.subs);
4760
+ for (let j = 0; j < nsub.subs.length; j++) {
4761
+ newSubs.push(nsub.subs[j]);
4762
+ }
4382
4763
  continue;
4383
4764
  }
4384
4765
  }
@@ -5388,7 +5769,10 @@
5388
5769
  return t.pop();
5389
5770
  }
5390
5771
  static concatRunes(x, y) {
5391
- return [...x, ...y];
5772
+ for (let i = 0; i < y.length; i++) {
5773
+ x.push(y[i]);
5774
+ }
5775
+ return x;
5392
5776
  }
5393
5777
  constructor(wholeRegexp, flags = 0) {
5394
5778
  this.wholeRegexp = wholeRegexp;
@@ -5407,6 +5791,7 @@
5407
5791
  this.repeats = 0; // product of all repetitions seen
5408
5792
  this.height = null; // regexp height, for height limit check
5409
5793
  this.size = null; // regexp compiled size, for size limit check
5794
+ this.nlb = 0; // Number of lookbehinds seen
5410
5795
  }
5411
5796
 
5412
5797
  // Allocate a Regexp, from the free list if possible.
@@ -5423,8 +5808,8 @@
5423
5808
  return re;
5424
5809
  }
5425
5810
  reuse(re) {
5426
- if (this.height !== null && Object.prototype.hasOwnProperty.call(this.height, re)) {
5427
- delete this.height[re];
5811
+ if (this.height !== null && this.height.has(re)) {
5812
+ this.height.delete(re);
5428
5813
  }
5429
5814
  if (re.subs !== null && re.subs.length > 0) {
5430
5815
  re.subs[0] = this.free;
@@ -5456,20 +5841,20 @@
5456
5841
  if (n <= 0) {
5457
5842
  n = 1;
5458
5843
  }
5459
- if (n > Parser.MAX_SIZE / this.repeats) {
5844
+ if (n > Math.floor(Parser.MAX_SIZE / this.repeats)) {
5460
5845
  this.repeats = Parser.MAX_SIZE;
5461
5846
  } else {
5462
5847
  this.repeats *= n;
5463
5848
  }
5464
5849
  }
5465
- if (this.numRegexp < Parser.MAX_SIZE / this.repeats) {
5850
+ if (this.numRegexp < Math.floor(Parser.MAX_SIZE / this.repeats)) {
5466
5851
  return;
5467
5852
  }
5468
5853
 
5469
5854
  // We need to start tracking size.
5470
5855
  // Make the map and belatedly populate it
5471
5856
  // with info about everything we've constructed so far.
5472
- this.size = {};
5857
+ this.size = new Map();
5473
5858
  for (let reEx of this.stack) {
5474
5859
  this.checkSize(reEx);
5475
5860
  }
@@ -5479,9 +5864,9 @@
5479
5864
  }
5480
5865
  }
5481
5866
  calcSize(re, force = false) {
5482
- if (!force) {
5483
- if (Object.prototype.hasOwnProperty.call(this.size, re)) {
5484
- return this.size[re];
5867
+ if (!force && this.size !== null) {
5868
+ if (this.size.has(re)) {
5869
+ return this.size.get(re);
5485
5870
  }
5486
5871
  }
5487
5872
  let size = 0;
@@ -5491,6 +5876,8 @@
5491
5876
  size = re.runes.length;
5492
5877
  break;
5493
5878
  }
5879
+ case Regexp.Op.PLB:
5880
+ case Regexp.Op.NLB:
5494
5881
  case Regexp.Op.CAPTURE:
5495
5882
  case Regexp.Op.STAR:
5496
5883
  {
@@ -5538,7 +5925,10 @@
5538
5925
  }
5539
5926
  }
5540
5927
  size = Math.max(1, size);
5541
- this.size[re] = size;
5928
+ if (this.size === null) {
5929
+ this.size = new Map();
5930
+ }
5931
+ this.size.set(re, size);
5542
5932
  return size;
5543
5933
  }
5544
5934
  checkHeight(re) {
@@ -5546,7 +5936,7 @@
5546
5936
  return;
5547
5937
  }
5548
5938
  if (this.height === null) {
5549
- this.height = {};
5939
+ this.height = new Map();
5550
5940
  for (let reEx of this.stack) {
5551
5941
  this.checkHeight(reEx);
5552
5942
  }
@@ -5556,9 +5946,9 @@
5556
5946
  }
5557
5947
  }
5558
5948
  calcHeight(re, force = false) {
5559
- if (!force) {
5560
- if (Object.prototype.hasOwnProperty.call(this.height, re)) {
5561
- return this.height[re];
5949
+ if (!force && this.height !== null) {
5950
+ if (this.height.has(re)) {
5951
+ return this.height.get(re);
5562
5952
  }
5563
5953
  }
5564
5954
  let h = 1;
@@ -5568,7 +5958,10 @@
5568
5958
  h = 1 + hsub;
5569
5959
  }
5570
5960
  }
5571
- this.height[re] = h;
5961
+ if (this.height === null) {
5962
+ this.height = new Map();
5963
+ }
5964
+ this.height.set(re, h);
5572
5965
  return h;
5573
5966
  }
5574
5967
 
@@ -6136,6 +6529,19 @@
6136
6529
  let repeatPos = -1;
6137
6530
  bigswitch: switch (t.peek()) {
6138
6531
  case Codepoint.CODES.get('('):
6532
+ // Intercept Lookbehinds if the flag is enabled
6533
+ if ((this.flags & RE2Flags.LOOKBEHIND) !== 0) {
6534
+ if (t.lookingAt('(?<=')) {
6535
+ this.parsePosLookBehind();
6536
+ t.skip(4); // Skip over '(?<='
6537
+ break;
6538
+ }
6539
+ if (t.lookingAt('(?<!')) {
6540
+ this.parseNegLookBehind();
6541
+ t.skip(4); // Skip over '(?<!'
6542
+ break;
6543
+ }
6544
+ }
6139
6545
  if ((this.flags & RE2Flags.PERL_X) !== 0 && t.lookingAt('(?')) {
6140
6546
  // Flag changes and non-capturing groups.
6141
6547
  this.parsePerlFlags(t);
@@ -6416,6 +6822,20 @@
6416
6822
  throw new RE2JSSyntaxException(Parser.ERR_INVALID_PERL_OP, t.from(startPos));
6417
6823
  }
6418
6824
 
6825
+ // Lookbehinds parsing
6826
+ parsePosLookBehind() {
6827
+ const re = this.newRegexp(Regexp.Op.LEFT_PAREN);
6828
+ re.flags = this.flags;
6829
+ re.lb = ++this.nlb;
6830
+ return this.push(re);
6831
+ }
6832
+ parseNegLookBehind() {
6833
+ const re = this.newRegexp(Regexp.Op.LEFT_PAREN);
6834
+ re.flags = this.flags;
6835
+ re.lb = -++this.nlb;
6836
+ return this.push(re);
6837
+ }
6838
+
6419
6839
  // parseVerticalBar handles a | in the input.
6420
6840
  parseVerticalBar() {
6421
6841
  this.concat();
@@ -6485,6 +6905,18 @@
6485
6905
  }
6486
6906
  // Restore flags at time of paren.
6487
6907
  this.flags = re2.flags;
6908
+
6909
+ // Handle lookbehinds
6910
+ if (re2.lb !== 0) {
6911
+ if (re2.lb > 0) {
6912
+ re2.op = Regexp.Op.PLB;
6913
+ } else {
6914
+ re2.op = Regexp.Op.NLB;
6915
+ }
6916
+ re2.subs = [re1];
6917
+ this.push(re2);
6918
+ return;
6919
+ }
6488
6920
  if (re2.cap === 0) {
6489
6921
  // Just for grouping.
6490
6922
  this.push(re1);
@@ -6883,21 +7315,25 @@
6883
7315
  // We must use the NFA.
6884
7316
  if (ncap > 0) {
6885
7317
  // Backtracker bit-state execution bounds check
6886
- if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
7318
+ if (this.prog.numLb === 0 && input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
6887
7319
  return Backtracker.execute(this, input, pos, anchor, ncap);
6888
7320
  }
6889
7321
  // NFA execution
6890
7322
  return this.doExecuteNFA(input, pos, anchor, ncap);
6891
7323
  }
6892
- const dfaResult = this.dfa.match(input, pos, anchor);
6893
- if (dfaResult !== null) {
6894
- // DFA succeeded (returned true or false)
6895
- return dfaResult ? [] : null; // Return empty array to signify "matched but no captures"
6896
- }
6897
7324
 
6898
- // Backtracker bit-state execution bounds check
6899
- if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
6900
- return Backtracker.execute(this, input, pos, anchor, ncap);
7325
+ // The DFA will safely return null (bailout) if it encounters a lookbehind
7326
+ if (this.prog.numLb === 0) {
7327
+ const dfaResult = this.dfa.match(input, pos, anchor);
7328
+ if (dfaResult !== null) {
7329
+ // DFA succeeded (returned true or false)
7330
+ return dfaResult ? [] : null; // Return empty array to signify "matched but no captures"
7331
+ }
7332
+
7333
+ // Backtracker bit-state execution bounds check
7334
+ if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
7335
+ return Backtracker.execute(this, input, pos, anchor, ncap);
7336
+ }
6901
7337
  }
6902
7338
 
6903
7339
  // Fallback to NFA
@@ -7481,9 +7917,20 @@
7481
7917
  }
7482
7918
 
7483
7919
  class RE2Set {
7484
- constructor(anchor = RE2Flags.UNANCHORED, flags = RE2Flags.PERL) {
7920
+ static UNANCHORED = RE2Flags.UNANCHORED;
7921
+ static ANCHOR_START = RE2Flags.ANCHOR_START;
7922
+ static ANCHOR_BOTH = RE2Flags.ANCHOR_BOTH;
7923
+ constructor(anchor = RE2Set.UNANCHORED, flags = 0) {
7485
7924
  this.anchor = anchor;
7486
- this.flags = flags;
7925
+ this.jsFlags = flags;
7926
+ let re2Flags = RE2Flags.PERL;
7927
+ if ((flags & PublicFlags.DISABLE_UNICODE_GROUPS) !== 0) {
7928
+ re2Flags &= -129;
7929
+ }
7930
+ if ((flags & PublicFlags.LOOKBEHINDS) !== 0) {
7931
+ re2Flags |= RE2Flags.LOOKBEHIND;
7932
+ }
7933
+ this.re2Flags = re2Flags;
7487
7934
  this.regexps = [];
7488
7935
  this.prog = null;
7489
7936
  this.dfa = null;
@@ -7493,7 +7940,17 @@
7493
7940
  if (this.prog) {
7494
7941
  throw new RE2JSCompileException('Cannot add patterns after compile');
7495
7942
  }
7496
- const re = Parser.parse(pattern, this.flags);
7943
+ let fregex = pattern;
7944
+ if ((this.jsFlags & PublicFlags.CASE_INSENSITIVE) !== 0) {
7945
+ fregex = `(?i)${fregex}`;
7946
+ }
7947
+ if ((this.jsFlags & PublicFlags.DOTALL) !== 0) {
7948
+ fregex = `(?s)${fregex}`;
7949
+ }
7950
+ if ((this.jsFlags & PublicFlags.MULTILINE) !== 0) {
7951
+ fregex = `(?m)${fregex}`;
7952
+ }
7953
+ const re = Parser.parse(fregex, this.re2Flags);
7497
7954
  this.regexps.push(Simplify.simplify(re));
7498
7955
  return this.regexps.length - 1;
7499
7956
  }
@@ -7512,15 +7969,21 @@
7512
7969
  match(input) {
7513
7970
  if (!this.prog) this.compile();
7514
7971
  const machineInput = Array.isArray(input) ? MachineInput.fromUTF8(input) : MachineInput.fromUTF16(input);
7972
+ let internalAnchor = RE2Flags.UNANCHORED;
7973
+ if (this.anchor === RE2Set.ANCHOR_START) {
7974
+ internalAnchor = RE2Flags.ANCHOR_START;
7975
+ } else if (this.anchor === RE2Set.ANCHOR_BOTH) {
7976
+ internalAnchor = RE2Flags.ANCHOR_BOTH;
7977
+ }
7515
7978
 
7516
7979
  // Fast path: Try the blistering fast DFA
7517
- const dfaResult = this.dfa.matchSet(machineInput, 0, this.anchor);
7980
+ const dfaResult = this.dfa.matchSet(machineInput, 0, internalAnchor);
7518
7981
  if (dfaResult !== null) return dfaResult;
7519
7982
 
7520
7983
  // Safe Fallback: Handle boundaries (\b) or massive state explosions via NFA
7521
7984
  const machine = Machine.fromRE2(this.dummyRe2);
7522
7985
  machine.init(0);
7523
- return machine.matchSet(machineInput, 0, this.anchor);
7986
+ return machine.matchSet(machineInput, 0, internalAnchor);
7524
7987
  }
7525
7988
  }
7526
7989
 
@@ -7620,7 +8083,7 @@
7620
8083
  changed = true;
7621
8084
  continue;
7622
8085
  } else if (ch === '(' && i + 2 < size && data[i + 1] === '?' && data[i + 2] === '<') {
7623
- if (i + 3 >= size || data[i + 3] !== '=' && data[i + 3] !== '!') {
8086
+ if (i + 3 < size && !'=!>)'.includes(data[i + 3])) {
7624
8087
  result += '(?P<';
7625
8088
  i += 3;
7626
8089
  changed = true;
@@ -7650,24 +8113,28 @@
7650
8113
  /**
7651
8114
  * Flag: case insensitive matching.
7652
8115
  */
7653
- static CASE_INSENSITIVE = 1;
8116
+ static CASE_INSENSITIVE = PublicFlags.CASE_INSENSITIVE;
7654
8117
  /**
7655
8118
  * Flag: dot ({@code .}) matches all characters, including newline.
7656
8119
  */
7657
- static DOTALL = 2;
8120
+ static DOTALL = PublicFlags.DOTALL;
7658
8121
  /**
7659
8122
  * Flag: multiline matching: {@code ^} and {@code $} match at beginning and end of line, not just
7660
8123
  * beginning and end of input.
7661
8124
  */
7662
- static MULTILINE = 4;
8125
+ static MULTILINE = PublicFlags.MULTILINE;
7663
8126
  /**
7664
8127
  * Flag: Unicode groups (e.g. {@code \p\ Greek\} ) will be syntax errors.
7665
8128
  */
7666
- static DISABLE_UNICODE_GROUPS = 8;
8129
+ static DISABLE_UNICODE_GROUPS = PublicFlags.DISABLE_UNICODE_GROUPS;
7667
8130
  /**
7668
8131
  * Flag: matches longest possible string.
7669
8132
  */
7670
- static LONGEST_MATCH = 16;
8133
+ static LONGEST_MATCH = PublicFlags.LONGEST_MATCH;
8134
+ /**
8135
+ * Flag: enable linear-time captureless lookbehinds.
8136
+ */
8137
+ static LOOKBEHINDS = PublicFlags.LOOKBEHINDS;
7671
8138
 
7672
8139
  /**
7673
8140
  * Returns a literal pattern string for the specified string.
@@ -7730,13 +8197,16 @@
7730
8197
  if ((flags & RE2JS.MULTILINE) !== 0) {
7731
8198
  fregex = `(?m)${fregex}`;
7732
8199
  }
7733
- if ((flags & ~(RE2JS.MULTILINE | RE2JS.DOTALL | RE2JS.CASE_INSENSITIVE | RE2JS.DISABLE_UNICODE_GROUPS | RE2JS.LONGEST_MATCH)) !== 0) {
7734
- throw new RE2JSFlagsException('Flags should only be a combination of MULTILINE, DOTALL, CASE_INSENSITIVE, DISABLE_UNICODE_GROUPS, LONGEST_MATCH');
8200
+ if ((flags & ~(RE2JS.MULTILINE | RE2JS.DOTALL | RE2JS.CASE_INSENSITIVE | RE2JS.DISABLE_UNICODE_GROUPS | RE2JS.LONGEST_MATCH | RE2JS.LOOKBEHINDS)) !== 0) {
8201
+ throw new RE2JSFlagsException('Flags should only be a combination of MULTILINE, DOTALL, CASE_INSENSITIVE, DISABLE_UNICODE_GROUPS, LONGEST_MATCH, LOOKBEHINDS');
7735
8202
  }
7736
8203
  let re2Flags = RE2Flags.PERL;
7737
8204
  if ((flags & RE2JS.DISABLE_UNICODE_GROUPS) !== 0) {
7738
8205
  re2Flags &= -129;
7739
8206
  }
8207
+ if ((flags & RE2JS.LOOKBEHINDS) !== 0) {
8208
+ re2Flags |= RE2Flags.LOOKBEHIND;
8209
+ }
7740
8210
  const p = new RE2JS(regex, flags);
7741
8211
  // The compiled RE2 regexp.
7742
8212
  p.re2Input = RE2.compileImpl(fregex, re2Flags, (flags & RE2JS.LONGEST_MATCH) !== 0);