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
@@ -42,6 +42,8 @@ class RE2Flags {
42
42
  static UNICODE_GROUPS = 0x80;
43
43
  // Regexp END_TEXT was $, not \z. Internal use only.
44
44
  static WAS_DOLLAR = 0x100;
45
+ // Allow captureless Lookbehinds (?<=) and (?<!)
46
+ static LOOKBEHIND = 0x200;
45
47
  static MATCH_NL = RE2Flags.CLASS_NL | RE2Flags.DOT_NL;
46
48
  // As close to Perl as possible.
47
49
  static PERL = RE2Flags.CLASS_NL | RE2Flags.ONE_LINE | RE2Flags.PERL_X | RE2Flags.UNICODE_GROUPS;
@@ -53,12 +55,31 @@ class RE2Flags {
53
55
  static ANCHOR_BOTH = 2;
54
56
  }
55
57
 
58
+ /**
59
+ * Public flags for RE2JS and RE2Set compilation.
60
+ */
61
+ const PublicFlags = {
62
+ CASE_INSENSITIVE: 1,
63
+ // case insensitive matching
64
+ DOTALL: 2,
65
+ // dot matches all characters, including newline
66
+ MULTILINE: 4,
67
+ // multiline matching
68
+ DISABLE_UNICODE_GROUPS: 8,
69
+ // unicode groups will be syntax errors
70
+ LONGEST_MATCH: 16,
71
+ // matches longest possible string
72
+ LOOKBEHINDS: 512 // enable linear-time captureless lookbehinds
73
+ };
74
+
56
75
  /**
57
76
  * Various constants and helper for unicode codepoints.
58
77
  */
59
78
  const ASCII_SIZE = 128;
60
79
  const ASCII_TO_UPPER = new Int32Array(ASCII_SIZE);
61
80
  const ASCII_TO_LOWER = new Int32Array(ASCII_SIZE);
81
+ // The highest legal Basic Multilingual Plane (BMP) value.
82
+ const MAX_BMP = 0xffff;
62
83
  for (let i = 0; i < ASCII_SIZE; i++) {
63
84
  if (i >= 97 && i <= 122) {
64
85
  // a-z
@@ -82,11 +103,13 @@ class Codepoint {
82
103
  static toUpperCase(codepoint) {
83
104
  if (codepoint < ASCII_SIZE) return ASCII_TO_UPPER[codepoint];
84
105
  const s = String.fromCodePoint(codepoint).toUpperCase();
85
- if (s.length > 1) {
106
+ const expectedLen = s.codePointAt(0) > MAX_BMP ? 2 : 1;
107
+ if (s.length > expectedLen) {
86
108
  return codepoint;
87
109
  }
88
110
  const sOrigin = String.fromCodePoint(s.codePointAt(0)).toLowerCase();
89
- if (sOrigin.length > 1 || sOrigin.codePointAt(0) !== codepoint) {
111
+ const originExpectedLen = sOrigin.codePointAt(0) > MAX_BMP ? 2 : 1;
112
+ if (sOrigin.length > originExpectedLen || sOrigin.codePointAt(0) !== codepoint) {
90
113
  return codepoint;
91
114
  }
92
115
  return s.codePointAt(0);
@@ -97,11 +120,13 @@ class Codepoint {
97
120
  static toLowerCase(codepoint) {
98
121
  if (codepoint < ASCII_SIZE) return ASCII_TO_LOWER[codepoint];
99
122
  const s = String.fromCodePoint(codepoint).toLowerCase();
100
- if (s.length > 1) {
123
+ const expectedLen = s.codePointAt(0) > MAX_BMP ? 2 : 1;
124
+ if (s.length > expectedLen) {
101
125
  return codepoint;
102
126
  }
103
127
  const sOrigin = String.fromCodePoint(s.codePointAt(0)).toUpperCase();
104
- if (sOrigin.length > 1 || sOrigin.codePointAt(0) !== codepoint) {
128
+ const originExpectedLen = sOrigin.codePointAt(0) > MAX_BMP ? 2 : 1;
129
+ if (sOrigin.length > originExpectedLen || sOrigin.codePointAt(0) !== codepoint) {
105
130
  return codepoint;
106
131
  }
107
132
  return s.codePointAt(0);
@@ -203,52 +228,52 @@ class UnicodeTables {
203
228
  static _CASE_ORBIT = null;
204
229
  static get CASE_ORBIT() {
205
230
  if (!this._CASE_ORBIT) {
206
- 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');
231
+ this._CASE_ORBIT = decodeOrbit('rCrDIzDYqpII-LiC8cQlHa+0HGrpI6EzClClOBmOBkOBoOBpOBnOBrOBsOBqOlByPBzPBxPyK5crCz+HCydD1dD4dB5dB6dC8dEgeBheCieDmeDpeHj-HCweD1fDxeB+9HBwfC1FE2eBxfBjeBjdD1eDmpIHycB0fEmdBgda6cBhdD4cB1cdyhBC0hBK+hBDhiBBiiBIqiBIgkHChkHKikHDjkHBkkHImkHYjjBBnkH9gGygBB0gBB+gBBhhBBlkHBihBBqhBBijBBqypB4OhzHB70H6BgzHD-GiHo8HBp8HBq8HBr8HBs8HBt8HBu8HBv8HBg8HBh8HBi8HBj8HBk8HBl8HBm8HBn8HB48HB58HB68HB78HB88HB98HB+8HB-8HBw8HBx8HBy8HBz8HB08HB18HB28HB38HBo9HBp9HBq9HBr9HBs9HBt9HBu9HBv9HBg9HBh9HBi9HBj9HBk9HBl9HBm9HBn9HE89HJz9HClaFs+HJj+HHwcQwdQ8-HJz-HqJpdErCBlG-ohBrypBBokH6lVm4+BBl4+B');
207
232
  }
208
233
  return this._CASE_ORBIT;
209
234
  }
210
235
  static _Print = null;
211
236
  static get Print() {
212
237
  if (!this._Print) {
213
- this._Print = new UnicodeRangeTable(decodeRanges('hB9CBjBLBCpWBDFBFGBCCCBSBCsMBClBBDxBBDCBC2BBJaBFFBSVBC-FBCvBBD6BBDkDBP6BBDwBBDOBCbBDCCBJBGeBJqCBCgFBCHBDBBDVBCGBCEEBCBDIBDBBDDBJFFBCCBDBDYBDCBCFBFBBDVBCGBCBBCBBCBBDCCBDBFBBDCBEIIBCBCIIBPBLCBCIBCCBCVBCGBCBBCEBDJBCCBCCBDQQBCBDLBIGBCCBCHBDBBDVBCGBCBBCEBDIBDBBDCBICBFBBCEBDRBLBBCFBECBCDBEBBCCCBEEBEEBBBELBFEBECBCDBDHHPUBGMBCCBCWBCPBDIBCCBCDBIBBCCBDDDBCBDJBIVBCCBCWBCJBCEBDIBCCBCDBIBBHBBCDBDJBCCBNMBCCBCyBBCCBCFBFPBDZBCCBCRBEXBCIBCDDBFBEFFBEBCCCBGBHJBDCBN5BBFcBmBBBCCCBDBCXBCCCBVBDEBCCCBFBCJBDDBhBnCBCjBBFmBBCjBBCOBCMBmBlGBCGGD4LBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBDfBEZBH1CBDFBD-TBCbBE4CBIVBKXBKTBNMBCCBCBBN9CBDJBHJBHNBCKBH4CBIqBBGlCBLeBCLBFLBFEEBoBBDEBMrBBFZBHKBE9BBDgCBCcBDKBHJBHNBDeByBsCBClFBJ7BBEOBE9BBGqBBDKBJqBBG1QBDFBDlBBDFBDHBCGCBdBD0BBCOBCNBDFBCSBDCBCIBSXBJuBBSBBDaBCMBEgBBQgBBQrEBF5UBXKBWz4BBDfBC8KBGsBBCGGD3BBIBBPXBKGBCGBCGBCGBCGBCGBCGBCGBC9DBjBZBC4CBN1GBbPBC+BBC1CBDmDBGqBBC9CBC1CBKvBBCszcBE2BBK7KBV3FBJtGBDBBCCCBGBW6BBEJBH3BBJlCBJLBHzDBMdBEtCBCKBFgBBC2BBKNBDJBDmDBZbBLFBDFBDFBKGBCGBC7BBF9DBDJBHj9KBNWBFwBBloItLBDpDBnBGBNEBGZBCEBCCCBCCBCCB7DBR8NBD1BBIhBhBBoBBHyBBCSBCDBFEBCmEBF9FBEFBDFBDFBDCBEGBCGBOBBDLBCZBCSBCBBCOBDNBjB6DBGCBFsBBE3CBCMBEwBwBBsBBjEcBEwBBQbBFjBBKdBGqBBGdBCkBBFNBrB9EBDJBHjBBFjBBFnBBJzBBMLBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBCnCBJIBxBSBCBBGgBBEaBGhChCB2BBFTBDxBBCBBGHBCCBCcBDCBFJBIIBI-BBhBmBBFLBK1BBEcBDaBGZBIDBNGBxCoCB4ByBBOyBBItBBJJBHlBBEcBJBBxGeBCpBBCCBDBBRCB4BrBBJpBBXZBnBbBVWBKtCBFjBBK9BBCEBOYBIJBH0BBCRBJmBBK-CBCTBMRBCuBB-BGBCCCBCBCOBCKBH6BBGJBHDBCHBDBBDVBCGBCBBCEBCJBDBBDCBDHHGGBDGBEEBMJBCDDClBBCJBCDDCDBCJBCBBJBBe7CBCEBfnCBJJBnF1BBDlBBjBkCBMJBHMBU5BBHJBHTBdaBDOBFWB6F7BBlDyCBNHBDDDBGBCBBCdBCBBDLBKJBnCHBDtBBDKBcnCBJyCBOoCBIJB3FhBBPJBHIBCsBBCNBLcBEfBDVBCNBqCGBCBBCrBBECCBCCBHBJJBHFBCBBCkBBCBBCFBIJB3JYBIQBCoBBEcB2CQQBwBBO6cBnDuDBCEBMjGBtyCiDBOvhBBRVBL68DBGmSB61G5BBn2B4RBIeBCJBFwCBCJBHdBDFBLlCBLJBCGBCUBGSBxN5BBnG6CBmDqCBF4BBIQBhCEBMBBP3-FBJ1mBBqBJBo3IDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBDDBh7D5HBHzNBtCtBBDWBKzDB9B1HBLmBBDpCBJvDBWlCB7DTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBD9VBQEBCOBxiBeBHFB2GGBCQBDGBCBBCEBG9BBiBxDxDBrBBENBDJBFBBhKeBS5BBGxOxOBoBB3GqBBFhPhPBFBCDBCBBCOBCkGBDPBqBrCBFJBFBByYjCBtC8BBjGDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBBvIrBBFjDBNOBDOBCOBCkBBLtFB5BcBOrBBFIBIBBPFB7E3eBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBClDBngB-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEBxq3VvHB', false));
238
+ this._Print = new UnicodeRangeTable(decodeRanges('hB9CBjBLBCpWBDFBFGBCCCBSBCsMBClBBDxBBDCBC2BBJaBFFBSVBC-FBCvBBD6BBDkDBP6BBDwBBDOBCbBDCCBJBGfBIqCBCgFBCHBDBBDVBCGBCEEBCBDIBDBBDDBJFFBCCBDBDYBDCBCFBFBBDVBCGBCBBCBBCBBDCCBDBFBBDCBEIIBCBCIIBPBLCBCIBCCBCVBCGBCBBCEBDJBCCBCCBDQQBCBDLBIGBCCBCHBDBBDVBCGBCBBCEBDIBDBBDCBICBFBBCEBDRBLBBCFBECBCDBEBBCCCBEEBEEBBBELBFEBECBCDBDHHPUBGMBCCBCWBCPBDIBCCBCDBIBBCCBCBBDDBDJBIVBCCBCWBCJBCEBDIBCCBCDBIBBGCBCDBDJBCCBNMBCCBCyBBCCBCFBFPBDZBCCBCRBEXBCIBCDDBFBEFFBEBCCCBGBHJBDCBN5BBFcBmBBBCCCBDBCXBCCCBVBDEBCCCBFBCJBDDBhBnCBCjBBFmBBCjBBCOBCMBmBlGBCGGD4LBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBDfBEZBH1CBDFBD-TBCbBE4CBIVBKXBKTBNMBCCBCBBN9CBDJBHJBHNBCKBH4CBIqBBGlCBLeBCLBFLBFEEBoBBDEBMrBBFZBHKBE9BBDgCBCcBDKBHJBHNBDtBBDLBVsCBClFBJ7BBEOBE9BBGqBBDKBJqBBG1QBDFBDlBBDFBDHBCGCBdBD0BBCOBCNBDFBCSBDCBCIBSXBJuBBSBBDaBCMBEhBBPgBBQrEBF5UBXKBWz4BBD9LBGsBBCGGD3BBIBBPXBKGBCGBCGBCGBCGBCGBCGBCGBC9DBjBZBC4CBN1GBbPBC+BBC1CBDmDBGqBBC9CBC1CBKvBBCszcBE2BBK7KBV3FBJ8GBV7BBEJBH3BBJlCBJLBHzDBMdBEtCBCKBFgBBC2BBKNBDJBDmDBZbBLFBDFBDFBKGBCGBC7BBF9DBDJBHj9KBNWBFwBBloItLBDpDBnBGBNEBGZBCEBCCCBCCBCCBoUBhBpBBHyBBCSBCDBFEBCmEBF9FBEFBDFBDFBDCBEGBCGBOBBDLBCZBCSBCBBCOBDNBjB6DBGCBFsBBE3CBCMBEwBwBBsBBjEcBEwBBQbBFjBBKdBGqBBGdBCkBBFNBrB9EBDJBHjBBFjBBFnBBJzBBMLBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBCnCBJIBxBSBCBBGgBBEaBGaBnB3BBFTBDxBBCBBGHBCCBCcBDCBFJBIIBI-BBhBmBBFLBK1BBEcBDaBGZBIDBNGBxCoCB4ByBBOyBBItBBJJBHlBBEcBJBBxGeBCpBBCCBDBBRFBJIBiBtBBJpBBXZBnBbBVWBKtCBFjBBK9BBCEBOYBIJBH0BBCRBJmBBK-CBCTBMRBCuBB-BGBCCCBCBCOBCKBH6BBGJBHDBCHBDBBDVBCGBCBBCEBCJBDBBDCBDHHGGBDGBEEBMJBCDDClBBCJBCDDCDBCJBCBBJBBe7CBCEBfnCBJJBnF1BBDlBBjBkCBMJBHMBU5BBHJBHTBdaBDOBFWB6F7BBlDyCBNHBDDDBGBCBBCdBCBBDLBKJBnCHBDtBBDKBcnCBJyCBOoCBIJB3CHB5ChBBPJBHIBCsBBCNBLcBEfBDVBCNBqCGBCBBCrBBECCBCCBHBJJBHFBCBBCkBBCBBCFBIJBHrBBFJB3HYBIQBCoBBEcB2CQQBwBBO6cBnDuDBCEBMjGBtyCiDBOvhBBRVBL68DBGmSB61G5BBn2B4RBIeBCJBFwCBCJBHdBDFBLlCBLJBCGBCUBGSBxN5BBnG6CBGYBDYBtBqCBF4BBIQBhCEBMGBK1mHBqBfBiDyDB+vIDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBDDBh7D8HBEzNBHWBQQBQtBBDWBKzDB9B1HBLmBBDpCBJvDBWlCB7DTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBD9VBQEBCOBxiBeBHFB2GGBCQBDGBCBBCEBG9BBiBxDxDBrBBENBDJBFBBhKeBS5BBGxOxOBoBB3GqBBFhGhGBdBCVBJBBhHGBCDBCBBCOBCkGBDPBqBrCBFJBFBByYjCBtC8BBjGDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBBvIrBBFjDBNOBDOBCOBCkBBLtFB5BcBOrBBFIBIBBPFB7E4eBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBBPIBoB3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBCmDBmgB-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIBnkzVvHB', false));
214
239
  }
215
240
  return this._Print;
216
241
  }
217
242
  static CATEGORIES = new LazyMap({
218
- 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)),
243
+ 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)),
219
244
  Cc: () => new UnicodeRangeTable(decodeRanges('AfgDgB', true)),
220
245
  Cf: () => new UnicodeRangeTable(decodeRanges('tFzqBzqBBEBXhGhGyBhMhMBxCxCs5D9-B9-BBDBbEByBEBCJBw03B6H6HBBBimEQQj7IPBhjiBDBwmFHBn0rYffB+CB', false)),
221
- 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)),
246
+ 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)),
222
247
  Co: () => new UnicodeRangeTable(decodeRanges('gg4B-nGh4hc9--BD9--B', true)),
223
248
  Cs: () => new UnicodeRangeTable(decodeRanges('gg2B--B', true)),
224
- L: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBLLFGGBVBCeBCpOBFLBPEBICCiEEBCBBDDBCHHCCBCCCBSBCyCBCqEBJlFBClBBDHHBnBBoCaBFDBuBqBBkBBBCiDBCQQBIIBLLBBBDRRCdBe4CBMZZBfBKBBFGGBUBFKKEYYBXBIKBGXBCFBSpBB7B1BBETTIJBQPBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBDDDBffFHBCCBCWBCJBCEBEgBgBBCCBQQBSSBHBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNGB7BBBCCCBDBCXBCCCBIBCBBKDDBDBCWWBCBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNSSBkBBCGGDqBBCsKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPBR1CBDFBErTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBkBFFkC4CBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBzC+C+CBtBBSHB3BdBOBBLrBBbjBBqBCBLjBBDKBGqBBDCBqBDBCFBCBBEGGB+FBhC1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGB1DOORMBmDFFDJBCEEBDBHGCBCBCKBDDBGEBF1B1BB8zC8zCBjHBHDBEBBNlBBCGGD3BBIRRBVBKGBCGBCGBCGBCGBCGBCGBCGBxC2O2OBrBrBBDBGBBF1CBHCBC5CBCDBGqBBC9CBSfBxBPBhQ-tGBhCs0VBkCtBBDsIBEPBLBBVuBBReBDlCByBIBDmDBDiCBDBBCCCBGBWPBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBdRRBDBCJBLEBCoBBYCBCHBVWBEEEBwBBCEEBDDBDBDCCZCBDKBICBNFBDFBDFBKGBCGBCqBBCNBHyDBej9KBNWBFwBBloItLBDpDBnBGBNEBGCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBlBZBHZBM4CBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBxB9EBTjBBFjBBFnBBJzBBNKBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBnC3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4ByBBOyBBOjBBnBbBKWB7HpBBHBBRCB8BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB1D-BBgBHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPoKoKBRBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBBRDBgBUBGSBxNsBB0G-BBhEqCBGjCjCBLBhCBBCddB2-FBJ1mBBqBJBo3IDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBn7F0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BeBHFBmI9BBzEsBBLGBRiKiKBcBTrBBlPbBlHdBDwPwPBFBCDBCBBCOBCkGB8BjCBI1lB1lBBCBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEB', false)),
225
- LC: () => new UnicodeRangeTable(decodeRanges('hCZBHZB7BLLBVBCeBCiGBCDBFvGBCaBhGDBDBBECBCHHCCBCCCBSBCyCBCqEBJlFBClBBKoBB44ClBBCGGDqBBDCBhV1CBDFBjkCKBGqBBDCBhCrBBgCMBChBBmD1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGBmIFFDJBCEEBDBHGCBCBCFBFDDBCBGEBF1B1BB8zC8zCB6DBDmDBHDBEBBNlBBCGGzoetBBTbBnEtCBCWBEDBC9BBDBBCCCBGBZBBE2Z2ZBpBBGIBIvCBh6TGBNEBqgBZBHZBmlBvCBhDjBBFjBB1DKBCOBCGBCBBCKBCOBCGBCBBk2ByBBOyBB+CVBLVB74C-BBhrV-BBhsZ0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BJBCTBHFB2uCjCB', false)),
226
- Ll: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBC2BCBQCBuBCDECBBBDCCDEEBFFDEEBBBDDDCCCDCCBCCDEECDDBDDBBBHGDCOCBSCBDDCEEC4BCBFBDDDBCCFICBjCBCaBiGCCEEEBBBTccBhBBCBBECBCWCBDBCGDB0B0BBuBBCgBCK0BCDMCBgDCxBoBBo6CqBBDCB5XFBjkCIBC2D2DBqBBgCMBChBBnD0ECBHBCgDCBHBJFBLHBJHBJFBLHBJHBJNBDHBJHBJHBJEBCBBHEEBBBCBBJDBDBBJHBLCBCBBzIEEBEEcKFDBBJDBF2B2Bs1CvBBCEEBGCFCCBCCBEBGiDCBIICFFNlBBCGG0oesBCUaCoEMCBBBC+BCBGBCCCDICFCCDCCBBBCSCGGGCMCFCCDEECICbEE2ZqBBGIBIvCBh6TGBNEBqhBZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfB7sZZBbGBCRBbZBbDBCCCBFBCKBbZBbZBbZBbZBbZBbZBbZBbZBbbBdYBCFBbYBCFBbYBCFBbYBCFBbYBCFBC15B15BBIBCTBHFB4vChBB', false)),
227
- Lm: () => new UnicodeRangeTable(decodeRanges('wVRBFLBPEBICCmEGG-OnHnHlFBBuIBBFgBgBKEEhFoFoF1mBgEgE2R72B72BsDkTkTxOFBvF+BBOjBjBBjBByVOORMBg-CBByHgGgG2OsBsBBDBGiDiDB+C+CBBB34bjnBjnBBEBvIzDzDdBB6DIBxCYYqDCBEBB2OXXqEtDtDWBBoDDBKngVngVuBBBh-BFBCpBBCIB0sBhBhBxuXDB9PCBpBBBnRMBhCBBCtgQtgQBCBCGBCBByhM9BBqGGBudgjBgjB', false)),
228
- Lo: () => new UnicodeRangeTable(decodeRanges('qFQQhIFFBCBxG8Z8ZBZBFDBuBfBCJBkBBBCiDBCZZBLLBBBDRRCdBe4CBMZZBfBWVBrBYBIKBGXBCFBSoBB8B1BBETTIJBROBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBDDDBffFHBCCBCWBCJBCEBEgBgBBCCBQQBSSBHBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNFB8BBBCCCBDBCXBCCCBIBCBBKDDBDBYDBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNyDyDBnKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPByDrTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBpBkCkCBhBBC0BBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBxFuBBSHB3BdBOBBLrBBbjBBqBCBLdByDDBCFBCBBE7hB7hBBCB4-C3BBZWBKGBCGBCGBCGBCGBCGBCGBCGBoR2B2BF1CBJCCB4CBFGGBpBBC9CBSfBxBPBhQ-tGBhC0wUBC2jBBkCnBBJrIBFPBLBBjCyByBBkCBqFoDoDEGBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBuBEBDIBLEBCoBBYCBCHBVPBCFBEEEBwBBCEEBDDBDBDCCZBBEKBIPPBEBDFBDFBKGBCGByEiBBej9KBNWBFwBBloItLBDpDBkCCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBqDJBCsBBDeBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBhEtCBjDnBBJzBB9CzBBN2JBKVBLHB5EFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBnC3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4FjBBnBDBCxJxJBoBBHBBRCB8BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB0GHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPoKoKBRBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBB0BUBGSB0NnBB2MqCBGwFwFB2-FBJ1mBBqBJB43IiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBxzI2P2PBrBBiBiKiKBcBTrBBlPaBmHdBDwPwPBFBCDBCBBCOBCkGB8pBDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEB', false)),
249
+ L: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBLLFGGBVBCeBCpOBFLBPEBICCiEEBCBBDDBCHHCCBCCCBSBCyCBCqEBJlFBClBBDHHBnBBoCaBFDBuBqBBkBBBCiDBCQQBIIBLLBBBDRRCdBe4CBMZZBfBKBBFGGBUBFKKEYYBXBIKBGXBCGBRpBB7B1BBETTIJBQPBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBCBBDBBfFFBGBCCBCWBCJBCEBEffBBBCBBQBBSIBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNGB7BBBCCCBDBCXBCCCBIBCBBKDDBDBCWWBCBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNSSBkBBCGGDqBBCsKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPBR1CBDFBErTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBkBFFkC4CBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBzC+C+CBtBBSHB3BdBOBBLrBBbjBBqBCBLjBBDKBGqBBDCBqBDBCFBCBBEGGB+FBhC1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGB1DOORMBmDFFDJBCEEBDBHGCBCBCKBDDBGEBF1B1BB8zC8zCBjHBHDBEBBNlBBCGGD3BBIRRBVBKGBCGBCGBCGBCGBCGBCGBCGBxC2O2OBrBrBBDBGBBF1CBHCBC5CBCDBGqBBC9CBSfBxBPBhQ-tGBhCs0VBkCtBBDsIBEPBLBBVuBBReBDlCByBIBDmDBDxCBVQBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBdRRBDBCJBLEBCoBBYCBCHBVWBEEEBwBBCEEBDDBDBDCCZCBDKBICBNFBDFBDFBKGBCGBCqBBCNBHyDBej9KBNWBFwBBloItLBDpDBnBGBNEBGCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBlBZBHZBM4CBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBxB9EBTjBBFjBBFnBBJzBBNKBCOBCGBCBBCKBCOBCGBCBBEzBBN2JBKVBLHBZFBCpBBCIBmCFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBHZBnB3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4ByBBOyBBOjBBnBbBKWB7HpBBHBBRFB5BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB1D-BBgBHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPYYBqBBlISBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBBRDBgBUBGSBxNsBB0G-BBhBYBDYBtBqCBGjCjCBLBhCBBCPPBNNB0mHBqBfBiDyDB+vIDBCGBCBBCiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBn7F0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BeBHFBmI9BBzEsBBLGBRiKiKBcBTrBBlPbBlHdBDwGwGBdBCCBCBBCGBDEBKBBhHGBCDBCBBCOBCkGB8BjCBI1lB1lBBCBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIB', false)),
250
+ LC: () => new UnicodeRangeTable(decodeRanges('hCZBHZB7BLLBVBCeBCiGBCDBFvGBDZBhGDBDBBECBCHHCCBCCCBSBCyCBCqEBJlFBClBBKoBB44ClBBCGGDqBBDCBhV1CBDFBjkCKBGqBBDCBhCrBBgCMBChBBmD1IBDFBDlBBDFBDHBCGCBdBD0BBCGBCEEBBBCGBEDBDFBFMBGCBCGBmIFFDJBCEEBDBHGCBCBCFBFDDBCBGEBF1B1BB8zC8zCB6DBDmDBHDBEBBNlBBCGGzoetBBTbBnEtCBCWBEDBCsCBZBBE2Z2ZBpBBGIBIvCBh6TGBNEBqgBZBHZBmlBvCBhDjBBFjBB1DKBCOBCGBCBBCKBCOBCGBCBBk2ByBBOyBB+CVBLVB74C-BBhrV-BBhBYBDYBtpZ0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDYBCYBCeBCYBCeBCYBCeBCYBCeBCYBCHB15BJBCTBHFB2uCjCB', false)),
251
+ Ll: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBC2BCBQCBuBCDECBBBDCCDEEBFFDEEBBBDDDCCCDCCBCCDEECDDBDDBBBHGDCOCBSCBDDCEEC4BCBFBDDDBCCFICBjCBDZBiGCCEEEBBBTccBhBBCBBECBCWCBDBCGDB0B0BBuBBCgBCK0BCDMCBgDCxBoBBo6CqBBDCB5XFBjkCIBC2D2DBqBBgCMBChBBnD0ECBHBCgDCBHBJFBLHBJHBJFBLHBJHBJNBDHBJHBJHBJEBCBBHEEBBBCBBJDBDBBJHBLCBCBBzIEEBEEcKFDBBJDBF2B2Bs1CvBBCEEBGCFCCBCCBEBGiDCBIICFFNlBBCGG0oesBCUaCoEMCBBBC+BCBGBCCCDICFCCDCCBBBCSCGGGCMCFCCDOCbEE2ZqBBGIBIvCBh6TGBNEBqhBZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfB8BYBnqZZBbGBCRBbZBbDBCCCBFBCKBbZBbZBbZBbZBbZBbZBbZBbZBbbBdYBCFBbYBCFBbYBCFBbYBCFBbYBCFBC15B15BBIBCTBHFB4vChBB', false)),
252
+ Lm: () => new UnicodeRangeTable(decodeRanges('wVRBFLBPEBICCmEGG-OnHnHlFBBuIBBFgBgBKEEhFoFoF1mBgEgE2R72B72BsDkTkTxOFBvF+BBOjBjBBjBByVOORMBg-CBByHgGgG2OsBsBBDBGiDiDB+C+CBBB34bjnBjnBBEBvIzDzDdBB6DIBxCYYpDDBEBB2OXXqEtDtDWBBoDDBKngVngVuBBBh-BFBCpBBCIB0sBhBhB2K04D04DnrTDB9PCBpBBBnRMBhCBBCPPB9-P9-PBCBCGBCBByhM9BBqGGBud0Q0QsSAB', false)),
253
+ Lo: () => new UnicodeRangeTable(decodeRanges('qFQQhIFFBCBxGBB7ZaBFDBuBfBCJBkBBBCiDBCZZBLLBBBDRRCdBe4CBMZZBfBWVBrBYBIKBGXBCGBRoBB8B1BBETTIJBROBFHBDBBDVBCGBCEEBCBERROBBCCBPBBLJJBEBFBBDVBCGBCBBCBBCBBgBDBCUUBBBRIBCCBCVBCGBCBBCEBETTQBBYMMBGBDBBDVBCGBCBBCEBEffBCCBBBQSSCFBECBCDBEBBCCCBEEBEEBBBELBX1B1BBGBCCBCWBCPBEbbBBBCBBDBBfFFBGBCCBCWBCJBCEBEffBBBCBBQBBSIBCCBCoBBDRRGCBJCBZFBGRBEXBCIBCDDBFB7BvBBCBBNFB8BBBCCCBDBCXBCCCBIBCBBKDDBDBYDBhBgCgCBGBCjBBcEB0DqBBVRRBEBFDBEEEBIIBBBFMBNyDyDBnKBCDBDGBCCCBCBDoBBCDBDgBBCDBDGBCCCBCBDOBC4BBCDBDiCBmBPByDrTBDQBCZBGqCBHHBIRBOSBPRBPMBCCBQzBBpBkCkCBhBBC0BBIEBDhBBCGGBkCBLeByBdBDEBMrBBFZB3BWBK0BBxFuBBSHB3BdBOBBLrBBbjBBqBCBLdByDDBCFBCBBE7hB7hBBCB4-C3BBZWBKGBCGBCGBCGBCGBCGBCGBCGBoR2B2BF1CBJCCB4CBFGGBpBBC9CBSfBxBPBhQ-tGBhC0wUBC2jBBkCnBBJrIBFPBLBBjCyByBBkCBqFoDoDEGBCCBCDBCWBezBBPxBB-BFBECCBMMBaBLWBacBIuBBuBEBDIBLEBCoBBYCBCHBVPBCFBEEEBwBBCEEBDDBDBDCCZBBEKBIPPBEBDFBDFBKGBCGByEiBBej9KBNWBFwBBloItLBDpDBkCCCBIBCMBCEBCCCBCCBCCBqDBiBqLBT-BBD1BBpBLB1DEBCmEBqDJBCsBBDeBEFBDFBDFBDCBkBLBCZBCSBCBBCOBDNBjB6DBmMcBEwBBwBfBOTBCHBHlBBLdBDjBBFHBhEtCBjDnBBJzBB9CzBBN2JBKVBLHB5EFBDCCBqBBCBBEDDBVBLWBKeBiCSBCBBLVBLZBHZBnB3BBHBBhCQQBCBCCBCcBrBcBEcBkBHBCbBc1BBLVBLSBORBvDoCB4FjBBnBDBCxJxJBoBBHBBRCBCBB5BcBLJJBUBrBRBvBUBcWBN0BB6BBBDOOBrBBhBYBbjBBeDDJiBBENNBuBBPDBWCCkBRBCYBUBBgCGBCCCBCBCOBCJBIuBBnBHBDBBDVBCGBCBBCEBETTNEBfJBCDDClBBCaaCtBtBBzBBTDBVCBfvBBVBBC5F5FBtBBqBDBlBvBBV8B8BBpBBOoCoCBZBmBGB6FrBB0GHBDDDBGBCBBCXBQCC-CHBDmBBRCCdLLBmBBIWWMtBBUTTBnCBoGgBBgBIBCkBBSyByBBcBxDGBCBBClBBWaaBEBCBBCfBPYYBnBBCBBlISBQCCBLBChBB9DwCwCB4cBnHjGBtyCgDBQvhBBSFBa68DBGmSB61GdBj3B4RBIeBSuCBSdBTvBB0BUBGSB0NnBB2MqCBGwFwFB0mHBqBfBiDyDBuwIiJBQeeBBBDPPBCBJrMBloCqDBGMBEIBIJBxzI2P2PBrBBiBiKiKBcBTrBBlPaBmHdBDwGwGBdBCCBCBBCGBDEBKiHiHBFBCDBCBBCOBCkGB8pBDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQBlqE-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIB', false)),
229
254
  Lt: () => new UnicodeRangeTable(decodeRanges('lOGDnB2sH2sHBGBJHBJHBNQQwBAB', false)),
230
- Lu: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiB2BCDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIJDCMCDQCDDDCCBC4BCIBBCBBDCCBCBCGCiJCCEJJHCCBBBCCCBCCBPBCIBkBDDBBBEWCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBpCDBNDBNDBNEBMDBnIFFECBDCBDEEBDBHGCBCBDDBLBBG+B+B9zCvBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBEEGGCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBhtZZBbZBbZBbCCBGDBDDBCBCHBbZBbBBCDBDHBCGBcBBCDBCEBCEEBFBcZBbZBbZBbZBbZBbZBfYBiBYBiBYBiBYBiBYBiB2pE2pEBgBB', false)),
231
- M: () => new UnicodeRangeTable(decodeRanges('gYvDB0IGBoIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCgBB3BCBCRBCGBLBBeCB5BCCBFBDBBDCBKLLBbbDCB5BCCBDBFBBDCBEffBEEMCB5BCCBGBCCBCCBVBBXFBCCB5BCCBFBDBBDCBICBLBBf8B8BBDBECBCDBKpBpBBDB4BCCBFBCCBCDBIBBMBBeCB5BCCBFBCCBCDBIBBMBBQNNBCB4BBBCGBCCBCDBKLLBeeBBBnCFFBEBCCCBGBTBB+BDDBFBNHBjDDDBHBMGBqCBBcECFBByBTBCBBGKBCjBBKlDlDBSBYDBFCBCCBDGBEDBOLBCLLBCBgWCBzdDBdCBeBBfBBhCfBKuBuBBBBC2D2DBjBjB3DLBFLB8GEB6BJBCcBDxBxBBdByBEBwBQBnBIBNCBfMB5BNBxBTB5ECBCUBFHHDCBnG-BBxWgBB--CCBuEhDhDBeBrRFBqDBB1udDBCJBhBBBxCBBxIEEFYYBDBF0C0CBzBzBBQBbRBOnBnBBGBaMBtBDBwBNBlBkCkCBMBNJJBuBuBBBBzBCCBBBDBBGBBCqBqBBDBGBBtHHBCBBx5TiXiXBOBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBwCDBnCKByBDB7DCB2BOBqBDDBLLBCBuBKBI+B+BBBBlBNBRBBtBNNBBBxBNBJDBCBB9CLBHDD+ELBWDB4BBBCGBDBBDCBKLLBDDBFBEEBkCIBCDDCDBCEBCPPBzCzCBQBYyCyCBSBsHGBDIBcBBzCQBrDMBmDOBhIOB2HFBCBBDDBCCCBuEuEBFBDGBEddBIBpBGBCDBJKKBJBvBPB2MHBCHBzCVBCNB7DFBECCBCCBFBCjCjCBDBCBBCEB8KDBKBBCxBxBBFBEEBYmnFmnFHOBpmLRBhuCEB8BGB5gBCCB1BBIDByCMMBslTslTBizEizEBsBBDWB-QEBEFBJHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBBhXGBuDGB29lYvHB', false)),
232
- Mc: () => new UnicodeRangeTable(decodeRanges('joC4B4BDCBJDBCBBzBBB7BCBHBBDBBLsBsB7BCBjC7B7BBBBJCCB2B2BB7B7BCHHBDDBLLnDBBCBBECBCCBLqBqBBBB+BDB+BBB7BCCBDBDBBCBBKBBdPPB7B7BBBBGCBCCBLrBrBBsCsCBBBHHBTBBrKBBgCsFsFBFFHDDBaaBLLBBBDGBWBBDFBDLLBBB5zBffiEIIBGBCBB7KDBDCBFBBCFBhHBB7BCCKCCBJJBEByExBxBGCCBDBCBB+BffFBBD9B9BDCBCEEBxBxBBGBJBBsFWW35EBB0-dBBD5C5CBzBzBBOBvEBBwBxBxBBFFBDDBBBvDBBDBBZuBuBCuDuDDBBGuHuHBCCBCCBCC0gZCCgEuBuBBBBFBB0DZZB8B8BxBCBKBBO+C+CBBBEBBCrFrFBBBgBBB7BBBCDBDBBDCBKLLB1C1CBBBIDDCDBCBBCmDmDBBBJBBErDrDBBBHCCBCBDuHuHBBBHDBDyDyDBBBJBBCuDuDCBBHoDoDCBBFmImIBBBK4H4HBEBCBBFDDCvEvEBBBJDBF1C1CeBB-B4M4MPrDrDIDD2GEBFBBC-K-KBNNxBBBJBBCpvQpvQBBBlxD2BBpDBB0rYBBHFB', false)),
255
+ Lu: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiB2BCDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIJDCMCDQCDDDCCBC4BCIBBCBBDCCBCBCGCiJCCEJJHCCBBBCCCBCCBPBCIBkBDDBBBEWCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBpCDBNDBNDBNEBMDBnIFFECBDCBDEEBDBHGCBCBDDBLBBG+B+B9zCvBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBQCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBhCYBoqZZBbZBbZBbCCBGDBDDBCBCHBbZBbBBCDBDHBCGBcBBCDBCEBCEEBFBcZBbZBbZBbZBbZBbZBfYBiBYBiBYBiBYBiBYBiB2pE2pEBgBB', false)),
256
+ M: () => new UnicodeRangeTable(decodeRanges('gYvDB0IGBoIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCgBB3BCBCRBCGBLBBeCB5BCCBFBDBBDCBKLLBbbDCB5BCCBDBFBBDCBEffBEEMCB5BCCBGBCCBCCBVBBXFBCCB5BCCBFBDBBDCBICBLBBf8B8BBDBECBCDBKpBpBBDB4BCCBFBCCBCDBIBBMBBeCB5BCCBFBCCBCDBIBBMBBQNNBCB4BBBCGBCCBCDBKLLBeeBBBnCFFBEBCCCBGBTBB+BDDBFBNHBjDDDBHBMGBqCBBcECFBByBTBCBBGKBCjBBKlDlDBSBYDBFCBCCBDGBEDBOLBCLLBCBgWCBzdDBdCBeBBfBBhCfBKuBuBBBBC2D2DBjBjB3DLBFLB8GEB6BJBCcBDxBxBBsBBDLBVEBwBQBnBIBNCBfMB5BNBxBTB5ECBCUBFHHDCBnG-BBxWgBB--CCBuEhDhDBeBrRFBqDBB1udDBCJBhBBBxCBBxIEEFYYBDBF0C0CBzBzBBQBbRBOnBnBBGBaMBtBDBwBNBlBkCkCBMBNJJBuBuBBBBzBCCBBBDBBGBBCqBqBBDBGBBtHHBCBBx5TiXiXBOBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBuCFBnCKByBDB7DCB2BOBqBDDBLLBCBuBKBI+B+BBBBlBNBRBBtBNNBBBxBNBJDBCBB9CLBHDD+ELBWDB4BBBCGBDBBDCBKLLBDDBFBEEBkCIBCDDCDBCEBCPPBzCzCBQBYyCyCBSBsHGBDIBcBBzCQBrDMBmDOBhIOB2HFBCBBDDBCCCBuEuEBFBDGBEddBIBpBGBCDBJKKBJBvBPBnGHBoGHBCHBzCVBCNB7DFBECCBCCBFBCjCjCBDBCBBCEB8KDBKBBCxBxBBFBEEBYmnFmnFHOBpmLRBhuCEB8BGB5gBCCB1BBIDByCMMBslTslTBizEizEBsBBDWB-QEBEFBJHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBB0HDDIBBG7O7OBFBuDGB29lYvHB', false)),
257
+ Mc: () => new UnicodeRangeTable(decodeRanges('joC4B4BDCBJDBCBBzBBB7BCBHBBDBBLsBsB7BCBjC7B7BBBBJCCB2B2BB7B7BCHHBDDBLLnDBBCBBECBCCBLqBqBBBB+BDB+BBB7BCCBDBDBBCBBKBBdPPB7B7BBBBGCBCCBLrBrBBsCsCBBBHHBTBBrKBBgCsFsFBFFHDDBaaBLLBBBDGBWBBDFBDLLBBB5zBffiEIIBGBCBB7KDBDCBFBBCFBhHBB7BCCKCCBJJBEByExBxBGCCBDBCBB+BffFBBD9B9BDCBCEEBxBxBBGBJBBsFWW35EBB0-dBBD5C5CBzBzBBOBvEBBwBxBxBBFFBDDBBBvDBBDBBZuBuBCuDuDDBBGuHuHBCCBCCBCC0gZCCgEuBuBBBBFBB0DZZB8B8BxBCBKBBO+C+CBBBEBBCrFrFBBBgBBB7BBBCDBDBBDCBKLLB1C1CBBBIDDCDBCBBCmDmDBBBJBBErDrDBBBHCCBCBDuHuHBBBHDBDyDyDBBBJBBCuDuDCBBHoDoDCBBFmImIBBBK4H4HBEBCBBFDDCvEvEBBBJDBF1C1CeBB-BqGqGECCoGPPrDIID2G2GBDBFBBC-K-KBNNxBBBJBBCpvQpvQBBBlxD2BBpDBB0rYBBHFB', false)),
233
258
  Me: () => new UnicodeRangeTable(decodeRanges('okBBB1xF-wB-wBBCBCCBsshBCB', false)),
234
- Mn: () => new UnicodeRangeTable(decodeRanges('gYvDB0IEBqIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCfB4BCCFHBFEEBFBLBBe7B7BFDBJVVBbbDBB6BFFBFFBDDBBBEffBEEMBB6BFFBDBCBBFVVBXXBEBC7B7BDCCBCBJIIBMMBff+BNNzBEE4BCCBBBGCBCDBIBBMBBe7B7BDHHGBBVBBdBB6BBBFDBJVVBeepCIIBBBC7C7CDGBNHBjDDDBHBMGBqCBBcEC4BNBCEBCBBGKBCjBBKnDnDBCBCFBCBBDBBaBBFCBRDBODDBHHQgWgWBBBzdCBeBBfBBfBBhCBBCGBJDDBJBKuBuBBBBC2D2DBjBjB3DCBFBBKHHBBB8GBBD7B7BCGBCCCDHBHJBDxBxBBMBCPByBDBxBCCBDBCGGpBIBNBBhBDBDBBCCB5BCCBEECCB7BHBDBB5ECBCMBCGBFHHEBBnG-BBxWMBFEEBKB--CCBuEhDhDBeBrRDBsDBB1udFFBIBhBBBxCBBxIEEFaaBGG4EBBbRBOnBnBBGBaKBvBCBxBDDBCBDBBoBkCkCBEBDBBDBBNJJwB0B0BCCBDBBGBBCrBrBBJJvHDDFx5Tx5TiXPBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBwCDBnCKByBDB8D3B3BBNBqBDDBLLBBByBDBDBBI+B+BBBBlBEBCHB-BNNB1B1BBHBLDBDgDgDBBBDCCBHHD+E+EEHBWBB6BBBEmBmBBFBEEBnCFBOECPBB2CHBDCBCYY1CFBCFFBCCBvHvHBCBHBBCBBcBB2CHBDCCBrDrDCDDBEBCmDmDCDDBCBCEBkIIBCBBhIBBCFFxEDBDBBFhBhBBIBpBFBDDBJKKBEBDCBvBMBCBB3MGBCFBCzCzCBUBDGBCBBCBB7DFBECCBCCBFBCpCpCBEEC8K8KBMMB1B1BBDBGCCYmnFmnFHOBpmLLBECBhuCEB8BGB5gBgCgCBCByC5lT5lTBizEizEBsBBDWBhRCBSHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBBhXGBuDGB29lYvHB', false)),
235
- N: () => new UnicodeRangeTable(decodeRanges('wBJB5DBBGDDBBBitBJBnEJBnGJB9MJB3DJBFFBtDJB3DJB3DJBDFBvDMB0DJBJGBoDJBpDGBISBuDJBhDJB3DJBnCTBtIJBnCJBwWTBybCBwHJBHJBXJBtJJBhEKBmFJBHJB3FJB3CJBnEJBHJB3gBEEBEBHJBnGyBBDEB3W7BBvCVB3TdBqrBqYqYaIBPCB4KDBrEJBfHBCOBhBJBoBOBh7cJB9FJBhKFB7EJBnBJBnGJBXJB3CJB3MJB34UJBuPsBBN4BBSBB2KaBlBDBeJJnEEBrGJBvdHBaGBoBIBsCEBXFBhFBBDPBDtBBhCIB1BBBfCBsCEBpDHBZHBqBGBrKFBxBJBHJB3IeB-EJBrBDBxDGBnEdBhEJB9BJBxEJBITB8HJB3KJB3DJB3LJBnDJBHTBtCLBlNSB+CJB3UJB3CcBkHJBnCJBnNJBnDUBshBuDBimPJBnpCJB3CJBnEJBCGBvQJBnIWB6yXJBnuBTBNTBtDYB2iBxBBhqCJBnNJB3PJB4HJBtWIBhEJB4Y6BBCCBCDBtCsBBCOBjeMBk3CJB', false)),
236
- Nd: () => new UnicodeRangeTable(decodeRanges('wBJnxBJnEJnGJ9MJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJhDJ3DJnCJ3IJnCJn6BJnBJtJJhEJnFJHJ3FJ3CJnEJHJnuiBJnVJnBJnGJXJ3CJ3MJ34UJnsBJnkCJHJ9YJhEJ9BJxEJ3IJ3KJ3DJ3LJnDJHTtCJnNJnDJ3UJ3CJ3HJnCJnNJ3uQJnpCJ3CJnEJ3QJ37XJ12CxBhqCJnNJ3PJ4HJ2aJ30EJ', true)),
237
- Nl: () => new UnicodeRangeTable(decodeRanges('u3FCBwzCiBBDDB-zDaaBHBPCBs1dJBxyW0BBtOJJnEEBrhIuDB', false)),
259
+ Mn: () => new UnicodeRangeTable(decodeRanges('gYvDB0IEBqIsBBCCCBCCBCCpCKBxBUBRmDmDBFBDFBDBBCDBkBffBZB8CKB7BIBKZZBCBCIBCCBCEBsBCB8BIBrBXBCfB4BCCFHBFEEBFBLBBe7B7BFDBJVVBbbDBB6BFFBFFBDDBBBEffBEEMBB6BFFBDBCBBFVVBXXBEBC7B7BDCCBCBJIIBMMBff+BNNzBEE4BCCBBBGCBCDBIBBMBBe7B7BDHHGBBVBBdBB6BBBFDBJVVBeepCIIBBBC7C7CDGBNHBjDDDBHBMGBqCBBcEC4BNBCEBCBBGKBCjBBKnDnDBCBCFBCBBDBBaBBFCBRDBODDBHHQgWgWBBBzdCBeBBfBBfBBhCBBCGBJDDBJBKuBuBBBBC2D2DBjBjB3DCBFBBKHHBBB8GBBD7B7BCGBCCCDHBHJBDxBxBBMBCeBDLBVDBxBCCBDBCGGpBIBNBBhBDBDBBCCB5BCCBEECCB7BHBDBB5ECBCMBCGBFHHEBBnG-BBxWMBFEEBKB--CCBuEhDhDBeBrRDBsDBB1udFFBIBhBBBxCBBxIEEFaaBGG4EBBbRBOnBnBBGBaKBvBCBxBDDBCBDBBoBkCkCBEBDBBDBBNJJwB0B0BCCBDBBGBBCrBrBBJJvHDDFx5Tx5TiXPBRPBuejHjH2EEBn0BCBCBBGDBpBCBFmFmFB+R+RBCBiCEB+JBBuCFBnCKByBDB8D3B3BBNBqBDDBLLBBByBDBDBBI+B+BBBBlBEBCHB-BNNB1B1BBHBLDBDgDgDBBBDCCBHHD+E+EEHBWBB6BBBEmBmBBFBEEBnCFBOECPBB2CHBDCBCYY1CFBCFFBCCBvHvHBCBHBBCBBcBB2CHBDCCBrDrDCDDBEBCmDmDCDDBCBCEBkIIBCBBhIBBCFFxEDBDBBFhBhBBIBpBFBDDBJKKBEBDCBvBMBCBBnGCCBBBCqGqGBFBCFBCzCzCBUBDGBCBBCBB7DFBECCBCCBFBCpCpCBEEC8K8KBMMB1B1BBDBGCCYmnFmnFHOBpmLLBECBhuCEB8BGB5gBgCgCBCByC5lT5lTBizEizEBsBBDWBhRCBSHBDGBfDB1ECB89B2BBFxBBJPPXEBCOBxqBGBCQBDGBCBBCEBlDhFhFBFB4L+B+BBCB9PDB-HBB0HDDIBBG7O7OBFBuDGB29lYvHB', false)),
260
+ N: () => new UnicodeRangeTable(decodeRanges('wBJB5DBBGDDBBBitBJBnEJBnGJB9MJB3DJBFFBtDJB3DJB3DJBDFBvDMB0DJBJGBoDJBpDGBISBuDJBhDJB3DJBnCTBtIJBnCJBwWTBybCBwHJBHJBXJBtJJBhEKBmFJBHJB3FJB3CJBnEJBHJB3gBEEBEBHJBnGyBBDEB3W7BBvCVB3TdBqrBqYqYaIBPCB4KDBrEJBfHBCOBhBJBoBOBh7cJB9FJBhKFB7EJBnBJBnGJBXJB3CJB3MJB34UJBuPsBBN4BBSBB2KaBlBDBeJJnEEBrGJBvdHBaGBoBIBsCEBXFBhFBBDPBDtBBhCIB1BBBfCBsCEBpDHBZHBqBGBrKFBxBJBHJB3IeB-EJBrBDBxDGBnEdBhEJB9BJBxEJBITB8HJB3KJB3DJB3LJBnDJBHTBtCLBlNSB+CJB3UJB3CcBkHJBnCJB3BJBnLJBnDUBshBuDBimPJBnpCJB3CJBnEJBCGBvQJBnIWB+KCB6nXJBnuBTBNTBtDYB2iBxBBhqCJBnNJB3PJB4HJBtWIBhEJB4Y6BBCCBCDBtCsBBCOBjeMBk3CJB', false)),
261
+ Nd: () => new UnicodeRangeTable(decodeRanges('wBJnxBJnEJnGJ9MJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJ3DJhDJ3DJnCJ3IJnCJn6BJnBJtJJhEJnFJHJ3FJ3CJnEJHJnuiBJnVJnBJnGJXJ3CJ3MJ34UJnsBJnkCJHJ9YJhEJ9BJxEJ3IJ3KJ3DJ3LJnDJHTtCJnNJnDJ3UJ3CJ3HJnCJ3BJnLJ3uQJnpCJ3CJnEJ3QJ37XJ12CxBhqCJnNJ3PJ4HJ2aJ30EJ', true)),
262
+ Nl: () => new UnicodeRangeTable(decodeRanges('u3FCBwzCiBBDDB-zDaaBHBPCBs1dJBxyW0BBtOJJnEEBrhIuDBm8SCB', false)),
238
263
  No: () => new UnicodeRangeTable(decodeRanges('yFBBGDDBBB2pCFB5LFB5DCBmEGB6GGBSIByNJB2hBTB0jBJBhP20B20BEFBHJBnGPBqB3W3WB6BBvCVB3TdBqrB1kB1kBBCBrEJBfHBCOBhBJBoBOBxrdFBymWsBBiCDBSBB2KaBlBDB1pBHBaGBoBIBsCEBXFBhFBBDPBDtBBhCIB1BBBfCBsCEBpDHBZHBqBGBrKFBhLeB-EJBrBDBxDGBnETB8LTBmqBBBvNIBobSB0aUBn8SGB-YWBqhZTBNTBtDYBvqFIBid6BBCCBCDBtCsBBCOBjeMB', false)),
239
- P: () => new UnicodeRangeTable(decodeRanges('hBCBCFBCDBLBBEBBbCBCccCkBkBGEELBBEEE-VJJzOFBqBBB0BCCDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCmBmBBCBoCrCrCBDBFBBwDFBsFlTlTBHB4EuTuTtBBBvCCBoCBB+ECBCCBmBKB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBM9Z9ZBWBJTBCMBCLBfBBPBB6TDBeBB+hBNBwCBBgBJB0MVBgCDBhBBB8XDBCBBxDwEwEBtBBCfBDLBkNCBFJBDLBRNNjD7C7CjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HzqUzqUBxGxGBIBXiBBCNBCFFCBB2ECBCFBCDBLBBEBBbCBCccCCCBFB7MCB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDByO-J-JoFEBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
264
+ P: () => new UnicodeRangeTable(decodeRanges('hBCBCFBCDBLBBEBBbCBCccCkBkBGEELBBEEE-VJJzOFBqBBB0BCCDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCmBmBBCBoCrCrCBDBFBBwDFBsFlTlTBHB4EuTuTtBBBvCCBoCBB+ECBCCBmBKB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBM9Z9ZBWBJTBCMBCLBfBBPBB6TDBeBB+hBNBwCBBgBJB0MVBgCDBhBBB8XDBCBBxDwEwEBtBBCfBDLBkNCBFJBDLBRNNjD7C7CjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HzqUzqUBxGxGBIBXiBBCNBCFFCBB2ECBCFBCDBLBBEBBbCBCccCCCBFB7MCB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDByO-J-JjBlElEBDBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
240
265
  Pc: () => new UnicodeRangeTable(decodeRanges('-Cg-Hg-HBUU-u3BBBZCBwHAB', false)),
241
266
  Pd: () => new UnicodeRangeTable(decodeRanges('tB9qB9qB0BiyDiyDmgBqgCqgCBEBiwDDDgBBBFdd-NUUwDxszBxszBBmBmBLqFqFhzD-J-J', false)),
242
267
  Pe: () => new UnicodeRangeTable(decodeRanges('pB0B0BgB+1D+1DC-6B-6BqtC4B4BQ7T7TCff-hBMCxChBhBCGC1MUChCCCiBmhBmhBCECtBGCtNICEGCDBB-ozB6G6GeOCESSCCCrF0B0BgBGD', false)),
243
268
  Pf: () => new UnicodeRangeTable(decodeRanges('7F+6H+6HEddpuDCCFDDQEE', false)),
244
269
  Pi: () => new UnicodeRangeTable(decodeRanges('rFt7Ht7HDBBDaapuDCCFDDQEE', false)),
245
- Po: () => new UnicodeRangeTable(decodeRanges('hBCBCCBDECBLLBEEBcclCGGPBBI-V-VJzOzOBEBqB3B3BDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCxDxDrCEBFBBwDFBsFlTlTBHBmY9D9DBBBoCBB+ECBCCBmBFBCDB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBMjajaBJJBGBJIBDDBDCBEKBCCCBIB7kDDBCBBxDwEwEBFFBBBDDDBHBCBBCDDBLLBDBCJBDDBCCCBLBDCBtNCB6B+F+FjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HlxUlxUBFBDXXVBBDDBECBCDBICBHCCB2E2EBBBCCBDECBLLBEEBcclBDDB7M7MBBB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDB5dEBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
270
+ Po: () => new UnicodeRangeTable(decodeRanges('hBCBCCBDECBLLBEEBcclCGGPBBI-V-VJzOzOBEBqB3B3BDDDtBBBVBBCBBOCCBBBrCDBnDsBsBBMBqHCB3BOBgBmImIBLLtE5D5D6DnMnMNwLwL7CLLBpFpFBNBCxDxDrCEBFBBwDFBsFlTlTBHBmY9D9DBBBoCBB+ECBCCBmBFBCDB6JBB5GBBhEGBCFBhFBBLGBdCB9DDB8BEB-BBBhCHBMjajaBJJBGBJIBDDBDCBEKBCCCBIB7kDDBCBBxDwEwEBFFBBBDDDBHBCBBCDDBLLBDBCJBDDBCCCBLBDCBtNCB6B+F+FjgdBBuICBkDLL0DFB9LDB3CBBpBCBCyByBBwBwBiDMBRBB9DDB-DBBRBB6HlxUlxUBFBDXXVBBDDBECBCDBICBHCCB2E2EBBBCCBDECBLLBEEBcclBDDB7M7MBBB9UxBxB-MoXoXoGgBgBxIIBnBxDxDBFBjCGB6CDB0ZlElEBDBtBDB+FGBuDBBCDB-DDBxBBBwCDBFOOCCB5CFBsDrJrJBCCBzDzDBDBLBBCpDpD7HWBqDCBdMBtCjEjEBBB9HpIpIBBB8E9C9CBGB0CCBCEB+CJB4GgDgDBDBrBBBmUBBrCMBwFxjBxjBBDB97CBB8zOBBmEiCiCBDBJpRpRBBBoJDBoK9lT9lTovHEB07C-a-aBAB', false)),
246
271
  Ps: () => new UnicodeRangeTable(decodeRanges('oBzBzBgB-1D-1DC-6B-6B-rCEEnB4B4BQ7T7TCff-hBMCxChBhBCGC1MUChCCCiBmhBmhBCECaTTCECtNICEGCDipzBipzB4GeeCMCESSCCCrFzBzBgBEEDAB', false)),
247
- S: () => new UnicodeRangeTable(decodeRanges('kBHHRCBgBCCcCCkBEBCBBDCCBCBDEEfgBgBrODBNNBGGBCCCBPB2DPPBxDxDsErIrIBBB3DCBDDDBvGvGLUUB4H4HIBBpEqLqLBHHB2H2H-DjEjEBGBlEwGwGqBmGmGiGCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WuLuLlL+E+EBgBBiLJBKIBhiBCCBBBMCBOCBOCBOBBmCOOoBCBOCBUgBBgCBBCDBCBBLCCBBBGFBCECFMMBFFBDBGDBC7B7BBFFB2LBFcBD+HBXKByCtCBXnTBtBwBBDeBLyMBX+BBFfBD1LBDfBCoDBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBB8CBB0HBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BB6RWBKBBoDBB+EDBLDB+RCBiHPPB+9T+9TpEQB+LPBgEtBtBBCBjDCCBBBD7E7EHRRBBBgBCCcCCiEGBCGBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwSmWmWBwtCwtC2kCcBr6SDBG3qU3qUk7DvHBRzNB9EzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBrbaagBaagBaagBaagBaa9B-PB4BDBzBHBCNBCBBp2BwNwNttCEE+DiOiOBvIvIBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E3eBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBC7CB', false)),
248
- Sc: () => new UnicodeRangeTable(decodeRanges('kB+D+DBCBqnB8D8DzPBBzPBBI2H2HoImSmS8sClmClmCBfB47hBkuVkuVtD7E7E8GBBEBB3-HDB-4wBxtCxtC', false)),
272
+ S: () => new UnicodeRangeTable(decodeRanges('kBHHRCBgBCCcCCkBEBCBBDCCBCBDEEfgBgBrODBNNBGGBCCCBPB2DPPBxDxDsErIrIBBB3DCBDDDBvGvGLUUB4H4HIBBpEqLqLBHHB2H2H-DjEjEBGBlEwGwGqBmGmGiGCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WuLuLlL+E+EBgBBiLJBKIBhiBCCBBBMCBOCBOCBOBBmCOOoBCBOCBUhBB-BBBCDBCBBLCCBBBGFBCECFMMBFFBDBGDBC7B7BBFFB2LBFcBD+HBXKByCtCBXnTBtBwBBDeBLyMBX+BBFfBD1LBDpEBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBB8CBB0HBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BB6RWBKBBoDBB+EDBLDB+RCBiHPPB+9T+9TpEgBBuLPBhCBB3BHBtBDBjDCCBBBD7E7EHRRBBBgBCCcCCiEGBCGBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwSmWmWBiKiKBGBnjC2kC2kCBbBr6SDBG3qU3qUk7DvHBLCBEzNBHWBQQBgDzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBrbaagBaagBaagBaagBaa9B-PB4BDBzBHBCNBCBBp2BwNwNttCEE+DiOiOBvIvIBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E4eBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBBPIBoB3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBC7CBLAB', false)),
273
+ Sc: () => new UnicodeRangeTable(decodeRanges('kB+D+DBCBqnB8D8DzPBBzPBBI2H2HoImSmS8sClmClmCBgBB37hBkuVkuVtD7E7E8GBBEBB3-HDB-4wBxtCxtC', false)),
249
274
  Sk: () => new UnicodeRangeTable(decodeRanges('+CCCoCHHFEEqQDBNNBGGBCCCBPB2DPPBjoBjoB15FCCBBBMCBOCBOCBOBB9kEBBkzdWBKBBoDBBxePPBniUniUBPB8bCCjF4g9B4g9BBDB', false)),
250
- Sm: () => new UnicodeRangeTable(decodeRanges('rBRRBBB+BCCuBFFmBgBgB-XwQwQBBB8xGOOoBCBOCBsEoBoBBDBHlClCBDBGBBFGDIgBgBBDDCgBgBBqIBhBBB7CffBXBpBFB2OKK3BHBwDxKxKBDBDeBLPBhIiEBX+BBFfBDhIBxBUBDFB9+zB5Z5ZCCBlFRRBBB+BCCkEHHBCBitDBBypyBaagBaagBaagBaagBaat5FBB', false)),
251
- So: () => new UnicodeRangeTable(decodeRanges('mFDDFCCyerIrIBgEgEBvGvGLUUB4H4HkQ2L2LjEFBClElEwGqBqBoMCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WzWzW+EhBBiLJBKIBksBBBCDBCBBLCCBHHBEBCECFMMBPPCBBC7B7BBKKBDBDDBCBBCBBCGBCeBDBBCCCBdBtIHBFTBDGBDwCBCdBanBBHnCBXKByCtCBX2FBCIBC1BBJuDBC3HBtBrBBhC-HBhQvBBWBBHmBBDfBCoDBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBBxKBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BBibDBLBBC+R+RBBBn2UPBgEuBuBBBBlPEEFBBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwS3jD3jD2kCHBFQBr6SDBG3qU3qUk7DvHBRzNB9EzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBqlB-PB4BDBzBHBCNBCBBp2B96C96CiEyWyWBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E6HBG3WBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBC7CB', false)),
275
+ Sm: () => new UnicodeRangeTable(decodeRanges('rBRRBBB+BCCuBFFmBgBgB-XwQwQBBB8xGOOoBCBOCBsEoBoBBDBHlClCBDBGBBFGDIgBgBBDDCgBgBBqIBhBBB7CffBXBpBFB2OKK3BHBwDxKxKBDBDeBLPBhIiEBX+BBFfBDhIBxBUBDFB9+zB5Z5ZCCBlFRRBBB+BCCkEHHBCBitDBBhrwBx+Bx+BagBgBagBgBagBgBagBgBat5Ft5FB-uC-uCBHB', false)),
276
+ So: () => new UnicodeRangeTable(decodeRanges('mFDDFCCyerIrIBgEgEBvGvGLUUB4H4HkQ2L2LjEFBClElEwGqBqBoMCBQCCBBBDFBVECmEHBCFBCBBGDBmGBBxXJB0WzWzW+EhBBiLJBKIBksBBBCDBCBBLCCBHHBEBCECFMMBPPCBBC7B7BBKKBDBDDBCBBCBBCGBCeBDBBCCCBdBtIHBFTBDGBDwCBCdBanBBHnCBXKByCtCBX2FBCIBC1BBJuDBC3HBtBrBBhC-HBhQvBBWBBHmBBDpEBmHFBmLBBvBZBC4CBN1GBbPBFOOBNNWBBHBBxKBBFJBhBlBBKRRBdBMdBJQQBeBLmBBQ-JBhuG-BBx0V2BBibDBLBBC+R+RBBBqqUPBuLPBhCBB3BHBuBCBlPEEFBBOBB6JIB6BQBDCBCMBEwBwBBrBB7zBBBwSpgBpgBBGBnjC2kC2kCBGBFQBr6SDBG3qU3qUk7DvHBLCBEzNBHWBQPBhDzDB9B1HBLmBBD7BBGCBXBBIdBF8BBWhCBE7F7FB1CBqlB-PB4BDBzBHBCNBCBBp2B96C96CiEyWyWBqBBFjDBNOBDOBCOBCkBBYgFB5BcBOrBBFIBIBBPFB7E6HBG4WBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-B3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBC7CBLAB', false)),
252
277
  Z: () => new UnicodeRangeTable(decodeRanges('gBgEgEgvFgsCgsCBJBeBBGwBwBh9DAB', false)),
253
278
  Zl: () => new UnicodeRangeTable(decodeRanges('ohIA', true)),
254
279
  Zp: () => new UnicodeRangeTable(decodeRanges('phIA', true)),
@@ -261,7 +286,7 @@ class UnicodeTables {
261
286
  Adlam: () => new UnicodeRangeTable(decodeRanges('go6DrCFJFB', true)),
262
287
  Ahom: () => new UnicodeRangeTable(decodeRanges('g4lCaDOFW', true)),
263
288
  Anatolian_Hieroglyphs: () => new UnicodeRangeTable(decodeRanges('ggxCmS', true)),
264
- Arabic: () => new UnicodeRangeTable(decodeRanges('gwBEBCFBCNBCCBCfBCJBMZBCrDBChBBxCvBBxHeBCBBGqCBCcBxy8ByDBRqLBDvCBD1BBIhBhBBOBxDEBCmEBk7DeBkCCB4BDBh43BDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBB', false)),
289
+ Arabic: () => new UnicodeRangeTable(decodeRanges('gwBEBCFBCNBCCBCfBCJBMZBCrDBChBBxCvBBxHhBBGqCBCcBxy8BtPBDvEBhBPBxDEBCmEBk7DeBkCFBJIBiBFBh43BDBCaBCBBCDDCJBCDBCCCHFFCECBBBCBBCDDCICBCCDDBCGBCDBCDBCCCBIBCQBGCBCEBCQB1BBB', false)),
265
290
  Armenian: () => new UnicodeRangeTable(decodeRanges('xpBlBDxBDCks9BE', true)),
266
291
  Avestan: () => new UnicodeRangeTable(decodeRanges('g4iC1BEG', true)),
267
292
  Balinese: () => new UnicodeRangeTable(decodeRanges('g4GsCCxB', true)),
@@ -269,6 +294,7 @@ class UnicodeTables {
269
294
  Bassa_Vah: () => new UnicodeRangeTable(decodeRanges('w26CdDF', true)),
270
295
  Batak: () => new UnicodeRangeTable(decodeRanges('g+GzBJD', true)),
271
296
  Bengali: () => new UnicodeRangeTable(decodeRanges('gsCDBCHBDBBDVBCGBCEEBCBDIBDBBDDBJFFBCCBDBDYB', false)),
297
+ Beria_Erfe: () => new UnicodeRangeTable(decodeRanges('g17CYDY', true)),
272
298
  Bhaiksuki: () => new UnicodeRangeTable(decodeRanges('ggnCICsBCNLc', true)),
273
299
  Bopomofo: () => new UnicodeRangeTable(decodeRanges('qXB6wLqBxDf', true)),
274
300
  Brahmi: () => new UnicodeRangeTable(decodeRanges('ggkCtCFjBKA', true)),
@@ -282,7 +308,7 @@ class UnicodeTables {
282
308
  Cham: () => new UnicodeRangeTable(decodeRanges('gwqB2BKNDJDD', true)),
283
309
  Cherokee: () => new UnicodeRangeTable(decodeRanges('g9E1CDFz7lBvC', true)),
284
310
  Chorasmian: () => new UnicodeRangeTable(decodeRanges('w9jCb', true)),
285
- Common: () => new UnicodeRangeTable(decodeRanges('AgCBbFBbuBBCOBCEBYgBgBiOmBBGEBDTB1DKKHCC+THHPEEhB9E9ElQiEiEB6mB6mB2MDBjJwvBwvBBBBoCBBsGBBCumBumBOIIBCBCFBCCBDmYmYBKBD2CBCKBEKBCOBSgBBgClBBCCBDFBCaBCQBqBCBF5UBXKBW-cBhIzTBDfBCoDBhQ9CBzMUBCCCBXBQHBFDB8CBBE7C7CB0E0EBOBhBlBBKxBxBB+BBgBwCBwB5C5CBmFBhuG-BBhoWhBBnDCBmFJB1HhFhFsMPPBzuUzuUBxGxGBIBXiBBCSBCDB0ECCBeBbFBbKBLuBuBBhChCBFBCGBLEBjICBFsBBEIBxCMB0BsBBlHaBltuBDB96D5HBHzNB9EzDB9B1HBLmBBD9BBEQBJBBIdBF8BB2GTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBDxBByjFjCBtC8BBjWrBBFjDBNOBDOBCOBCkBBLtFB5BZBCBBOrBBFIBIBBPFB7E3eBFQBEMBE2DBF+CBHLBFQQBKBF3BBJJBHnBBJdBDLBFBB-BzKBNNBDMBEJBG3BBIOBDKBHIBIyEBClDBoghYffB+CB', false)),
311
+ Common: () => new UnicodeRangeTable(decodeRanges('AgCBbFBbuBBCOBCEBYgBgBiOmBBGEBDTB1DKKHCC+THHPEEhB9E9ElQiEiEB6mB6mB2MDBjJwvBwvBBBBoCBBsGBBCumBumBOIIBCBCFBCCBDmYmYBKBD2CBCKBEKBCOBShBB-BlBBCCBDFBCaBCQBqBCBF5UBXKBW-cBhIzTBDpEBhQ9CBzMUBCCCBXBQHBFDB8CBBE7C7CB0E0EBOBhBlBBKxBxBB+BBgBwCBwB5C5CBmFBhuG-BBhoWhBBnDCBmFJB1HhFhFsMPPBzuUzuUBxGxGBIBXiBBCSBCDB0ECCBeBbFBbKBLuBuBBhChCBFBCGBLEBjICBFsBBEIBxCMB0BsBBlHaBltuBDB96D8HBEzNBHWBQQBgDzDB9B1HBLmBBD9BBEQBJBBIdBF8BB2GTBNTBN2CBKYBoE0CBCmCBCBBDDDBDDBCBCLBCCCBFBCgCBCDBDHBCGBCbBCDBCEBCEEBFBCzKBDjJBDxBByjFjCBtC8BBjWrBBFjDBNOBDOBCOBCkBBLtFB5BZBCBBOrBBFIBIBBPFB7E4eBEQBEMBE5GBHLBFQQBKBF3BBJJBHnBBJdBDLBFBBPIBoB3KBJNBDMBEKBE4BBCFFBOBDLBFJBIyEBCmDBnghYffB+CB', false)),
286
312
  Coptic: () => new UnicodeRangeTable(decodeRanges('ifNxkKzDGG', true)),
287
313
  Cuneiform: () => new UnicodeRangeTable(decodeRanges('ggoC5cnDuDCEMjG', true)),
288
314
  Cypriot: () => new UnicodeRangeTable(decodeRanges('ggiCFBDCCBqBBCBBEDD', false)),
@@ -307,7 +333,7 @@ class UnicodeTables {
307
333
  Gunjala_Gondi: () => new UnicodeRangeTable(decodeRanges('grnCFCBCkBCBCFIJ', true)),
308
334
  Gurmukhi: () => new UnicodeRangeTable(decodeRanges('hwCCBCFBFBBDVBCGBCBBCBBCBBDCCBDBFBBDCBEIIBCBCIIBPB', false)),
309
335
  Gurung_Khema: () => new UnicodeRangeTable(decodeRanges('go4C5B', true)),
310
- Han: () => new UnicodeRangeTable(decodeRanges('g0LZBC4CBN1GBwBCCaIBPDBle-tGBhC-vUBhoWtLBDpDBpodBBNBBvgkB-2pBBhB5hEBH9GBDh0FBPwpHBQtTBjtC9QBjvBq6EBG-iEB', false)),
336
+ Han: () => new UnicodeRangeTable(decodeRanges('g0LZBC4CBN1GBwBCCaIBPDBle-tGBhC-vUBhoWtLBDpDBpodBBNGBqgkB-2pBBhB9oEBDt0FBDwpHBQtTBjtC9QBjvBq6EBGppIB', false)),
311
337
  Hangul: () => new UnicodeRangeTable(decodeRanges('goE-HvxHBiI9CyDeiCei3dckUj9KNWFwBl9JeEFDFDFDC', true)),
312
338
  Hanifi_Rohingya: () => new UnicodeRangeTable(decodeRanges('gojCnBJJ', true)),
313
339
  Hanunoo: () => new UnicodeRangeTable(decodeRanges('g5FU', true)),
@@ -315,12 +341,12 @@ class UnicodeTables {
315
341
  Hebrew: () => new UnicodeRangeTable(decodeRanges('xsB2BBJaBFFBpp9BZBCEBCCCBCCBCCBIB', false)),
316
342
  Hiragana: () => new UnicodeRangeTable(decodeRanges('hiM1CBHCBi7-C+IBTeeBBBulQAB', false)),
317
343
  Imperial_Aramaic: () => new UnicodeRangeTable(decodeRanges('giiCVCI', true)),
318
- Inherited: () => new UnicodeRangeTable(decodeRanges('gYvDB2IBBlOKBbhXhXBCB8qEeBiQCBCMBCGBFHHEBBnG-BBtQBBjGgBB65DDBsDBBmrzBPBRNBwejHjH7iEl+uBl+uBBsBBDWBhRCBSHBDGBfDBz6rYvHB', false)),
344
+ Inherited: () => new UnicodeRangeTable(decodeRanges('gYvDB2IBBlOKBbhXhXBCB8qEtBBDLBlPCBCMBCGBFHHEBBnG-BBtQBBjGgBB65DDBsDBBmrzBPBRNBwejHjH7iEl+uBl+uBBsBBDWBhRCBSHBDGBfDBz6rYvHB', false)),
319
345
  Inscriptional_Pahlavi: () => new UnicodeRangeTable(decodeRanges('g7iCSGH', true)),
320
346
  Inscriptional_Parthian: () => new UnicodeRangeTable(decodeRanges('g6iCVDH', true)),
321
347
  Javanese: () => new UnicodeRangeTable(decodeRanges('gsqBtCDJFB', true)),
322
348
  Kaithi: () => new UnicodeRangeTable(decodeRanges('gkkCiCLA', true)),
323
- Kannada: () => new UnicodeRangeTable(decodeRanges('gkDMCCCWCJCEDICCCDIBHBCDDJCC', true)),
349
+ Kannada: () => new UnicodeRangeTable(decodeRanges('gkDMCCCWCJCEDICCCDIBGCCDDJCC', true)),
324
350
  Katakana: () => new UnicodeRangeTable(decodeRanges('hlM5CBDCBxHPBxGuBBC3CBvgzBJBCsBBzisBDBCGBCBBCgJgJBBBzBPPBCB', false)),
325
351
  Kawi: () => new UnicodeRangeTable(decodeRanges('g4nCQCoBEc', true)),
326
352
  Kayah_Li: () => new UnicodeRangeTable(decodeRanges('goqBtBCA', true)),
@@ -331,7 +357,7 @@ class UnicodeTables {
331
357
  Khudawadi: () => new UnicodeRangeTable(decodeRanges('w1kC6BGJ', true)),
332
358
  Kirat_Rai: () => new UnicodeRangeTable(decodeRanges('gq7C5B', true)),
333
359
  Lao: () => new UnicodeRangeTable(decodeRanges('h0DBBCCCBDBCXBCCCBVBDEBCCCBFBCJBDDB', false)),
334
- Latin: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBQQGWBCeBCgOBoBEB8wGlBBHwBBGDBGMBClCBiC-HByLOORMBuEBBHccSoBB42CfBj1elDBEiCBDBBCCCBGBWNBxZqBBCIBCDB38TGB7gBZBHZBmhCFBCpBBCIBm61BeBHFB', false)),
360
+ Latin: () => new UnicodeRangeTable(decodeRanges('hCZBHZBwBQQGWBCeBCgOBoBEB8wGlBBHwBBGDBGMBClCBiC-HByLOORMBuEBBHccSoBB42CfBj1elDBExCBVOBxZqBBCIBCDB38TGB7gBZBHZBmhCFBCpBBCIBm61BeBHFB', false)),
335
361
  Lepcha: () => new UnicodeRangeTable(decodeRanges('ggH3BEOEC', true)),
336
362
  Limbu: () => new UnicodeRangeTable(decodeRanges('goGeBCLBFLBFEEBKB', false)),
337
363
  Linear_A: () => new UnicodeRangeTable(decodeRanges('gwhC2JKVLH', true)),
@@ -390,9 +416,10 @@ class UnicodeTables {
390
416
  Runic: () => new UnicodeRangeTable(decodeRanges('g1FqCEK', true)),
391
417
  Samaritan: () => new UnicodeRangeTable(decodeRanges('ggCtBDO', true)),
392
418
  Saurashtra: () => new UnicodeRangeTable(decodeRanges('gkqBlCJL', true)),
393
- Sharada: () => new UnicodeRangeTable(decodeRanges('gskC-C', true)),
419
+ Sharada: () => new UnicodeRangeTable(decodeRanges('gskC-ChsCH', true)),
394
420
  Shavian: () => new UnicodeRangeTable(decodeRanges('wihCvB', true)),
395
421
  Siddham: () => new UnicodeRangeTable(decodeRanges('gslC1BDlB', true)),
422
+ Sidetic: () => new UnicodeRangeTable(decodeRanges('gqiCZ', true)),
396
423
  SignWriting: () => new UnicodeRangeTable(decodeRanges('gg2DrUQECO', true)),
397
424
  Sinhala: () => new UnicodeRangeTable(decodeRanges('hsDCBCRBEXBCIBCDDBFBEFFBEBCCCBGBHJBDCBt-gCTB', false)),
398
425
  Sogdian: () => new UnicodeRangeTable(decodeRanges('w5jCpB', true)),
@@ -407,21 +434,23 @@ class UnicodeTables {
407
434
  Tai_Le: () => new UnicodeRangeTable(decodeRanges('wqGdDE', true)),
408
435
  Tai_Tham: () => new UnicodeRangeTable(decodeRanges('gxG+BCcDKHJHN', true)),
409
436
  Tai_Viet: () => new UnicodeRangeTable(decodeRanges('g0qBiCZE', true)),
437
+ Tai_Yo: () => new UnicodeRangeTable(decodeRanges('g25DeCVJB', true)),
410
438
  Takri: () => new UnicodeRangeTable(decodeRanges('g0lC5BHJ', true)),
411
439
  Tamil: () => new UnicodeRangeTable(decodeRanges('i8CBBCFBECBCDBEBBCCCBEEBEEBBBELBFEBECBCDBDHHPUBm+kCxBBOAB', false)),
412
440
  Tangsa: () => new UnicodeRangeTable(decodeRanges('wz6CuCCJ', true)),
413
- Tangut: () => new UnicodeRangeTable(decodeRanges('g-7CgBgBB2-FBJ-XBhQIB', false)),
414
- Telugu: () => new UnicodeRangeTable(decodeRanges('ggDMBCCBCWBCPBDIBCCBCDBIBBCCBDDDBCBDJBIIB', false)),
441
+ Tangut: () => new UnicodeRangeTable(decodeRanges('g-7CgBgBB+3GBhQeBiDyDB', false)),
442
+ Telugu: () => new UnicodeRangeTable(decodeRanges('ggDMCCCWCPDICCCDIBCCCBDDDJII', true)),
415
443
  Thaana: () => new UnicodeRangeTable(decodeRanges('g8BxB', true)),
416
444
  Thai: () => new UnicodeRangeTable(decodeRanges('hwD5BGb', true)),
417
445
  Tibetan: () => new UnicodeRangeTable(decodeRanges('g4DnCCjBFmBCjBCOCGFB', true)),
418
446
  Tifinagh: () => new UnicodeRangeTable(decodeRanges('wpL3BIBPA', true)),
419
447
  Tirhuta: () => new UnicodeRangeTable(decodeRanges('gklCnCJJ', true)),
420
448
  Todhri: () => new UnicodeRangeTable(decodeRanges('guhCzB', true)),
449
+ Tolong_Siki: () => new UnicodeRangeTable(decodeRanges('wtnCrBFJ', true)),
421
450
  Toto: () => new UnicodeRangeTable(decodeRanges('w04De', true)),
422
451
  Tulu_Tigalari: () => new UnicodeRangeTable(decodeRanges('g8kCJBCDDClBBCJBCDDCDBCJBCBBJBB', false)),
423
452
  Ugaritic: () => new UnicodeRangeTable(decodeRanges('g8gCdCA', true)),
424
- 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)),
453
+ 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)),
425
454
  Vai: () => new UnicodeRangeTable(decodeRanges('gopBrJ', true)),
426
455
  Vithkuqi: () => new UnicodeRangeTable(decodeRanges('wrhCKCOCGCBCKCOCGCB', true)),
427
456
  Wancho: () => new UnicodeRangeTable(decodeRanges('g24D5BGA', true)),
@@ -431,22 +460,18 @@ class UnicodeTables {
431
460
  Zanabazar_Square: () => new UnicodeRangeTable(decodeRanges('gwmCnC', true))
432
461
  });
433
462
  static FOLD_CATEGORIES = new LazyMap({
434
- C: () => new UnicodeRangeTable(decodeRanges('z+pBCC', false)),
435
- Cn: () => new UnicodeRangeTable(decodeRanges('z+pBCC', false)),
436
- L: () => new UnicodeRangeTable(decodeRanges('latkpBtkpBCAB', false)),
437
- LC: () => new UnicodeRangeTable(decodeRanges('latkpBtkpBCAB', false)),
438
- Ll: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiBuBCEECDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIBBCBBCBBCOCDQCDBBCCCBBBC4BCIBBCBBDCCBCBCGC3HrBrBCEEJHHCCBCCCBCCBPBCIBkBJJCUCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBZHBJHBJHBJEBMEBMDBNEBMEBqJEEBHHxC9zC9zCBuBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBEECKCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBh1ehBB', false)),
463
+ L: () => new UnicodeRangeTable(decodeRanges('laA', true)),
464
+ LC: () => new UnicodeRangeTable(decodeRanges('laA', true)),
465
+ Ll: () => new UnicodeRangeTable(decodeRanges('hCZBmDWBCGBiBuBCEECDOCDuBCBECEBBCCCBCCBBBDDBCBBCCBEBBCBBCECBCCDCCBCCBBBCCCBEEIBBCBBCBBCOCDQCDBBCCCBBBC4BCIBBCBBDCCBCBCGC3HrBrBCEEJHHCCBCCCBCCBPBCIBkBJJCUCGDDCBBDyBBxBgBCK2BCBMCD+CCDlBBq6ClBBCGGzW1CB0kCHHBpBBDCBhK0ECKgDCKHBJFBLHBJHBJFBMGCJHBZHBJHBJHBJEBMEBMDBNEBMEBqJEEBHHxC9zC9zCBuBBxBCCBBBDGCBCBCDDJCBCgDCJCCFuqeuqeCqBCUaCoEMCE8BCLECBICFCCDCCEUCBDBCEBCOCBCBCCCBQCZs5Vs5VBYBmmBnBBpEjBB9EKBCOBCGBCBBr3ByBB+EVB75CfBhsVfBhCYBoyehBB', false)),
439
466
  Lt: () => new UnicodeRangeTable(decodeRanges('kOCCBCCBCClBCCtsHHBJHBJHBMQQwBAB', false)),
440
- Lu: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBCuBCEECDOCDsBCDECBBBDCCDEEGDDECBDDDCCCDFFDEECDDECCGBBCBBCBBCOCBSCDBBCEECkBCEQCJDDBCCFICBEBCBBCCCBEEBCCBCBCEBDCCBDDIDDCBBEFBGLLBnFnFsBCCEEEBBBvBDBCdBCBBECBCWCBDBCGD1BvBBCgBCK0BCDMCBgDCyBlBBq6CqBBDCB5XFBjkCIBCvHvHERRzD0ECGGGC8CCBHBJFBLHBJHBJFBMGCJHBJNBzBBBNSSBPPBEEpL2B2Bs1CvBBCEEBGCHDDLiDCJCCFNNBkBBCGG0oesBCUaCoEMCE8BCLCCDICFFFCBBDSCMOCFCCDEEGECb9a9advCBi8UZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfBj1ehBB', false)),
467
+ Lu: () => new UnicodeRangeTable(decodeRanges('hDZB7BqBqBBWBCHBCuBCEECDOCDsBCDECBBBDCCDEEGDDECBDDDCCCDFFDEECDDECCGBBCBBCBBCOCBSCDBBCEECkBCEQCJDDBCCFICBEBCBBCCCBEEBCCBCBCEBDCCBDDIDDCBBEFBGLLBnFnFsBCCEEEBBBvBDBCdBCBBECBCWCBDBCGD1BvBBCgBCK0BCDMCBgDCyBlBBq6CqBBDCB5XFBjkCIBCvHvHERRzD0ECGGGC8CCBHBJFBLHBJHBJFBMGCJHBJNBzBBBNSSBPPBEEpL2B2Bs1CvBBCEEBGCHDDLiDCJCCFNNBkBBCGG0oesBCUaCoEMCE8BCLCCDICFFFCBBDSCMOCFCCDOCb9a9advCBi8UZBumBnBBpEjBB8EKBCOBCGBCBBk4ByBB+DVB75CfBhsVfB8BYBvyehBB', false)),
441
468
  M: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false)),
442
469
  Mn: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false))
443
470
  });
444
471
  static FOLD_SCRIPT = new LazyMap({
445
472
  Common: () => new UnicodeRangeTable(decodeRanges('8cgBgB', false)),
446
473
  Greek: () => new UnicodeRangeTable(decodeRanges('1FwUwU', false)),
447
- Inherited: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false)),
448
- Latin: () => new UnicodeRangeTable(decodeRanges('y+pBCC', false)),
449
- Unknown: () => new UnicodeRangeTable(decodeRanges('z+pBCC', false))
474
+ Inherited: () => new UnicodeRangeTable(decodeRanges('5cgBgBlgHAB', false))
450
475
  });
451
476
  }
452
477
 
@@ -575,11 +600,16 @@ class Unicode {
575
600
  // to compare it to |r2|.
576
601
  // -1 is interpreted as the end-of-file mark.
577
602
  static equalsIgnoreCase(r1, r2) {
578
- // Runes already match, or one of them is EOF
579
- if (r1 < 0 || r2 < 0 || r1 === r2) {
603
+ // Runes already match
604
+ if (r1 === r2) {
580
605
  return true;
581
606
  }
582
607
 
608
+ // Safely fail if either is EOF (and they didn't explicitly match above)
609
+ if (r1 < 0 || r2 < 0) {
610
+ return false;
611
+ }
612
+
583
613
  // Fast path for the common case where both runes are ASCII characters.
584
614
  // Coerces both runes to lowercase if applicable.
585
615
  if (r1 <= this.MAX_ASCII && r2 <= this.MAX_ASCII) {
@@ -832,7 +862,7 @@ class Utils {
832
862
  // Encoding[(Encoding['UTF_16'] = 0)] = 'UTF_16'
833
863
  // Encoding[(Encoding['UTF_8'] = 1)] = 'UTF_8'
834
864
  const createEnum = (values = [], initNum = 0) => {
835
- const enumObject = {};
865
+ const enumObject = Object.create(null);
836
866
  for (let i = 0; i < values.length; i++) {
837
867
  const val = values[i];
838
868
  const keyVal = initNum + i;
@@ -974,6 +1004,9 @@ class MachineInputBase {
974
1004
  hasString() {
975
1005
  return false;
976
1006
  }
1007
+ hasAnyString() {
1008
+ return false;
1009
+ }
977
1010
 
978
1011
  // Helper for the exact-literal fast-path execution router
979
1012
  prefixLength() {
@@ -999,6 +1032,13 @@ class MachineUTF8Input extends MachineInputBase {
999
1032
  return idx !== -1 && idx <= this.end - target.length;
1000
1033
  }
1001
1034
 
1035
+ // Executes a high-speed, single - pass search for multiple literal strings
1036
+ // simultaneously using an Aho-Corasick automaton.
1037
+ hasAnyString(prefilter, pos) {
1038
+ if (!prefilter.ac8) return false;
1039
+ return prefilter.ac8.searchUTF8(this.bytes, this.start + pos, this.end);
1040
+ }
1041
+
1002
1042
  // Returns the rune at the specified index; the units are
1003
1043
  // unspecified, but could be UTF-8 byte, UTF-16 char, or rune
1004
1044
  // indices. Returns the width (in the same units) of the rune in
@@ -1017,17 +1057,23 @@ class MachineUTF8Input extends MachineInputBase {
1017
1057
  return c << 3 | 1;
1018
1058
  } else if (c >= 0xc2 && c <= 0xdf && pos + 1 < this.end) {
1019
1059
  const c1 = this.bytes[pos + 1] & 0xff;
1060
+ if ((c1 & 0xc0) !== 0x80) return c << 3 | 1;
1020
1061
  const rune = (c & 0x1f) << 6 | c1 & 0x3f;
1021
1062
  return rune << 3 | 2;
1022
1063
  } else if (c >= 0xe0 && c <= 0xef && pos + 2 < this.end) {
1023
1064
  const c1 = this.bytes[pos + 1] & 0xff;
1065
+ if ((c1 & 0xc0) !== 0x80) return c << 3 | 1;
1024
1066
  const c2 = this.bytes[pos + 2] & 0xff;
1067
+ if ((c2 & 0xc0) !== 0x80) return c << 3 | 1;
1025
1068
  const rune = (c & 0x0f) << 12 | (c1 & 0x3f) << 6 | c2 & 0x3f;
1026
1069
  return rune << 3 | 3;
1027
1070
  } else if (c >= 0xf0 && c <= 0xf4 && pos + 3 < this.end) {
1028
1071
  const c1 = this.bytes[pos + 1] & 0xff;
1072
+ if ((c1 & 0xc0) !== 0x80) return c << 3 | 1;
1029
1073
  const c2 = this.bytes[pos + 2] & 0xff;
1074
+ if ((c2 & 0xc0) !== 0x80) return c << 3 | 1;
1030
1075
  const c3 = this.bytes[pos + 3] & 0xff;
1076
+ if ((c3 & 0xc0) !== 0x80) return c << 3 | 1;
1031
1077
  const rune = (c & 0x07) << 18 | (c1 & 0x3f) << 12 | (c2 & 0x3f) << 6 | c3 & 0x3f;
1032
1078
  return rune << 3 | 4;
1033
1079
  } else {
@@ -1106,6 +1152,13 @@ class MachineUTF16Input extends MachineInputBase {
1106
1152
  return idx !== -1 && idx <= this.end - prefilter.str.length;
1107
1153
  }
1108
1154
 
1155
+ // Executes a high-speed, single - pass search for multiple literal strings
1156
+ // simultaneously using an Aho-Corasick automaton.
1157
+ hasAnyString(prefilter, pos) {
1158
+ if (!prefilter.ac16) return false;
1159
+ return prefilter.ac16.searchUTF16(this.charSequence, this.start + pos, this.end);
1160
+ }
1161
+
1109
1162
  // Returns the rune at the specified index; the units are
1110
1163
  // unspecified, but could be UTF-8 byte, UTF-16 char, or rune
1111
1164
  // indices. Returns the width (in the same units) of the rune in
@@ -1551,7 +1604,15 @@ class Matcher {
1551
1604
  if (this.hasMatch) {
1552
1605
  start = this.groups[1];
1553
1606
  if (this.groups[0] === this.groups[1]) {
1554
- start++;
1607
+ // Safely calculate structural encoding width to avoid sequence corruption
1608
+ const machineInput = this.matcherInput.isUTF16Encoding() ? MachineInput.fromUTF16(this.matcherInput.asCharSequence(), 0, this.matcherInputLength) : MachineInput.fromUTF8(this.matcherInput.asBytes(), 0, this.matcherInputLength);
1609
+ const r = machineInput.step(start);
1610
+ if (r < 0) {
1611
+ // EOF
1612
+ start++; // Advance past length to force loop exit
1613
+ } else {
1614
+ start += r & 7; // Advance by safely decoded width
1615
+ }
1555
1616
  }
1556
1617
  }
1557
1618
  return this.genMatch(start, RE2Flags.UNANCHORED);
@@ -1565,14 +1626,16 @@ class Matcher {
1565
1626
  * @private
1566
1627
  */
1567
1628
  genMatch(startByte, anchor) {
1568
- const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, 1);
1629
+ const hasLookbehinds = this.patternInput.re2().prog.numLb > 0;
1630
+ const ngroup = hasLookbehinds ? 1 + this.patternGroupCount : 1;
1631
+ const res = this.patternInput.re2().matchMachineInput(this.matcherInput, startByte, this.matcherInputLength, anchor, ngroup);
1569
1632
  const ok = res[0];
1570
1633
  if (!ok) {
1571
1634
  return false;
1572
1635
  }
1573
1636
  this.groups = res[1];
1574
1637
  this.hasMatch = true;
1575
- this.hasGroups = false;
1638
+ this.hasGroups = hasLookbehinds || this.patternGroupCount === 0;
1576
1639
  this.anchorFlag = anchor;
1577
1640
  return true;
1578
1641
  }
@@ -1688,6 +1751,8 @@ class Matcher {
1688
1751
  const groupName = replacement.substring(i + 1, j);
1689
1752
  res += this.group(groupName);
1690
1753
  last = j + 1;
1754
+ i = j;
1755
+ continue;
1691
1756
  }
1692
1757
  }
1693
1758
  }
@@ -1767,6 +1832,7 @@ class Matcher {
1767
1832
  if (j === replacement.length || replacement.codePointAt(j) !== Codepoint.CODES.get('>')) {
1768
1833
  res += replacement.substring(i - 1, j + 1);
1769
1834
  last = j + 1;
1835
+ i = j;
1770
1836
  continue;
1771
1837
  }
1772
1838
  const groupName = replacement.substring(i + 1, j);
@@ -1776,6 +1842,8 @@ class Matcher {
1776
1842
  res += `$<${groupName}>`;
1777
1843
  }
1778
1844
  last = j + 1;
1845
+ i = j;
1846
+ continue;
1779
1847
  }
1780
1848
  }
1781
1849
  }
@@ -1859,6 +1927,8 @@ class Inst {
1859
1927
  static RUNE1 = 9;
1860
1928
  static RUNE_ANY = 10;
1861
1929
  static RUNE_ANY_NOT_NL = 11;
1930
+ static LB_WRITE = 12;
1931
+ static LB_CHECK = 13;
1862
1932
  static isRuneOp(op) {
1863
1933
  return Inst.RUNE <= op && op <= Inst.RUNE_ANY_NOT_NL;
1864
1934
  }
@@ -1898,6 +1968,8 @@ class Inst {
1898
1968
  return r === r0;
1899
1969
  }
1900
1970
  const len = this.runes.length;
1971
+ if (len === 0) return false;
1972
+
1901
1973
  // If the array is exactly 2, 4, 6, or 8 items, DO NOT fall through to binary search
1902
1974
  if (len === 2 || len === 4 || len === 6 || len === 8) {
1903
1975
  for (let j = 0; j < len; j += 2) {
@@ -1911,22 +1983,19 @@ class Inst {
1911
1983
  return false; // Stop here
1912
1984
  }
1913
1985
 
1914
- // Otherwise binary search.
1915
- let lo = 0;
1916
- let hi = this.runes.length / 2 | 0;
1917
- while (lo < hi) {
1918
- const m = lo + hi >> 1; // native cpu instruction for "lo + (((hi - lo) / 2) | 0)"
1919
- const c = this.runes[2 * m];
1920
- if (c <= r) {
1921
- if (r <= this.runes[2 * m + 1]) {
1922
- return true;
1923
- }
1924
- lo = m + 1;
1925
- } else {
1926
- hi = m;
1927
- }
1986
+ // Branchless Binary Search (Lower Bound)
1987
+ // Compiles to optimal conditional move (cmov) machine code, preventing
1988
+ // branch mispredictions on large, chaotic Unicode arrays
1989
+ let base = 0;
1990
+ let n = len >> 1;
1991
+ while (n > 1) {
1992
+ const half = n >> 1;
1993
+ base += this.runes[base + half << 1] <= r ? half : 0;
1994
+ n -= half;
1928
1995
  }
1929
- return false;
1996
+ base += this.runes[base << 1] <= r ? 1 : 0;
1997
+ const m = base - 1;
1998
+ return m >= 0 && r <= this.runes[m << 1 | 1];
1930
1999
  }
1931
2000
 
1932
2001
  // matchRunePos checks whether the instruction matches (and consumes) r.
@@ -1941,6 +2010,7 @@ class Inst {
1941
2010
  return r === r0 ? 0 : -1;
1942
2011
  }
1943
2012
  const len = this.runes.length;
2013
+ if (len === 0) return -1;
1944
2014
  if (len === 2 || len === 4 || len === 6 || len === 8) {
1945
2015
  for (let j = 0; j < len; j += 2) {
1946
2016
  if (r < this.runes[j]) return -1;
@@ -1948,19 +2018,18 @@ class Inst {
1948
2018
  }
1949
2019
  return -1;
1950
2020
  }
1951
- let lo = 0;
1952
- let hi = Math.floor(len / 2);
1953
- while (lo < hi) {
1954
- const m = lo + hi >> 1;
1955
- const c = this.runes[2 * m];
1956
- if (c <= r) {
1957
- if (r <= this.runes[2 * m + 1]) return m;
1958
- lo = m + 1;
1959
- } else {
1960
- hi = m;
1961
- }
2021
+
2022
+ // Branchless Binary Search (Lower Bound)
2023
+ let base = 0;
2024
+ let n = len >> 1;
2025
+ while (n > 1) {
2026
+ const half = n >> 1;
2027
+ base += this.runes[base + half << 1] <= r ? half : 0;
2028
+ n -= half;
1962
2029
  }
1963
- return -1;
2030
+ base += this.runes[base << 1] <= r ? 1 : 0;
2031
+ const m = base - 1;
2032
+ return m >= 0 && r <= this.runes[m << 1 | 1] ? m : -1;
1964
2033
  }
1965
2034
  /**
1966
2035
  *
@@ -1982,6 +2051,10 @@ class Inst {
1982
2051
  return 'fail';
1983
2052
  case Inst.NOP:
1984
2053
  return `nop -> ${this.out}`;
2054
+ case Inst.LB_WRITE:
2055
+ return `lbwrite ${this.lb} -> ${this.out}`;
2056
+ case Inst.LB_CHECK:
2057
+ return `lbcheck ${this.lb} -> ${this.out}, ${this.arg}`;
1985
2058
  case Inst.RUNE:
1986
2059
  if (this.runes === null) {
1987
2060
  return 'rune <null>';
@@ -2055,6 +2128,7 @@ class Queue {
2055
2128
  //
2056
2129
  // Called by RE2.doExecute.
2057
2130
  class Machine {
2131
+ static THREADS_CHUNK_SIZE = 128;
2058
2132
  static fromRE2(re2) {
2059
2133
  const m = new Machine();
2060
2134
  m.prog = re2.prog;
@@ -2081,21 +2155,29 @@ class Machine {
2081
2155
  } else {
2082
2156
  this.resetCap();
2083
2157
  }
2158
+
2159
+ // Initialize the Lookbehind tracking table
2160
+ if (this.prog.numLb > 0) {
2161
+ if (!this.lbTable || this.lbTable.length < this.prog.numLb + 1) {
2162
+ this.lbTable = new Int32Array(this.prog.numLb + 1);
2163
+ }
2164
+ this.lbTable.fill(-1);
2165
+ }
2084
2166
  }
2085
2167
 
2086
2168
  // Wipes existing typed array memory without reallocating
2087
2169
  resetCap() {
2088
2170
  for (let i = 0; i < this.poolSize; i++) {
2089
2171
  const t = this.pool[i];
2090
- t.cap.fill(0);
2172
+ t.cap.fill(-1);
2091
2173
  }
2092
2174
  }
2093
2175
  initNewCap(ncap) {
2094
2176
  for (let i = 0; i < this.poolSize; i++) {
2095
2177
  const t = this.pool[i];
2096
- t.cap = new Int32Array(ncap);
2178
+ t.cap = new Int32Array(ncap).fill(-1);
2097
2179
  }
2098
- this.matchcap = new Int32Array(ncap);
2180
+ this.matchcap = new Int32Array(ncap).fill(-1);
2099
2181
  }
2100
2182
  submatches() {
2101
2183
  if (this.ncap === 0) {
@@ -2108,14 +2190,21 @@ class Machine {
2108
2190
  // alloc() allocates a new thread with the given instruction.
2109
2191
  // It uses the free pool if possible.
2110
2192
  alloc(inst) {
2111
- let t;
2112
- if (this.poolSize > 0) {
2113
- this.poolSize--;
2114
- t = this.pool[this.poolSize];
2115
- } else {
2116
- t = new Thread();
2117
- t.cap = new Int32Array(this.matchcap.length);
2193
+ if (this.poolSize === 0) {
2194
+ const capLen = this.matchcap.length;
2195
+
2196
+ // Bulk allocate threads in a tight loop so the V8 engine
2197
+ // places them adjacently in the young generation heap
2198
+ for (let i = 0; i < Machine.THREADS_CHUNK_SIZE; i++) {
2199
+ const t = new Thread();
2200
+ t.cap = new Int32Array(capLen);
2201
+ this.pool[this.poolSize++] = t;
2202
+ }
2118
2203
  }
2204
+
2205
+ // Pop a thread from the top of the pool stack
2206
+ this.poolSize--;
2207
+ const t = this.pool[this.poolSize];
2119
2208
  t.inst = inst;
2120
2209
  return t;
2121
2210
  }
@@ -2168,10 +2257,16 @@ class Machine {
2168
2257
  if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) {
2169
2258
  break;
2170
2259
  }
2260
+ if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2261
+ break;
2262
+ }
2171
2263
  if (this.matched) {
2172
2264
  break;
2173
2265
  }
2174
- if (!(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
2266
+ // Disable Prefix Acceleration if the regex contains lookbehinds
2267
+ // Fast-forwarding the string pointer will skip over the positions where
2268
+ // the parallel lookbehind automata need to be spawned.
2269
+ if (this.prog.numLb === 0 && !(this.re2.prefix.length === 0) && rune1 !== this.re2.prefixRune && input.canCheckPrefix()) {
2175
2270
  const advance = input.index(this.re2, pos);
2176
2271
  if (advance < 0) {
2177
2272
  break;
@@ -2189,6 +2284,10 @@ class Machine {
2189
2284
  if (this.ncap > 0) {
2190
2285
  this.matchcap[0] = pos;
2191
2286
  }
2287
+ // Spawn Lookbehind threads BEFORE the main pattern
2288
+ for (let i = 0; i < this.prog.lbStarts.length; i++) {
2289
+ this.add(runq, this.prog.lbStarts[i], pos, this.matchcap, flag, null);
2290
+ }
2192
2291
  this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
2193
2292
  }
2194
2293
  const nextPos = pos + width;
@@ -2238,8 +2337,15 @@ class Machine {
2238
2337
  while (true) {
2239
2338
  if (runq.isEmpty()) {
2240
2339
  if ((startCond & Utils.EMPTY_BEGIN_TEXT) !== 0 && pos !== 0) break;
2340
+ if ((anchor === RE2Flags.ANCHOR_START || anchor === RE2Flags.ANCHOR_BOTH) && pos !== 0) {
2341
+ break;
2342
+ }
2241
2343
  }
2242
2344
  if (pos === 0 || anchor === RE2Flags.UNANCHORED) {
2345
+ // Spawn Lookbehind threads BEFORE the main pattern
2346
+ for (let i = 0; i < this.prog.lbStarts.length; i++) {
2347
+ this.add(runq, this.prog.lbStarts[i], pos, this.matchcap, flag, null);
2348
+ }
2243
2349
  this.add(runq, this.prog.start, pos, this.matchcap, flag, null);
2244
2350
  }
2245
2351
  const nextPos = pos + width;
@@ -2349,63 +2455,83 @@ class Machine {
2349
2455
  runq.clear();
2350
2456
  }
2351
2457
  add(q, pc, pos, cap, cond, t) {
2352
- if (pc === 0) {
2353
- return t;
2354
- }
2355
- if (q.contains(pc)) {
2356
- return t;
2357
- }
2358
- const d = q.add(pc);
2359
- const inst = this.prog.inst[pc];
2360
- switch (inst.op) {
2361
- case Inst.FAIL:
2362
- break;
2363
- case Inst.ALT:
2364
- case Inst.ALT_MATCH:
2365
- t = this.add(q, inst.out, pos, cap, cond, t);
2366
- t = this.add(q, inst.arg, pos, cap, cond, t);
2367
- break;
2368
- case Inst.EMPTY_WIDTH:
2369
- if ((inst.arg & ~cond) === 0) {
2370
- t = this.add(q, inst.out, pos, cap, cond, t);
2371
- }
2372
- break;
2373
- case Inst.NOP:
2374
- t = this.add(q, inst.out, pos, cap, cond, t);
2375
- break;
2376
- case Inst.CAPTURE:
2377
- if (inst.arg < this.ncap) {
2378
- const opos = cap[inst.arg];
2379
- cap[inst.arg] = pos;
2380
- this.add(q, inst.out, pos, cap, cond, null);
2381
- cap[inst.arg] = opos;
2382
- } else {
2458
+ while (true) {
2459
+ if (pc === 0) {
2460
+ return t;
2461
+ }
2462
+ if (q.contains(pc)) {
2463
+ return t;
2464
+ }
2465
+ const d = q.add(pc);
2466
+ const inst = this.prog.inst[pc];
2467
+ switch (inst.op) {
2468
+ case Inst.FAIL:
2469
+ return t;
2470
+ case Inst.ALT:
2471
+ case Inst.ALT_MATCH:
2383
2472
  t = this.add(q, inst.out, pos, cap, cond, t);
2384
- }
2385
- break;
2386
- case Inst.MATCH:
2387
- case Inst.RUNE:
2388
- case Inst.RUNE1:
2389
- case Inst.RUNE_ANY:
2390
- case Inst.RUNE_ANY_NOT_NL:
2391
- if (t === null) {
2392
- t = this.alloc(inst);
2393
- } else {
2394
- t.inst = inst;
2395
- }
2396
- if (this.ncap > 0 && t.cap !== cap) {
2397
- // Direct assignment utilizing Typed Array performance
2398
- for (let c = 0; c < this.ncap; c++) {
2399
- t.cap[c] = cap[c];
2473
+ pc = inst.arg; // Flattened tail recursion
2474
+ continue;
2475
+ case Inst.EMPTY_WIDTH:
2476
+ if ((inst.arg & ~cond) === 0) {
2477
+ pc = inst.out; // Flattened tail recursion
2478
+ continue;
2400
2479
  }
2401
- }
2402
- q.denseThreads[d] = t;
2403
- t = null;
2404
- break;
2405
- default:
2406
- throw new Error('unhandled');
2480
+ return t;
2481
+ case Inst.NOP:
2482
+ pc = inst.out; // Flattened tail recursion
2483
+ continue;
2484
+ case Inst.CAPTURE:
2485
+ if (inst.arg < this.ncap) {
2486
+ const opos = cap[inst.arg];
2487
+ cap[inst.arg] = pos;
2488
+ this.add(q, inst.out, pos, cap, cond, null);
2489
+ cap[inst.arg] = opos;
2490
+ return t;
2491
+ } else {
2492
+ pc = inst.out; // Flattened tail recursion
2493
+ continue;
2494
+ }
2495
+ case Inst.LB_WRITE:
2496
+ this.lbTable[Math.abs(inst.lb)] = pos;
2497
+ pc = inst.out;
2498
+ continue;
2499
+ case Inst.LB_CHECK:
2500
+ if (inst.lb > 0) {
2501
+ // Positive Lookbehind
2502
+ if (this.lbTable[inst.lb] === pos) {
2503
+ pc = inst.out; // Flattened tail recursion
2504
+ continue;
2505
+ }
2506
+ } else if (this.lbTable[-inst.lb] !== pos) {
2507
+ // Negative Lookbehind
2508
+ pc = inst.out; // Flattened tail recursion
2509
+ continue;
2510
+ }
2511
+ return t;
2512
+ case Inst.MATCH:
2513
+ case Inst.RUNE:
2514
+ case Inst.RUNE1:
2515
+ case Inst.RUNE_ANY:
2516
+ case Inst.RUNE_ANY_NOT_NL:
2517
+ if (t === null) {
2518
+ t = this.alloc(inst);
2519
+ } else {
2520
+ t.inst = inst;
2521
+ }
2522
+ if (this.ncap > 0 && t.cap !== cap) {
2523
+ // Direct assignment utilizing Typed Array performance
2524
+ for (let c = 0; c < this.ncap; c++) {
2525
+ t.cap[c] = cap[c];
2526
+ }
2527
+ }
2528
+ q.denseThreads[d] = t;
2529
+ t = null;
2530
+ return t;
2531
+ default:
2532
+ throw new Error('unhandled');
2533
+ }
2407
2534
  }
2408
- return t;
2409
2535
  }
2410
2536
  }
2411
2537
 
@@ -2433,8 +2559,15 @@ class DFAState {
2433
2559
  this.nfaStates = nfaStates; // Int32Array of Instruction PCs
2434
2560
  this.isMatch = isMatch; // Boolean
2435
2561
  this.matchIDs = matchIDs; // Array of integers indicating which Set patterns matched
2436
- this.nextAscii = new Array(Unicode.MAX_ASCII + 1).fill(null); // Flat array for blisteringly fast ASCII lookups
2437
- this.nextMap = new Map(); // Cache of Char -> DFAState
2562
+
2563
+ // Latin-1 (Unicode.MAX_LATIN1 + 1) flat arrays for blisteringly fast O(1) lookups
2564
+ // completely covering standard English, European languages, and 1-byte encodings.
2565
+ this.nextLatin1 = new Array(Unicode.MAX_LATIN1 + 1).fill(null); // Flat array for blisteringly fast ASCII lookups
2566
+ this.nextLatin1Anchored = new Array(Unicode.MAX_LATIN1 + 1).fill(null); // Flat array for blisteringly fast ASCII lookups
2567
+ // 2 arrays used as hash map for V8 optimization (N is small number, so O(n) faster than Map O(1))
2568
+ this.transKeys = [];
2569
+ this.transVals = [];
2570
+ this.lastSeen = 0; // Track when this state was last used for LRU eviction
2438
2571
  }
2439
2572
  }
2440
2573
  class DFA {
@@ -2447,6 +2580,7 @@ class DFA {
2447
2580
  this.stateLimit = 10000; // Prevent memory explosion (ReDoS protection)
2448
2581
  this.cacheClears = 0; // Track thrashing
2449
2582
  this.failed = false; // mark if DFA cannot work with provided prog
2583
+ this.clock = 0; // Global clock for LRU eviction
2450
2584
  }
2451
2585
 
2452
2586
  // Follows epsilon (empty) transitions to find all reachable states without consuming a char
@@ -2477,6 +2611,8 @@ class DFA {
2477
2611
  // Bailing out on complex empty-width assertions to keep DFA fast.
2478
2612
  // Engine will seamlessly fall back to the NFA.
2479
2613
  case Inst.EMPTY_WIDTH:
2614
+ case Inst.LB_WRITE:
2615
+ case Inst.LB_CHECK:
2480
2616
  return null;
2481
2617
  }
2482
2618
  }
@@ -2504,6 +2640,7 @@ class DFA {
2504
2640
  for (let i = 0; i < bucket.length; i++) {
2505
2641
  const state = bucket[i];
2506
2642
  if (arraysEqual(state.nfaStates, sortedPCs)) {
2643
+ state.lastSeen = ++this.clock;
2507
2644
  return state;
2508
2645
  }
2509
2646
  }
@@ -2516,40 +2653,99 @@ class DFA {
2516
2653
  if (this.failed) return null;
2517
2654
 
2518
2655
  // Safety: prevent memory exhaustion from state explosion
2519
- // We flush the cache and return null, which seamlessly routes execution to the NFA
2656
+ // We prune the cache to keep the newest 50%
2520
2657
  if (this.stateCount >= this.stateLimit) {
2521
- this.stateCache.clear();
2522
- this.stateCount = 0;
2523
- this.startState = null;
2524
2658
  this.cacheClears++;
2525
2659
 
2526
2660
  // If this regex causes continuous cache thrashing, permanently fall back to NFA
2527
2661
  // to avoid spending CPU cycles constantly rebuilding the DFA tree.
2528
2662
  if (this.cacheClears >= DFA.MAX_CACHE_CLEARS) {
2529
2663
  this.failed = true;
2664
+ this.stateCache.clear();
2665
+ this.stateCount = 0;
2666
+ this.startState = null;
2667
+ return null;
2668
+ }
2669
+ this.evictCache();
2670
+
2671
+ // After eviction, the bucket reference might be stale or empty.
2672
+ // We must re-fetch or re-create the bucket.
2673
+ bucket = this.stateCache.get(hash);
2674
+ if (!bucket) {
2675
+ bucket = [];
2676
+ this.stateCache.set(hash, bucket);
2530
2677
  }
2531
- return null;
2532
2678
  }
2533
2679
 
2534
2680
  // State not found, create it and add to bucket
2535
2681
  const state = new DFAState(sortedPCs, closureResult.isMatch, closureResult.matchIDs);
2682
+ state.lastSeen = ++this.clock;
2536
2683
  bucket.push(state);
2537
2684
  this.stateCount++;
2538
2685
  return state;
2539
2686
  }
2687
+ evictCache() {
2688
+ const allStates = [];
2689
+ for (const bucket of this.stateCache.values()) {
2690
+ for (let i = 0; i < bucket.length; i++) {
2691
+ allStates.push(bucket[i]);
2692
+ }
2693
+ }
2694
+
2695
+ // Sort ascending by lastSeen (oldest first)
2696
+ allStates.sort((a, b) => a.lastSeen - b.lastSeen);
2697
+
2698
+ // Keep the newest 50%
2699
+ const keepCount = Math.max(1, Math.floor(this.stateLimit / 2));
2700
+ const startIndex = allStates.length - keepCount;
2701
+ const survivorsArray = allStates.slice(startIndex);
2702
+ const survivors = new Set(survivorsArray);
2703
+ this.stateCache.clear();
2704
+ this.stateCount = 0;
2705
+ for (let i = 0; i < survivorsArray.length; i++) {
2706
+ const state = survivorsArray[i];
2707
+
2708
+ // Sever ties to all states to prevent memory leaks and dangling pointers
2709
+ state.nextLatin1.fill(null);
2710
+ state.nextLatin1Anchored.fill(null);
2711
+ // zero-allocation cleanup
2712
+ state.transKeys.length = 0;
2713
+ state.transVals.length = 0;
2714
+ const hash = hashPCs(state.nfaStates);
2715
+ let bucket = this.stateCache.get(hash);
2716
+ if (!bucket) {
2717
+ bucket = [];
2718
+ this.stateCache.set(hash, bucket);
2719
+ }
2720
+ bucket.push(state);
2721
+ this.stateCount++;
2722
+ }
2723
+
2724
+ // Start state must either be preserved or nullified so it gets re-created
2725
+ if (this.startState && !survivors.has(this.startState)) {
2726
+ this.startState = null;
2727
+ }
2728
+ }
2540
2729
 
2541
2730
  // Compute the next DFA state given a current state and a character
2542
2731
  step(state, charCode, anchor) {
2543
- // OPTIMIZATION: ASCII Fast-Path
2544
- if (anchor === RE2Flags.UNANCHORED && charCode <= Unicode.MAX_ASCII) {
2545
- const next = state.nextAscii[charCode];
2546
- if (next !== null) {
2547
- return next;
2732
+ // OPTIMIZATION: Latin-1 Array Fast-Path
2733
+ if (charCode <= Unicode.MAX_LATIN1) {
2734
+ if (anchor === RE2Flags.UNANCHORED) {
2735
+ const next = state.nextLatin1[charCode];
2736
+ if (next !== null) return next;
2737
+ } else {
2738
+ const next = state.nextLatin1Anchored[charCode];
2739
+ if (next !== null) return next;
2548
2740
  }
2549
2741
  } else {
2742
+ // Dense Array Linear Search fallback for Runes > 255
2550
2743
  const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
2551
- if (state.nextMap.has(key)) {
2552
- return state.nextMap.get(key);
2744
+ // get [key] -> nextState
2745
+ const keys = state.transKeys;
2746
+ const len = keys.length;
2747
+ for (let i = 0; i < len; i++) {
2748
+ if (keys[i] === key) return state.transVals[i];
2553
2749
  }
2554
2750
  }
2555
2751
  const nextPCs = [];
@@ -2566,11 +2762,17 @@ class DFA {
2566
2762
  const nextState = this.getState(nextPCs);
2567
2763
 
2568
2764
  // Cache the result
2569
- if (anchor === RE2Flags.UNANCHORED && charCode <= Unicode.MAX_ASCII) {
2570
- state.nextAscii[charCode] = nextState;
2765
+ if (charCode <= Unicode.MAX_LATIN1) {
2766
+ if (anchor === RE2Flags.UNANCHORED) {
2767
+ state.nextLatin1[charCode] = nextState;
2768
+ } else {
2769
+ state.nextLatin1Anchored[charCode] = nextState;
2770
+ }
2571
2771
  } else {
2572
2772
  const key = charCode + (anchor === RE2Flags.UNANCHORED ? 0 : Unicode.MAX_RUNE + 1);
2573
- state.nextMap.set(key, nextState);
2773
+ // store key -> nextState
2774
+ state.transKeys.push(key);
2775
+ state.transVals.push(nextState);
2574
2776
  }
2575
2777
  return nextState;
2576
2778
  }
@@ -2603,10 +2805,11 @@ class DFA {
2603
2805
  if (width === 0) {
2604
2806
  break;
2605
2807
  }
2606
- currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_ASCII && currentState.nextAscii[rune] || this.step(currentState, rune, anchor);
2808
+ currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_LATIN1 && currentState.nextLatin1[rune] || this.step(currentState, rune, anchor);
2607
2809
 
2608
2810
  // If we hit an unrecoverable DFA error or bailout, signal fallback
2609
2811
  if (currentState === null) return null;
2812
+ currentState.lastSeen = ++this.clock;
2610
2813
  if (currentState.isMatch) {
2611
2814
  if (anchor === RE2Flags.ANCHOR_BOTH) {
2612
2815
  if (i + width === endPos) return true;
@@ -2654,9 +2857,10 @@ class DFA {
2654
2857
  const rune = r >> 3;
2655
2858
  const width = r & 7;
2656
2859
  if (width === 0) break;
2657
- currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_ASCII && currentState.nextAscii[rune] || this.step(currentState, rune, anchor);
2860
+ currentState = anchor === RE2Flags.UNANCHORED && rune <= Unicode.MAX_LATIN1 && currentState.nextLatin1[rune] || this.step(currentState, rune, anchor);
2658
2861
  if (currentState === null) return null; // Bailout to NFA
2659
2862
 
2863
+ currentState.lastSeen = ++this.clock;
2660
2864
  i += width;
2661
2865
  checkMatch(currentState, i);
2662
2866
  if (currentState.nfaStates.length === 0) {
@@ -2694,7 +2898,7 @@ class BitState {
2694
2898
  // Bitwise shift (>>> 5) instead of Math.floor( / 32)
2695
2899
  const visitedSize = prog.numInst() * (end + 1) + VISITED_BITS - 1 >>> 5;
2696
2900
  if (this.visited.length < visitedSize) {
2697
- this.visited = new Uint32Array(Math.floor(MAX_BACKTRACK_VECTOR / VISITED_BITS));
2901
+ this.visited = new Uint32Array(visitedSize);
2698
2902
  } else {
2699
2903
  this.visited.fill(0, 0, visitedSize);
2700
2904
  }
@@ -2780,11 +2984,12 @@ class BitState {
2780
2984
  const outInst = re2.prog.getInst(inst.out);
2781
2985
  if (Inst.isRuneOp(outInst.op)) {
2782
2986
  this.push(re2, inst.arg, currentPos, false);
2783
- currentPc = inst.out;
2987
+ currentPc = inst.arg;
2988
+ currentPos = this.end;
2784
2989
  continue;
2785
2990
  }
2786
2991
  this.push(re2, inst.out, this.end, false);
2787
- currentPc = inst.arg;
2992
+ currentPc = inst.out;
2788
2993
  continue;
2789
2994
  }
2790
2995
  case Inst.RUNE:
@@ -2865,6 +3070,11 @@ class BitState {
2865
3070
  if (currentPos === this.end) return true;
2866
3071
  break;
2867
3072
  }
3073
+ case Inst.LB_WRITE:
3074
+ case Inst.LB_CHECK:
3075
+ {
3076
+ throw new RE2JSInternalException('Backtracker cannot evaluate Lookbehind instructions');
3077
+ }
2868
3078
  default:
2869
3079
  {
2870
3080
  throw new RE2JSInternalException('bad inst');
@@ -3222,6 +3432,8 @@ const cleanupOnePass = (p, original) => {
3222
3432
  class OnePass {
3223
3433
  static compile(prog) {
3224
3434
  if (prog.start === 0) return null;
3435
+ // OnePass cannot evaluate Lookbehinds
3436
+ if (prog.numLb > 0) return null;
3225
3437
  const startInst = prog.inst[prog.start];
3226
3438
  // onepass regexps must be strictly anchored
3227
3439
  if (startInst.op !== Inst.EMPTY_WIDTH || (startInst.arg & Utils.EMPTY_BEGIN_TEXT) === 0) {
@@ -3299,6 +3511,10 @@ class OnePass {
3299
3511
  switch (inst.op) {
3300
3512
  case Inst.MATCH:
3301
3513
  {
3514
+ // Verify ANCHOR_BOTH constraint before accepting the match
3515
+ if (anchor === RE2Flags.ANCHOR_BOTH && pos !== input.endPos()) {
3516
+ return null;
3517
+ }
3302
3518
  matched = true;
3303
3519
  if (matchcap.length > 0) {
3304
3520
  matchcap[0] = 0;
@@ -3401,6 +3617,10 @@ class Regexp {
3401
3617
  // Matches concatenation of subs[]
3402
3618
  'ALTERNATE',
3403
3619
  // Matches union of subs[]
3620
+ 'PLB',
3621
+ // Positive LookBehind
3622
+ 'NLB',
3623
+ // Negative LookBehind
3404
3624
  // Pseudo ops, used internally by Parser for parsing stack:
3405
3625
  'LEFT_PAREN', 'VERTICAL_BAR']);
3406
3626
  static isPseudoOp(op) {
@@ -3425,6 +3645,7 @@ class Regexp {
3425
3645
  regex.max = re.max;
3426
3646
  regex.name = re.name;
3427
3647
  regex.namedGroups = re.namedGroups;
3648
+ regex.lb = re.lb; // Track lookbehind index
3428
3649
  return regex;
3429
3650
  }
3430
3651
  constructor(op) {
@@ -3439,6 +3660,7 @@ class Regexp {
3439
3660
  this.cap = 0; // capturing index, for CAPTURE
3440
3661
  this.name = null; // capturing name, for CAPTURE
3441
3662
  this.namedGroups = Object.create(null); // map of group name -> capturing index
3663
+ this.lb = 0; // Lookbehind index tracking
3442
3664
  }
3443
3665
  reinit() {
3444
3666
  this.flags = 0;
@@ -3449,6 +3671,7 @@ class Regexp {
3449
3671
  this.max = 0;
3450
3672
  this.name = null;
3451
3673
  this.namedGroups = Object.create(null);
3674
+ this.lb = 0;
3452
3675
  }
3453
3676
  toString() {
3454
3677
  return this.appendTo();
@@ -3539,6 +3762,12 @@ class Regexp {
3539
3762
  case Regexp.Op.ANY_CHAR:
3540
3763
  out += '(?s:.)';
3541
3764
  break;
3765
+ case Regexp.Op.PLB:
3766
+ out += `(?<=${this.subs[0].appendTo()})`;
3767
+ break;
3768
+ case Regexp.Op.NLB:
3769
+ out += `(?<!${this.subs[0].appendTo()})`;
3770
+ break;
3542
3771
  case Regexp.Op.CAPTURE:
3543
3772
  if (this.name === null || this.name.length === 0) {
3544
3773
  out += '(';
@@ -3703,11 +3932,101 @@ class Regexp {
3703
3932
  }
3704
3933
  break;
3705
3934
  }
3935
+ case Regexp.Op.PLB:
3936
+ case Regexp.Op.NLB:
3937
+ {
3938
+ if (this.lb !== that.lb || !this.subs[0].equals(that.subs[0])) {
3939
+ return false;
3940
+ }
3941
+ break;
3942
+ }
3706
3943
  }
3707
3944
  return true;
3708
3945
  }
3709
3946
  }
3710
3947
 
3948
+ // High-speed, single-pass Aho-Corasick string matcher optimized for V8.
3949
+ // Builds a trie with failure links to search for multiple prefixes simultaneously.
3950
+ class AhoCorasick {
3951
+ constructor(wordArrays) {
3952
+ this.next = [Object.create(null)];
3953
+ this.fail = [0];
3954
+ this.match = [false];
3955
+
3956
+ // Build Trie
3957
+ for (const word of wordArrays) {
3958
+ let node = 0;
3959
+ for (let i = 0; i < word.length; i++) {
3960
+ const val = word[i];
3961
+ if (!(val in this.next[node])) {
3962
+ this.next.push(Object.create(null));
3963
+ this.fail.push(0);
3964
+ this.match.push(false);
3965
+ this.next[node][val] = this.next.length - 1;
3966
+ }
3967
+ node = this.next[node][val];
3968
+ }
3969
+ this.match[node] = true;
3970
+ }
3971
+
3972
+ // Build Failure Links (BFS)
3973
+ const queue = [];
3974
+ for (const val in this.next[0]) {
3975
+ if (Object.prototype.hasOwnProperty.call(this.next[0], val)) {
3976
+ const child = this.next[0][val];
3977
+ this.fail[child] = 0;
3978
+ queue.push(child);
3979
+ }
3980
+ }
3981
+ while (queue.length > 0) {
3982
+ const curr = queue.shift();
3983
+ for (const val in this.next[curr]) {
3984
+ if (Object.prototype.hasOwnProperty.call(this.next[curr], val)) {
3985
+ const child = this.next[curr][val];
3986
+ let failNode = this.fail[curr];
3987
+ while (failNode !== 0 && !(val in this.next[failNode])) {
3988
+ failNode = this.fail[failNode];
3989
+ }
3990
+ if (val in this.next[failNode]) {
3991
+ this.fail[child] = this.next[failNode][val];
3992
+ } else {
3993
+ this.fail[child] = 0;
3994
+ }
3995
+ this.match[child] = this.match[child] || this.match[this.fail[child]];
3996
+ queue.push(child);
3997
+ }
3998
+ }
3999
+ }
4000
+ }
4001
+ searchUTF16(charSeq, start, end) {
4002
+ let node = 0;
4003
+ for (let i = start; i < end; i++) {
4004
+ const val = charSeq.charCodeAt(i);
4005
+ while (node !== 0 && !(val in this.next[node])) {
4006
+ node = this.fail[node];
4007
+ }
4008
+ if (val in this.next[node]) {
4009
+ node = this.next[node][val];
4010
+ }
4011
+ if (this.match[node]) return true;
4012
+ }
4013
+ return false;
4014
+ }
4015
+ searchUTF8(bytes, start, end) {
4016
+ let node = 0;
4017
+ for (let i = start; i < end; i++) {
4018
+ const val = bytes[i];
4019
+ while (node !== 0 && !(val in this.next[node])) {
4020
+ node = this.fail[node];
4021
+ }
4022
+ if (val in this.next[node]) {
4023
+ node = this.next[node][val];
4024
+ }
4025
+ if (this.match[node]) return true;
4026
+ }
4027
+ return false;
4028
+ }
4029
+ }
3711
4030
  class Prefilter {
3712
4031
  static Type = {
3713
4032
  NONE: 0,
@@ -3720,6 +4039,8 @@ class Prefilter {
3720
4039
  this.subs = [];
3721
4040
  this.str = '';
3722
4041
  this.bytes = null;
4042
+ this.ac16 = null;
4043
+ this.ac8 = null;
3723
4044
  }
3724
4045
  eval(input, pos) {
3725
4046
  switch (this.type) {
@@ -3733,6 +4054,10 @@ class Prefilter {
3733
4054
  }
3734
4055
  return true;
3735
4056
  case Prefilter.Type.OR:
4057
+ // Exploit Aho-Corasick if it was successfully built
4058
+ if (this.ac16 && this.ac8) {
4059
+ return input.hasAnyString(this, pos);
4060
+ }
3736
4061
  for (let i = 0; i < this.subs.length; i++) {
3737
4062
  if (this.subs[i].eval(input, pos)) return true;
3738
4063
  }
@@ -3750,6 +4075,8 @@ class PrefilterTree {
3750
4075
  static fromRegexp(re) {
3751
4076
  if (!re) return new Prefilter(Prefilter.Type.NONE);
3752
4077
  switch (re.op) {
4078
+ case Regexp.Op.PLB:
4079
+ case Regexp.Op.NLB:
3753
4080
  case Regexp.Op.NO_MATCH:
3754
4081
  case Regexp.Op.EMPTY_MATCH:
3755
4082
  case Regexp.Op.BEGIN_LINE:
@@ -3821,7 +4148,9 @@ class PrefilterTree {
3821
4148
  const s = PrefilterTree.simplify(sub);
3822
4149
  if (s.type !== Prefilter.Type.NONE) {
3823
4150
  if (s.type === Prefilter.Type.AND) {
3824
- newSubs.push(...s.subs);
4151
+ for (let j = 0; j < s.subs.length; j++) {
4152
+ newSubs.push(s.subs[j]);
4153
+ }
3825
4154
  } else {
3826
4155
  newSubs.push(s);
3827
4156
  }
@@ -3863,6 +4192,27 @@ class PrefilterTree {
3863
4192
  }
3864
4193
  }
3865
4194
  pf.subs = uniqueSubs;
4195
+
4196
+ // Build an Aho-Corasick automaton if all children are exact matches
4197
+ let allExact = true;
4198
+ for (const sub of uniqueSubs) {
4199
+ if (sub.type !== Prefilter.Type.EXACT) {
4200
+ allExact = false;
4201
+ break;
4202
+ }
4203
+ }
4204
+ if (allExact && uniqueSubs.length > 1) {
4205
+ const words16 = uniqueSubs.map(s => {
4206
+ const arr = [];
4207
+ for (let i = 0; i < s.str.length; i++) {
4208
+ arr.push(s.str.charCodeAt(i));
4209
+ }
4210
+ return arr;
4211
+ });
4212
+ pf.ac16 = new AhoCorasick(words16);
4213
+ const words8 = uniqueSubs.map(s => s.bytes);
4214
+ pf.ac8 = new AhoCorasick(words8);
4215
+ }
3866
4216
  return pf;
3867
4217
  }
3868
4218
  return pf;
@@ -3900,6 +4250,8 @@ class Prog {
3900
4250
  // number of CAPTURE insts in re
3901
4251
  // 2 => implicit ( and ) for whole match $0
3902
4252
  this.numCap = 2;
4253
+ this.lbStarts = []; // Track starting PCs of lookbehind automata
4254
+ this.numLb = 0; // Total number of lookbehinds
3903
4255
  }
3904
4256
 
3905
4257
  // Returns the instruction at the specified pc.
@@ -4232,6 +4584,26 @@ class Compiler {
4232
4584
  }
4233
4585
  return f;
4234
4586
  }
4587
+ lookBehind(a, lb) {
4588
+ const id = this.newInst(Inst.LB_WRITE);
4589
+ this.prog.getInst(id.i).lb = lb;
4590
+
4591
+ // Create the prefix wildcard `.*` for the lookbehind automaton
4592
+ const any = this.rune(Compiler.ANY_RUNE(), 0);
4593
+ const dotStar = this.star(any, true); // nongreedy = true
4594
+ const lbAutomaton = this.cat(dotStar, a);
4595
+ this.prog.patch(lbAutomaton.out, id.i);
4596
+ const checkId = this.newInst(Inst.LB_CHECK);
4597
+ this.prog.getInst(checkId.i).lb = lb;
4598
+
4599
+ // Save the starting point of this lookbehind automaton
4600
+ this.prog.lbStarts.push(lbAutomaton.i);
4601
+ if (Math.abs(lb) > this.prog.numLb) {
4602
+ this.prog.numLb = Math.abs(lb);
4603
+ }
4604
+ checkId.out = new PatchList(checkId.i << 1, checkId.i << 1);
4605
+ return checkId;
4606
+ }
4235
4607
  compile(re) {
4236
4608
  switch (re.op) {
4237
4609
  case Regexp.Op.NO_MATCH:
@@ -4267,6 +4639,9 @@ class Compiler {
4267
4639
  return this.empty(Utils.EMPTY_WORD_BOUNDARY);
4268
4640
  case Regexp.Op.NO_WORD_BOUNDARY:
4269
4641
  return this.empty(Utils.EMPTY_NO_WORD_BOUNDARY);
4642
+ case Regexp.Op.PLB:
4643
+ case Regexp.Op.NLB:
4644
+ return this.lookBehind(this.compile(re.subs[0]), re.lb);
4270
4645
  case Regexp.Op.CAPTURE:
4271
4646
  {
4272
4647
  const bra = this.cap(re.cap << 1);
@@ -4326,6 +4701,8 @@ class Simplify {
4326
4701
  return null;
4327
4702
  }
4328
4703
  switch (re.op) {
4704
+ case Regexp.Op.PLB:
4705
+ case Regexp.Op.NLB:
4329
4706
  case Regexp.Op.CAPTURE:
4330
4707
  {
4331
4708
  const sub = Simplify.simplify(re.subs[0]);
@@ -4362,7 +4739,9 @@ class Simplify {
4362
4739
  // Flatten nested concatenations
4363
4740
  if (nsub.op === Regexp.Op.CONCAT) {
4364
4741
  changed = true;
4365
- newSubs.push(...nsub.subs);
4742
+ for (let j = 0; j < nsub.subs.length; j++) {
4743
+ newSubs.push(nsub.subs[j]);
4744
+ }
4366
4745
  continue;
4367
4746
  }
4368
4747
  } else if (re.op === Regexp.Op.ALTERNATE) {
@@ -4374,7 +4753,9 @@ class Simplify {
4374
4753
  // Flatten nested alternations
4375
4754
  if (nsub.op === Regexp.Op.ALTERNATE) {
4376
4755
  changed = true;
4377
- newSubs.push(...nsub.subs);
4756
+ for (let j = 0; j < nsub.subs.length; j++) {
4757
+ newSubs.push(nsub.subs[j]);
4758
+ }
4378
4759
  continue;
4379
4760
  }
4380
4761
  }
@@ -5384,7 +5765,10 @@ class Parser {
5384
5765
  return t.pop();
5385
5766
  }
5386
5767
  static concatRunes(x, y) {
5387
- return [...x, ...y];
5768
+ for (let i = 0; i < y.length; i++) {
5769
+ x.push(y[i]);
5770
+ }
5771
+ return x;
5388
5772
  }
5389
5773
  constructor(wholeRegexp, flags = 0) {
5390
5774
  this.wholeRegexp = wholeRegexp;
@@ -5403,6 +5787,7 @@ class Parser {
5403
5787
  this.repeats = 0; // product of all repetitions seen
5404
5788
  this.height = null; // regexp height, for height limit check
5405
5789
  this.size = null; // regexp compiled size, for size limit check
5790
+ this.nlb = 0; // Number of lookbehinds seen
5406
5791
  }
5407
5792
 
5408
5793
  // Allocate a Regexp, from the free list if possible.
@@ -5419,8 +5804,8 @@ class Parser {
5419
5804
  return re;
5420
5805
  }
5421
5806
  reuse(re) {
5422
- if (this.height !== null && Object.prototype.hasOwnProperty.call(this.height, re)) {
5423
- delete this.height[re];
5807
+ if (this.height !== null && this.height.has(re)) {
5808
+ this.height.delete(re);
5424
5809
  }
5425
5810
  if (re.subs !== null && re.subs.length > 0) {
5426
5811
  re.subs[0] = this.free;
@@ -5452,20 +5837,20 @@ class Parser {
5452
5837
  if (n <= 0) {
5453
5838
  n = 1;
5454
5839
  }
5455
- if (n > Parser.MAX_SIZE / this.repeats) {
5840
+ if (n > Math.floor(Parser.MAX_SIZE / this.repeats)) {
5456
5841
  this.repeats = Parser.MAX_SIZE;
5457
5842
  } else {
5458
5843
  this.repeats *= n;
5459
5844
  }
5460
5845
  }
5461
- if (this.numRegexp < Parser.MAX_SIZE / this.repeats) {
5846
+ if (this.numRegexp < Math.floor(Parser.MAX_SIZE / this.repeats)) {
5462
5847
  return;
5463
5848
  }
5464
5849
 
5465
5850
  // We need to start tracking size.
5466
5851
  // Make the map and belatedly populate it
5467
5852
  // with info about everything we've constructed so far.
5468
- this.size = {};
5853
+ this.size = new Map();
5469
5854
  for (let reEx of this.stack) {
5470
5855
  this.checkSize(reEx);
5471
5856
  }
@@ -5475,9 +5860,9 @@ class Parser {
5475
5860
  }
5476
5861
  }
5477
5862
  calcSize(re, force = false) {
5478
- if (!force) {
5479
- if (Object.prototype.hasOwnProperty.call(this.size, re)) {
5480
- return this.size[re];
5863
+ if (!force && this.size !== null) {
5864
+ if (this.size.has(re)) {
5865
+ return this.size.get(re);
5481
5866
  }
5482
5867
  }
5483
5868
  let size = 0;
@@ -5487,6 +5872,8 @@ class Parser {
5487
5872
  size = re.runes.length;
5488
5873
  break;
5489
5874
  }
5875
+ case Regexp.Op.PLB:
5876
+ case Regexp.Op.NLB:
5490
5877
  case Regexp.Op.CAPTURE:
5491
5878
  case Regexp.Op.STAR:
5492
5879
  {
@@ -5534,7 +5921,10 @@ class Parser {
5534
5921
  }
5535
5922
  }
5536
5923
  size = Math.max(1, size);
5537
- this.size[re] = size;
5924
+ if (this.size === null) {
5925
+ this.size = new Map();
5926
+ }
5927
+ this.size.set(re, size);
5538
5928
  return size;
5539
5929
  }
5540
5930
  checkHeight(re) {
@@ -5542,7 +5932,7 @@ class Parser {
5542
5932
  return;
5543
5933
  }
5544
5934
  if (this.height === null) {
5545
- this.height = {};
5935
+ this.height = new Map();
5546
5936
  for (let reEx of this.stack) {
5547
5937
  this.checkHeight(reEx);
5548
5938
  }
@@ -5552,9 +5942,9 @@ class Parser {
5552
5942
  }
5553
5943
  }
5554
5944
  calcHeight(re, force = false) {
5555
- if (!force) {
5556
- if (Object.prototype.hasOwnProperty.call(this.height, re)) {
5557
- return this.height[re];
5945
+ if (!force && this.height !== null) {
5946
+ if (this.height.has(re)) {
5947
+ return this.height.get(re);
5558
5948
  }
5559
5949
  }
5560
5950
  let h = 1;
@@ -5564,7 +5954,10 @@ class Parser {
5564
5954
  h = 1 + hsub;
5565
5955
  }
5566
5956
  }
5567
- this.height[re] = h;
5957
+ if (this.height === null) {
5958
+ this.height = new Map();
5959
+ }
5960
+ this.height.set(re, h);
5568
5961
  return h;
5569
5962
  }
5570
5963
 
@@ -6132,6 +6525,19 @@ class Parser {
6132
6525
  let repeatPos = -1;
6133
6526
  bigswitch: switch (t.peek()) {
6134
6527
  case Codepoint.CODES.get('('):
6528
+ // Intercept Lookbehinds if the flag is enabled
6529
+ if ((this.flags & RE2Flags.LOOKBEHIND) !== 0) {
6530
+ if (t.lookingAt('(?<=')) {
6531
+ this.parsePosLookBehind();
6532
+ t.skip(4); // Skip over '(?<='
6533
+ break;
6534
+ }
6535
+ if (t.lookingAt('(?<!')) {
6536
+ this.parseNegLookBehind();
6537
+ t.skip(4); // Skip over '(?<!'
6538
+ break;
6539
+ }
6540
+ }
6135
6541
  if ((this.flags & RE2Flags.PERL_X) !== 0 && t.lookingAt('(?')) {
6136
6542
  // Flag changes and non-capturing groups.
6137
6543
  this.parsePerlFlags(t);
@@ -6412,6 +6818,20 @@ class Parser {
6412
6818
  throw new RE2JSSyntaxException(Parser.ERR_INVALID_PERL_OP, t.from(startPos));
6413
6819
  }
6414
6820
 
6821
+ // Lookbehinds parsing
6822
+ parsePosLookBehind() {
6823
+ const re = this.newRegexp(Regexp.Op.LEFT_PAREN);
6824
+ re.flags = this.flags;
6825
+ re.lb = ++this.nlb;
6826
+ return this.push(re);
6827
+ }
6828
+ parseNegLookBehind() {
6829
+ const re = this.newRegexp(Regexp.Op.LEFT_PAREN);
6830
+ re.flags = this.flags;
6831
+ re.lb = -++this.nlb;
6832
+ return this.push(re);
6833
+ }
6834
+
6415
6835
  // parseVerticalBar handles a | in the input.
6416
6836
  parseVerticalBar() {
6417
6837
  this.concat();
@@ -6481,6 +6901,18 @@ class Parser {
6481
6901
  }
6482
6902
  // Restore flags at time of paren.
6483
6903
  this.flags = re2.flags;
6904
+
6905
+ // Handle lookbehinds
6906
+ if (re2.lb !== 0) {
6907
+ if (re2.lb > 0) {
6908
+ re2.op = Regexp.Op.PLB;
6909
+ } else {
6910
+ re2.op = Regexp.Op.NLB;
6911
+ }
6912
+ re2.subs = [re1];
6913
+ this.push(re2);
6914
+ return;
6915
+ }
6484
6916
  if (re2.cap === 0) {
6485
6917
  // Just for grouping.
6486
6918
  this.push(re1);
@@ -6879,21 +7311,25 @@ class RE2 {
6879
7311
  // We must use the NFA.
6880
7312
  if (ncap > 0) {
6881
7313
  // Backtracker bit-state execution bounds check
6882
- if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
7314
+ if (this.prog.numLb === 0 && input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
6883
7315
  return Backtracker.execute(this, input, pos, anchor, ncap);
6884
7316
  }
6885
7317
  // NFA execution
6886
7318
  return this.doExecuteNFA(input, pos, anchor, ncap);
6887
7319
  }
6888
- const dfaResult = this.dfa.match(input, pos, anchor);
6889
- if (dfaResult !== null) {
6890
- // DFA succeeded (returned true or false)
6891
- return dfaResult ? [] : null; // Return empty array to signify "matched but no captures"
6892
- }
6893
7320
 
6894
- // Backtracker bit-state execution bounds check
6895
- if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
6896
- return Backtracker.execute(this, input, pos, anchor, ncap);
7321
+ // The DFA will safely return null (bailout) if it encounters a lookbehind
7322
+ if (this.prog.numLb === 0) {
7323
+ const dfaResult = this.dfa.match(input, pos, anchor);
7324
+ if (dfaResult !== null) {
7325
+ // DFA succeeded (returned true or false)
7326
+ return dfaResult ? [] : null; // Return empty array to signify "matched but no captures"
7327
+ }
7328
+
7329
+ // Backtracker bit-state execution bounds check
7330
+ if (input.endPos() <= Backtracker.maxBitStateLen(this.prog)) {
7331
+ return Backtracker.execute(this, input, pos, anchor, ncap);
7332
+ }
6897
7333
  }
6898
7334
 
6899
7335
  // Fallback to NFA
@@ -7477,9 +7913,20 @@ class RE2 {
7477
7913
  }
7478
7914
 
7479
7915
  class RE2Set {
7480
- constructor(anchor = RE2Flags.UNANCHORED, flags = RE2Flags.PERL) {
7916
+ static UNANCHORED = RE2Flags.UNANCHORED;
7917
+ static ANCHOR_START = RE2Flags.ANCHOR_START;
7918
+ static ANCHOR_BOTH = RE2Flags.ANCHOR_BOTH;
7919
+ constructor(anchor = RE2Set.UNANCHORED, flags = 0) {
7481
7920
  this.anchor = anchor;
7482
- this.flags = flags;
7921
+ this.jsFlags = flags;
7922
+ let re2Flags = RE2Flags.PERL;
7923
+ if ((flags & PublicFlags.DISABLE_UNICODE_GROUPS) !== 0) {
7924
+ re2Flags &= -129;
7925
+ }
7926
+ if ((flags & PublicFlags.LOOKBEHINDS) !== 0) {
7927
+ re2Flags |= RE2Flags.LOOKBEHIND;
7928
+ }
7929
+ this.re2Flags = re2Flags;
7483
7930
  this.regexps = [];
7484
7931
  this.prog = null;
7485
7932
  this.dfa = null;
@@ -7489,7 +7936,17 @@ class RE2Set {
7489
7936
  if (this.prog) {
7490
7937
  throw new RE2JSCompileException('Cannot add patterns after compile');
7491
7938
  }
7492
- const re = Parser.parse(pattern, this.flags);
7939
+ let fregex = pattern;
7940
+ if ((this.jsFlags & PublicFlags.CASE_INSENSITIVE) !== 0) {
7941
+ fregex = `(?i)${fregex}`;
7942
+ }
7943
+ if ((this.jsFlags & PublicFlags.DOTALL) !== 0) {
7944
+ fregex = `(?s)${fregex}`;
7945
+ }
7946
+ if ((this.jsFlags & PublicFlags.MULTILINE) !== 0) {
7947
+ fregex = `(?m)${fregex}`;
7948
+ }
7949
+ const re = Parser.parse(fregex, this.re2Flags);
7493
7950
  this.regexps.push(Simplify.simplify(re));
7494
7951
  return this.regexps.length - 1;
7495
7952
  }
@@ -7508,15 +7965,21 @@ class RE2Set {
7508
7965
  match(input) {
7509
7966
  if (!this.prog) this.compile();
7510
7967
  const machineInput = Array.isArray(input) ? MachineInput.fromUTF8(input) : MachineInput.fromUTF16(input);
7968
+ let internalAnchor = RE2Flags.UNANCHORED;
7969
+ if (this.anchor === RE2Set.ANCHOR_START) {
7970
+ internalAnchor = RE2Flags.ANCHOR_START;
7971
+ } else if (this.anchor === RE2Set.ANCHOR_BOTH) {
7972
+ internalAnchor = RE2Flags.ANCHOR_BOTH;
7973
+ }
7511
7974
 
7512
7975
  // Fast path: Try the blistering fast DFA
7513
- const dfaResult = this.dfa.matchSet(machineInput, 0, this.anchor);
7976
+ const dfaResult = this.dfa.matchSet(machineInput, 0, internalAnchor);
7514
7977
  if (dfaResult !== null) return dfaResult;
7515
7978
 
7516
7979
  // Safe Fallback: Handle boundaries (\b) or massive state explosions via NFA
7517
7980
  const machine = Machine.fromRE2(this.dummyRe2);
7518
7981
  machine.init(0);
7519
- return machine.matchSet(machineInput, 0, this.anchor);
7982
+ return machine.matchSet(machineInput, 0, internalAnchor);
7520
7983
  }
7521
7984
  }
7522
7985
 
@@ -7616,7 +8079,7 @@ class TranslateRegExpString {
7616
8079
  changed = true;
7617
8080
  continue;
7618
8081
  } else if (ch === '(' && i + 2 < size && data[i + 1] === '?' && data[i + 2] === '<') {
7619
- if (i + 3 >= size || data[i + 3] !== '=' && data[i + 3] !== '!') {
8082
+ if (i + 3 < size && !'=!>)'.includes(data[i + 3])) {
7620
8083
  result += '(?P<';
7621
8084
  i += 3;
7622
8085
  changed = true;
@@ -7646,24 +8109,28 @@ class RE2JS {
7646
8109
  /**
7647
8110
  * Flag: case insensitive matching.
7648
8111
  */
7649
- static CASE_INSENSITIVE = 1;
8112
+ static CASE_INSENSITIVE = PublicFlags.CASE_INSENSITIVE;
7650
8113
  /**
7651
8114
  * Flag: dot ({@code .}) matches all characters, including newline.
7652
8115
  */
7653
- static DOTALL = 2;
8116
+ static DOTALL = PublicFlags.DOTALL;
7654
8117
  /**
7655
8118
  * Flag: multiline matching: {@code ^} and {@code $} match at beginning and end of line, not just
7656
8119
  * beginning and end of input.
7657
8120
  */
7658
- static MULTILINE = 4;
8121
+ static MULTILINE = PublicFlags.MULTILINE;
7659
8122
  /**
7660
8123
  * Flag: Unicode groups (e.g. {@code \p\ Greek\} ) will be syntax errors.
7661
8124
  */
7662
- static DISABLE_UNICODE_GROUPS = 8;
8125
+ static DISABLE_UNICODE_GROUPS = PublicFlags.DISABLE_UNICODE_GROUPS;
7663
8126
  /**
7664
8127
  * Flag: matches longest possible string.
7665
8128
  */
7666
- static LONGEST_MATCH = 16;
8129
+ static LONGEST_MATCH = PublicFlags.LONGEST_MATCH;
8130
+ /**
8131
+ * Flag: enable linear-time captureless lookbehinds.
8132
+ */
8133
+ static LOOKBEHINDS = PublicFlags.LOOKBEHINDS;
7667
8134
 
7668
8135
  /**
7669
8136
  * Returns a literal pattern string for the specified string.
@@ -7726,13 +8193,16 @@ class RE2JS {
7726
8193
  if ((flags & RE2JS.MULTILINE) !== 0) {
7727
8194
  fregex = `(?m)${fregex}`;
7728
8195
  }
7729
- if ((flags & ~(RE2JS.MULTILINE | RE2JS.DOTALL | RE2JS.CASE_INSENSITIVE | RE2JS.DISABLE_UNICODE_GROUPS | RE2JS.LONGEST_MATCH)) !== 0) {
7730
- throw new RE2JSFlagsException('Flags should only be a combination of MULTILINE, DOTALL, CASE_INSENSITIVE, DISABLE_UNICODE_GROUPS, LONGEST_MATCH');
8196
+ if ((flags & ~(RE2JS.MULTILINE | RE2JS.DOTALL | RE2JS.CASE_INSENSITIVE | RE2JS.DISABLE_UNICODE_GROUPS | RE2JS.LONGEST_MATCH | RE2JS.LOOKBEHINDS)) !== 0) {
8197
+ throw new RE2JSFlagsException('Flags should only be a combination of MULTILINE, DOTALL, CASE_INSENSITIVE, DISABLE_UNICODE_GROUPS, LONGEST_MATCH, LOOKBEHINDS');
7731
8198
  }
7732
8199
  let re2Flags = RE2Flags.PERL;
7733
8200
  if ((flags & RE2JS.DISABLE_UNICODE_GROUPS) !== 0) {
7734
8201
  re2Flags &= -129;
7735
8202
  }
8203
+ if ((flags & RE2JS.LOOKBEHINDS) !== 0) {
8204
+ re2Flags |= RE2Flags.LOOKBEHIND;
8205
+ }
7736
8206
  const p = new RE2JS(regex, flags);
7737
8207
  // The compiled RE2 regexp.
7738
8208
  p.re2Input = RE2.compileImpl(fregex, re2Flags, (flags & RE2JS.LONGEST_MATCH) !== 0);