Bug 1559269 - Remove preliminary TokenStream support for private fields. r=khyperia
authorJason Orendorff <jorendorff@mozilla.com>
Wed, 26 Jun 2019 04:40:34 +0000
changeset 542967 347c39ed601e66e5239b67dd627018bf9d0ede97
parent 542966 647196edc18482fa0a890ab99db31c2c32e874cb
child 542968 1d9e6a4506c4cf6d372fa5de43c9ed1c8912e766
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskhyperia
bugs1559269
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1559269 - Remove preliminary TokenStream support for private fields. r=khyperia Differential Revision: https://phabricator.services.mozilla.com/D35532
js/src/frontend/TokenStream.cpp
js/src/jit-test/tests/fields/access.js
js/src/jit-test/tests/fields/basic.js
js/src/jit-test/tests/fields/bug1547915.js
js/src/jit-test/tests/fields/error.js
js/src/js.msg
--- a/js/src/frontend/TokenStream.cpp
+++ b/js/src/frontend/TokenStream.cpp
@@ -57,16 +57,20 @@ using mozilla::MakeSpan;
 using mozilla::Maybe;
 using mozilla::PointerRangeSize;
 using mozilla::Utf8Unit;
 
 using JS::ReadOnlyCompileOptions;
 using JS::RegExpFlag;
 using JS::RegExpFlags;
 
