Merge V8 5.2.361.47  DO NOT MERGE

https://chromium.googlesource.com/v8/v8/+/5.2.361.47

FPIIM-449

Change-Id: Ibec421b85a9b88cb3a432ada642e469fe7e78346
(cherry picked from commit bcf72ee8e3b26f1d0726869c7ddb3921c68b09a8)
diff --git a/src/regexp/regexp-parser.cc b/src/regexp/regexp-parser.cc
index d433fc8..abb644a 100644
--- a/src/regexp/regexp-parser.cc
+++ b/src/regexp/regexp-parser.cc
@@ -130,6 +130,7 @@
 
 
 RegExpTree* RegExpParser::ReportError(Vector<const char> message) {
+  if (failed_) return NULL;  // Do not overwrite any existing error.
   failed_ = true;
   *error_ = isolate()->factory()->NewStringFromAscii(message).ToHandleChecked();
   // Zip to the end to make sure the no more input is read.
@@ -511,9 +512,8 @@
         break;
       case '{': {
         int dummy;
-        if (ParseIntervalQuantifier(&dummy, &dummy)) {
-          return ReportError(CStrVector("Nothing to repeat"));
-        }
+        bool parsed = ParseIntervalQuantifier(&dummy, &dummy CHECK_FAILED);
+        if (parsed) return ReportError(CStrVector("Nothing to repeat"));
         // fallthrough
       }
       case '}':
@@ -845,29 +845,46 @@
 }
 
 #ifdef V8_I18N_SUPPORT
