text: /* This Source Code Form is subject to the terms of the Mozilla Public
   * License, v. 2.0. If a copy of the MPL was not distributed with this
   * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  
  // Simple cases, not using eval.
  {
      let \u{61} = 123;
      assertEq(a, 123);
  
      let \u{6A} = 123;
      assertEq(j, 123);
  
      let a\u{62} = 456;
      assertEq(ab, 456);
  
      let \u{63}\u{6b} = 789;
      assertEq(ck, 789);
  }
  
  const leadingZeros = [0, 1, 2, 3, 4, 100].map(c => "0".repeat(c));
  
  
  // From DerivedCoreProperties.txt (Unicode 9):
  // Derived Property: ID_Start
  //  Characters that can start an identifier.
  //  Generated from:
  //      Lu + Ll + Lt + Lm + Lo + Nl
  //    + Other_ID_Start
  //    - Pattern_Syntax
  //    - Pattern_White_Space
  const idStart = [
      0x0041,     // LATIN CAPITAL LETTER A, Gc=Lu
      0x006A,     // LATIN SMALL LETTER J, Gc=Ll
      0x00C9,     // LATIN CAPITAL LETTER E WITH ACUTE, Gc=Lu
      0x00FF,     // LATIN SMALL LETTER Y WITH DIAERESIS, Gc=Ll
      0x01C5,     // LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON, Gc=Lt
      0x0294,     // LATIN LETTER GLOTTAL STOP, Gc=Lo
      0x037A,     // GREEK YPOGEGRAMMENI, Gc=Lm
      0x16EE,     // RUNIC ARLAUG SYMBOL, Gc=Nl
      0xFF70,     // HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK, Gc=Lm
  ];
  
  const idStartSupplemental = [
      0x10140,    // GREEK ACROPHONIC ATTIC ONE QUARTER, Gc=Nl
      0x10300,    // OLD ITALIC LETTER A, Gc=Lo
      0x10400,    // DESERET CAPITAL LETTER LONG I, Gc=Lu
      0x10430,    // DESERET SMALL LETTER SHORT A, Gc=Ll
      0x16B40,    // PAHAWH HMONG SIGN VOS SEEV, Gc=Lm
  ];
  
  // From PropList.txt (Unicode 9):
  const otherIdStart = [
      0x1885,     // MONGOLIAN LETTER ALI GALI BALUDA, Gc=Mn
      0x1886,     // MONGOLIAN LETTER ALI GALI THREE BALUDA, Gc=Mn
      0x2118,     // SCRIPT CAPITAL P, Gc=Sm
      0x212E,     // ESTIMATED SYMBOL, Gc=So
      0x309B,     // KATAKANA-HIRAGANA VOICED SOUND MARK, Gc=Sk
      0x309C,     // KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK, Gc=Sk
  ];
  
  // From DerivedCoreProperties.txt (Unicode 9):
  // Derived Property: ID_Continue
  //  Characters that can continue an identifier.
  //  Generated from:
  //      ID_Start
  //    + Mn + Mc + Nd + Pc
  //    + Other_ID_Continue
  //    - Pattern_Syntax
  //    - Pattern_White_Space
  const idContinue = [
      0x0030,     // DIGIT ZERO, Gc=Nd
      0x0300,     // COMBINING GRAVE ACCENT, Gc=Mn
      0x0660,     // ARABIC-INDIC DIGIT ZERO, Gc=Nd
      0x0903,     // DEVANAGARI SIGN VISARGA, Gc=Mc
      0xFF10,     // FULLWIDTH DIGIT ZERO, Gc=Nd
      0xFF3F,     // FULLWIDTH LOW LINE, Gc=Pc
  ];
  
  const idContinueSupplemental = [
      0x101FD,    // PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE, Gc=Mn
      0x104A0,    // OSMANYA DIGIT ZERO, Gc=Nd
      0x11000,    // BRAHMI SIGN CANDRABINDU, Gc=Mc
  ];
  
  // From PropList.txt (Unicode 9):
  const otherIdContinue = [
      0x00B7,     // MIDDLE DOT, Gc=Po
      0x0387,     // GREEK ANO TELEIA, Gc=Po
      0x1369,     // ETHIOPIC DIGIT ONE, Gc=No
      0x136A,     // ETHIOPIC DIGIT TWO, Gc=No
      0x136B,     // ETHIOPIC DIGIT THREE, Gc=No
      0x136C,     // ETHIOPIC DIGIT FOUR, Gc=No
      0x136D,     // ETHIOPIC DIGIT FIVE, Gc=No
      0x136E,     // ETHIOPIC DIGIT SIX, Gc=No
      0x136F,     // ETHIOPIC DIGIT SEVEN, Gc=No
      0x1370,     // ETHIOPIC DIGIT EIGHT, Gc=No
      0x1371,     // ETHIOPIC DIGIT NINE, Gc=No
      0x19DA,     // NEW TAI LUE THAM DIGIT ONE, Gc=No
  ];
  
  for (let ident of [...idStart, ...otherIdStart, ...idStartSupplemental]) {
      for (let count of leadingZeros) {
          let zeros = "0".repeat(count);
          eval(`
              let \\u{${zeros}${ident.toString(16)}} = 123;
              assertEq(${String.fromCodePoint(ident)}, 123);
          `);
      }
  }
  
  for (let ident of [...idContinue, ...idContinueSupplemental, ...otherIdContinue]) {
      for (let zeros of leadingZeros) {
          assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError);
      }
  }
  
  for (let ident of [...idStart, ...otherIdStart, ...idContinue, ...otherIdContinue, ...idStartSupplemental, ...idContinueSupplemental]) {
      for (let zeros of leadingZeros) {
          eval(`
              let A\\u{${zeros}${ident.toString(16)}} = 123;
              assertEq(${String.fromCodePoint(0x41, ident)}, 123);
          `);
      }
  }
  
  
  const notIdentifiers = [
      0x0000,     // NULL, Gc=Cc
      0x000A,     // LINE FEED (LF), Gc=Cc
      0x005E,     // CIRCUMFLEX ACCENT, Gc=Sk
      0x00B1,     // PLUS-MINUS SIGN, Gc=Sm
      0xFF61,     // HALFWIDTH IDEOGRAPHIC FULL STOP, Gc=Po
      0x10061,    // Not assigned.
      0x10100,    // AEGEAN WORD SEPARATOR LINE, Gc=Po
      0x100061,   // <Plane 16 Private Use>, Gc=Co
  ];
  
  for (let ident of notIdentifiers) {
      for (let zeros of leadingZeros) {
          assertThrowsInstanceOf(() => eval(`\\u{${zeros}${ident.toString(16)}}`), SyntaxError);
      }
  }
  
  
  const incompleteEscapes = [
      "\\u{",
      "\\u{6",
      "\\u{61",
      "\\u{061",
      "\\u{0061",
      "\\u{00061",
      "\\u{000061",
      "\\u{0000061",
  
      "\\u}",
  ];
  for (let invalid of incompleteEscapes) {
      // Ends with EOF.
      assertThrowsInstanceOf(() => eval(invalid), SyntaxError);
  
      // Ends with EOL.
      assertThrowsInstanceOf(() => eval(invalid + "\n"), SyntaxError);
  
      // Ends with space.
      assertThrowsInstanceOf(() => eval(invalid + " "), SyntaxError);
  }
  
  
  const invalidEscapes = [
      // Empty escape.
      "",
  
      // Not hexadecimal characters.
      "\0",
      "G",
      "Z",
      "\uFFFF",
      "\uDBFF\uDFFF",
  
      // Has space characters.
      " 61",
      "61 ",
  
      // Has newline characters.
      "\n61",
      "61\n",
  
      // Exceeds 0x10FFFF, six characters.
      "110000",
      "110001",
      "fffffe",
      "ffffff",
  
      // Exceeds 0x10FFFF, more than six characters.
      "10ffff0",
      "10ffffabcdef",
  ];
  
  for (let invalid of invalidEscapes) {
      for (let zeros of leadingZeros) {
          assertThrowsInstanceOf(() => eval(`\\u{${zeros}${invalid}}`), SyntaxError);
          assertThrowsInstanceOf(() => eval(`var \\u{${zeros}${invalid}}`), SyntaxError);
      }
  }
  
  
  if (typeof reportCompare === "function")
      reportCompare(0, 0, "ok");
  