+// There's some very preliminary support for private fields in this file. It's
+// disabled in all builds, for now.
+//#define JS_PRIVATE_FIELDS 1
+
 struct ReservedWordInfo {
   const char* chars;  // C string with reserved word text
   js::frontend::TokenKind tokentype;
 };
 
 static const ReservedWordInfo reservedWords[] = {
 #define RESERVED_WORD_INFO(word, name, type) \
   {js_##word##_str, js::frontend::type},
@@ -124,30 +128,38 @@ MOZ_ALWAYS_INLINE const ReservedWordInfo
 }
 
 static const ReservedWordInfo* FindReservedWord(
     JSLinearString* str, js::frontend::NameVisibility* visibility) {
   JS::AutoCheckCannotGC nogc;
   if (str->hasLatin1Chars()) {
     const JS::Latin1Char* chars = str->latin1Chars(nogc);
     size_t length = str->length();
+#ifdef JS_PRIVATE_FIELDS
     if (length > 0 && chars[0] == '#') {
       *visibility = js::frontend::NameVisibility::Private;
       return nullptr;
     }
+#else
+    MOZ_ASSERT_IF(length > 0, chars[0] != '#');
+#endif
     *visibility = js::frontend::NameVisibility::Public;
     return FindReservedWord(chars, length);
   }
 
   const char16_t* chars = str->twoByteChars(nogc);
   size_t length = str->length();
+#ifdef JS_PRIVATE_FIELDS
   if (length > 0 && chars[0] == '#') {
     *visibility = js::frontend::NameVisibility::Private;
     return nullptr;
   }
+#else
+  MOZ_ASSERT_IF(length > 0, chars[0] != '#');
+#endif
   *visibility = js::frontend::NameVisibility::Public;
   return FindReservedWord(chars, length);
 }
 
 static uint32_t GetSingleCodePoint(const char16_t** p, const char16_t* end) {
   using namespace js;
 
   uint32_t codePoint;
@@ -228,18 +240,22 @@ bool IsIdentifier(const Latin1Char* char
 }
 
 bool IsIdentifierNameOrPrivateName(const Latin1Char* chars, size_t length) {
   if (length == 0) {
     return false;
   }
 
   if (char16_t(*chars) == '#') {
+#ifdef JS_PRIVATE_FIELDS
     ++chars;
     --length;
+#else
+    return false;
+#endif
   }
 
   return IsIdentifier(chars, length);
 }
 
 bool IsIdentifier(const char16_t* chars, size_t length) {
   if (length == 0) {
     return false;
@@ -270,21 +286,25 @@ bool IsIdentifierNameOrPrivateName(const
   }
 
   const char16_t* p = chars;
   const char16_t* end = chars + length;
   uint32_t codePoint;
 
   codePoint = GetSingleCodePoint(&p, end);
   if (codePoint == '#') {
+#ifdef JS_PRIVATE_FIELDS
     if (length == 1) {
       return false;
     }
 
     codePoint = GetSingleCodePoint(&p, end);
+#else
+    return false;
+#endif
   }
 
   if (!unicode::IsIdentifierStart(codePoint)) {
     return false;
   }
 
   while (p < end) {
     codePoint = GetSingleCodePoint(&p, end);
@@ -2146,18 +2166,21 @@ bool TokenStreamSpecific<Unit, AnyCharsA
   do {
     int32_t unit = getCodeUnit();
     if (unit == EOF) {
       break;
     }
 
     uint32_t codePoint;
     if (MOZ_LIKELY(isAsciiCodePoint(unit))) {
-      if (unicode::IsIdentifierPart(char16_t(unit)) ||
-          (char16_t(unit) == '#')) {
+      if (unicode::IsIdentifierPart(char16_t(unit))
+#ifdef JS_PRIVATE_FIELDS
+          || char16_t(unit) == '#'
+#endif
+      ) {
         if (!this->charBuffer.append(unit)) {
           return false;
         }
 
         continue;
       }
 
       if (unit != '\\' || !matchUnicodeEscapeIdent(&codePoint)) {
@@ -2261,27 +2284,20 @@ MOZ_MUST_USE bool TokenStreamSpecific<Un
     atom = atomizeSourceChars(anyCharsAccess().cx, MakeSpan(chars, length));
   }
   if (!atom) {
     return false;
   }
 
   noteBadToken.release();
   if (visibility == NameVisibility::Private) {
-    MOZ_ASSERT(identStart[0] == static_cast<Unit>('#'),
-               "Private identifier starts with #");
-    newPrivateNameToken(atom->asPropertyName(), start, modifier, out);
-
-    if (!anyCharsAccess().options().fieldsEnabledOption) {
-      errorAt(start.offset(), JSMSG_FIELDS_NOT_SUPPORTED);
-      return false;
-    }
-  } else {
-    newNameToken(atom->asPropertyName(), start, modifier, out);
+    errorAt(start.offset(), JSMSG_PRIVATE_FIELDS_NOT_SUPPORTED);
+    return false;
   }
+  newNameToken(atom->asPropertyName(), start, modifier, out);
   return true;
 }
 
 enum FirstCharKind {
   // A char16_t has the 'OneChar' kind if it, by itself, constitutes a valid
   // token that cannot also be a prefix of a longer token.  E.g. ';' has the
   // OneChar kind, but '+' does not, because '++' and '+=' are valid longer
   // tokens
@@ -3053,24 +3069,30 @@ MOZ_MUST_USE bool TokenStreamSpecific<Un
         // NOTE: |unit| may be EOF here.  A stray '.' at EOF would be an
         //       error, but subsequent code will handle it.
         ungetCodeUnit(unit);
 
         simpleKind = TokenKind::Dot;
         break;
 
       case '#': {
+#ifdef JS_PRIVATE_FIELDS
         TokenStart start(this->sourceUnits, -1);
         const Unit* identStart = this->sourceUnits.addressOfNextCodeUnit() - 1;
         IdentifierEscapes sawEscape;
         if (!matchIdentifierStart(&sawEscape)) {
           return badToken();
         }
         return identifierName(start, identStart, sawEscape, modifier,
                               NameVisibility::Private, ttp);
+#else
+        ungetCodeUnit(unit);
+        error(JSMSG_PRIVATE_FIELDS_NOT_SUPPORTED);
+        return badToken();
+#endif
       }
 
       case '=':
         if (matchCodeUnit('=')) {
           simpleKind = matchCodeUnit('=') ? TokenKind::StrictEq : TokenKind::Eq;
         } else if (matchCodeUnit('>')) {
           simpleKind = TokenKind::Arrow;
         } else {
--- a/js/src/jit-test/tests/fields/access.js
+++ b/js/src/jit-test/tests/fields/access.js
@@ -2,17 +2,10 @@
 
 class C {
     x = 5;
 }
 
 c = new C();
 assertEq(5, c.x);
 
-class D {
-    #y = 5;
-}
-
-d = new D();
-assertEq(5, d.#y);
-
 if (typeof reportCompare === "function")
   reportCompare(true, true);
--- a/js/src/jit-test/tests/fields/basic.js
+++ b/js/src/jit-test/tests/fields/basic.js
@@ -1,14 +1,9 @@
 // |jit-test| --enable-experimental-fields
 
 class C {
     x;
     y = 2;
 }
 
-class D {
-    #x;
-    #y = 2;
-}
-
 if (typeof reportCompare === "function")
   reportCompare(true, true);
--- a/js/src/jit-test/tests/fields/bug1547915.js
+++ b/js/src/jit-test/tests/fields/bug1547915.js
@@ -1,6 +1,6 @@
 // |jit-test| --enable-experimental-fields
 
 load(libdir + "asserts.js");
 
 source = `#_\\u200C`;
-assertThrowsInstanceOf(() => eval(source), ReferenceError);
+assertThrowsInstanceOf(() => eval(source), SyntaxError);
--- a/js/src/jit-test/tests/fields/error.js
+++ b/js/src/jit-test/tests/fields/error.js
@@ -19,16 +19,26 @@ source = `class C {
 assertErrorMessage(() => Function(source), SyntaxError, /./);
 
 source = `class C {
     #2;
 }`;
 assertErrorMessage(() => Function(source), SyntaxError, /./);
 
 source = `class C {
+    #x;
+}`;
+assertErrorMessage(() => Function(source), SyntaxError, /./);
+
+source = `class C {
+    #y = 2;
+}`;
+assertErrorMessage(() => Function(source), SyntaxError, /./);
+
+source = `class C {
     #["h" + "i"];
 }`;
 assertErrorMessage(() => Function(source), SyntaxError, /./);
 
 source = `class C {
     #"hi";
 }`;
 assertErrorMessage(() => Function(source), SyntaxError, /./);
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -353,16 +353,17 @@ MSG_DEF(JSMSG_WHILE_AFTER_DO,          0
 MSG_DEF(JSMSG_YIELD_IN_PARAMETER,      0, JSEXN_SYNTAXERR, "yield expression can't be used in parameter")
 MSG_DEF(JSMSG_YIELD_OUTSIDE_GENERATOR, 0, JSEXN_SYNTAXERR, "yield expression is only valid in generators")
 MSG_DEF(JSMSG_BAD_COLUMN_NUMBER,       0, JSEXN_RANGEERR, "column number out of range")
 MSG_DEF(JSMSG_COMPUTED_NAME_IN_PATTERN,0, JSEXN_SYNTAXERR, "computed property names aren't supported in this destructuring declaration")
 MSG_DEF(JSMSG_DEFAULT_IN_PATTERN,      0, JSEXN_SYNTAXERR, "destructuring defaults aren't supported in this destructuring declaration")
 MSG_DEF(JSMSG_BAD_NEWTARGET,           0, JSEXN_SYNTAXERR, "new.target only allowed within functions")
 MSG_DEF(JSMSG_ESCAPED_KEYWORD,         0, JSEXN_SYNTAXERR, "keywords must be written literally, without embedded escapes")
 MSG_DEF(JSMSG_FIELDS_NOT_SUPPORTED,    0, JSEXN_SYNTAXERR, "fields are not currently supported")
+MSG_DEF(JSMSG_PRIVATE_FIELDS_NOT_SUPPORTED, 0, JSEXN_SYNTAXERR, "private fields are not currently supported")
 
 // UTF-8 source text encoding errors
 MSG_DEF(JSMSG_BAD_LEADING_UTF8_UNIT,   1, JSEXN_SYNTAXERR, "{0} byte doesn't begin a valid UTF-8 code point")
 MSG_DEF(JSMSG_NOT_ENOUGH_CODE_UNITS,   5, JSEXN_SYNTAXERR, "{0} byte in UTF-8 must be followed by {1} byte{2}, but {3} byte{4} present")
 MSG_DEF(JSMSG_BAD_TRAILING_UTF8_UNIT,  1, JSEXN_SYNTAXERR, "bad trailing UTF-8 byte {0} doesn't match the pattern 0b10xxxxxx")
 MSG_DEF(JSMSG_FORBIDDEN_UTF8_CODE_POINT,2,JSEXN_SYNTAXERR, "{0} isn't a valid code point because {1}")
 MSG_DEF(JSMSG_BAD_CODE_UNITS,          1, JSEXN_NOTE, "the code units comprising this invalid code point were: {0}")