-bool IsExactPropertyValueAlias(const char* property_name, UProperty property,
-                               int32_t property_value) {
-  const char* short_name =
-      u_getPropertyValueName(property, property_value, U_SHORT_PROPERTY_NAME);
+bool IsExactPropertyAlias(const char* property_name, UProperty property) {
+  const char* short_name = u_getPropertyName(property, U_SHORT_PROPERTY_NAME);
   if (short_name != NULL && strcmp(property_name, short_name) == 0) return true;
   for (int i = 0;; i++) {
-    const char* long_name = u_getPropertyValueName(
-        property, property_value,
-        static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
+    const char* long_name = u_getPropertyName(
+        property, static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
     if (long_name == NULL) break;
     if (strcmp(property_name, long_name) == 0) return true;
   }
   return false;
 }
 
-bool LookupPropertyClass(UProperty property, const char* property_name,
-                         ZoneList<CharacterRange>* result, Zone* zone) {
-  int32_t property_value = u_getPropertyValueEnum(property, property_name);
+bool IsExactPropertyValueAlias(const char* property_value_name,
+                               UProperty property, int32_t property_value) {
+  const char* short_name =
+      u_getPropertyValueName(property, property_value, U_SHORT_PROPERTY_NAME);
+  if (short_name != NULL && strcmp(property_value_name, short_name) == 0) {
+    return true;
+  }
+  for (int i = 0;; i++) {
+    const char* long_name = u_getPropertyValueName(
+        property, property_value,
+        static_cast<UPropertyNameChoice>(U_LONG_PROPERTY_NAME + i));
+    if (long_name == NULL) break;
+    if (strcmp(property_value_name, long_name) == 0) return true;
+  }
+  return false;
+}
+
+bool LookupPropertyValueName(UProperty property,
+                             const char* property_value_name,
+                             ZoneList<CharacterRange>* result, Zone* zone) {
+  int32_t property_value =
+      u_getPropertyValueEnum(property, property_value_name);
   if (property_value == UCHAR_INVALID_CODE) return false;
 
   // We require the property name to match exactly to one of the property value
   // aliases. However, u_getPropertyValueEnum uses loose matching.
-  if (!IsExactPropertyValueAlias(property_name, property, property_value)) {
+  if (!IsExactPropertyValueAlias(property_value_name, property,
+                                 property_value)) {
     return false;
   }
 
@@ -892,49 +909,75 @@
   uset_close(set);
   return success;
 }
-#endif  // V8_I18N_SUPPORT
 
 bool RegExpParser::ParsePropertyClass(ZoneList<CharacterRange>* result) {
-#ifdef V8_I18N_SUPPORT
-  List<char> property_name_list;
+  // Parse the property class as follows:
+  // - \pN with a single-character N is equivalent to \p{N}
+  // - In \p{name}, 'name' is interpreted
+  //   - either as a general category property value name.
+  //   - or as a binary property name.
+  // - In \p{name=value}, 'name' is interpreted as an enumerated property name,
+  //   and 'value' is interpreted as one of the available property value names.
+  // - Aliases in PropertyAlias.txt and PropertyValueAlias.txt can be used.
+  // - Loose matching is not applied.
+  List<char> first_part;
+  List<char> second_part;
   if (current() == '{') {
-    for (Advance(); current() != '}'; Advance()) {
+    // Parse \p{[PropertyName=]PropertyNameValue}
+    for (Advance(); current() != '}' && current() != '='; Advance()) {
       if (!has_next()) return false;
-      property_name_list.Add(static_cast<char>(current()));
+      first_part.Add(static_cast<char>(current()));
+    }
+    if (current() == '=') {
+      for (Advance(); current() != '}'; Advance()) {
+        if (!has_next()) return false;
+        second_part.Add(static_cast<char>(current()));
+      }
+      second_part.Add(0);  // null-terminate string.
     }
   } else if (current() != kEndMarker) {
-    property_name_list.Add(static_cast<char>(current()));
+    // Parse \pN, where N is a single-character property name value.
+    first_part.Add(static_cast<char>(current()));
   } else {
     return false;
   }
   Advance();
-  property_name_list.Add(0);  // null-terminate string.
+  first_part.Add(0);  // null-terminate string.
 
-  const char* property_name = property_name_list.ToConstVector().start();
-
-#define PROPERTY_NAME_LOOKUP(PROPERTY)                                  \
-  do {                                                                  \
-    if (LookupPropertyClass(PROPERTY, property_name, result, zone())) { \
-      return true;                                                      \
-    }                                                                   \
-  } while (false)
-
-  // General_Category (gc) found in PropertyValueAliases.txt
-  PROPERTY_NAME_LOOKUP(UCHAR_GENERAL_CATEGORY_MASK);
-  // Script (sc) found in Scripts.txt
-  PROPERTY_NAME_LOOKUP(UCHAR_SCRIPT);
-  // To disambiguate from script names, block names have an "In"-prefix.
-  if (property_name_list.length() > 3 && property_name[0] == 'I' &&
-      property_name[1] == 'n') {
-    // Block (blk) found in Blocks.txt
-    property_name += 2;
-    PROPERTY_NAME_LOOKUP(UCHAR_BLOCK);
+  if (second_part.is_empty()) {
+    // First attempt to interpret as general category property value name.
+    const char* name = first_part.ToConstVector().start();
+    if (LookupPropertyValueName(UCHAR_GENERAL_CATEGORY_MASK, name, result,
+                                zone())) {
+      return true;
+    }
+    // Then attempt to interpret as binary property name with value name 'Y'.
+    UProperty property = u_getPropertyEnum(name);
+    if (property < UCHAR_BINARY_START) return false;
+    if (property >= UCHAR_BINARY_LIMIT) return false;
+    if (!IsExactPropertyAlias(name, property)) return false;
+    return LookupPropertyValueName(property, "Y", result, zone());
+  } else {
+    // Both property name and value name are specified. Attempt to interpret
+    // the property name as enumerated property.
+    const char* property_name = first_part.ToConstVector().start();
+    const char* value_name = second_part.ToConstVector().start();
+    UProperty property = u_getPropertyEnum(property_name);
+    if (property < UCHAR_INT_START) return false;
+    if (property >= UCHAR_INT_LIMIT) return false;
+    if (!IsExactPropertyAlias(property_name, property)) return false;
+    return LookupPropertyValueName(property, value_name, result, zone());
   }
-#undef PROPERTY_NAME_LOOKUP
-#endif  // V8_I18N_SUPPORT
+}
+
+#else  // V8_I18N_SUPPORT
+
+bool RegExpParser::ParsePropertyClass(ZoneList<CharacterRange>* result) {
   return false;
 }
 
+#endif  // V8_I18N_SUPPORT
+
 bool RegExpParser::ParseUnlimitedLengthHexNumber(int max_value, uc32* value) {
   uc32 x = 0;
   int d = HexValue(current());