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/test/intl/assert.js b/test/intl/assert.js
index 3180e6f..e176152 100644
--- a/test/intl/assert.js
+++ b/test/intl/assert.js
@@ -87,14 +87,13 @@
   return deepObjectEquals(a, b);
 }
 
-
 /**
- * Throws an exception, and prints the values in case of error.
+ * Throws an exception containing the user_message (if any) and the values.
  */
-function fail(expected, found) {
+function fail(expected, found, user_message = '') {
   // TODO(cira): Replace String with PrettyPrint for objects and arrays.
-  var message = 'Failure: expected <' + String(expected) + '>, found <' +
-      String(found) + '>.';
+  var message = 'Failure' + (user_message ? ' (' + user_message + ')' : '') +
+      ': expected <' + String(expected) + '>, found <' + String(found) + '>.';
   throw new Error(message);
 }
 
@@ -102,9 +101,9 @@
 /**
  * Throws if two variables have different types or values.
  */
-function assertEquals(expected, found) {
+function assertEquals(expected, found, user_message = '') {
   if (!deepEquals(expected, found)) {
-    fail(expected, found);
+    fail(expected, found, user_message);
   }
 }
 
@@ -112,49 +111,49 @@
 /**
  * Throws if value is false.
  */
-function assertTrue(value) {
-  assertEquals(true, value)
+function assertTrue(value, user_message = '') {
+  assertEquals(true, value, user_message);
 }
 
 
 /**
  * Throws if value is true.
  */
-function assertFalse(value) {
-  assertEquals(false, value);
+function assertFalse(value, user_message = '') {
+  assertEquals(false, value, user_message);
 }
 
 
 /**
- * Returns true if code throws specified exception.
+ * Runs code() and asserts that it throws the specified exception.
  */
 function assertThrows(code, type_opt, cause_opt) {
-  var threwException = true;
   try {
     if (typeof code == 'function') {
       code();
     } else {
       eval(code);
     }
-    threwException = false;
   } catch (e) {
     if (typeof type_opt == 'function') {
       assertInstanceof(e, type_opt);
     }
     if (arguments.length >= 3) {
-      assertEquals(e.type, cause_opt);
+      assertEquals(cause_opt, e.type, 'thrown exception type mismatch');
     }
     // Success.
     return;
   }
-  throw new Error("Did not throw exception");
+  var expected = arguments.length >= 3 ? cause_opt :
+      typeof type_opt == 'function' ? type_opt : 'any exception';
+  fail(expected, 'no exception', 'expected thrown exception');
 }
 
 
 /**
- * Throws an exception if code throws.
+ * Runs code() and asserts that it does now throw any exception.
  */
-function assertDoesNotThrow(code, name_opt) {
+function assertDoesNotThrow(code, user_message = '') {
   try {
     if (typeof code == 'function') {
       code();
@@ -162,7 +161,7 @@
       eval(code);
     }
   } catch (e) {
-    fail("threw an exception: ", e.message || e, name_opt);
+    fail("no expection", "exception: " + String(e), user_message);
   }
 }
 
diff --git a/test/intl/date-format/parse-MMMdy.js b/test/intl/date-format/parse-MMMdy.js
index b23a3cd..f713b36 100644
--- a/test/intl/date-format/parse-MMMdy.js
+++ b/test/intl/date-format/parse-MMMdy.js
@@ -28,6 +28,8 @@
 // Testing v8Parse method for date and time pattern.
 // Month is represented as a short name.
 
+// Flags: --intl-extra
+
 var dtf = new Intl.DateTimeFormat(['en'],
                                   {year: 'numeric', month: 'short',
                                    day: 'numeric',
diff --git a/test/intl/date-format/parse-invalid-input.js b/test/intl/date-format/parse-invalid-input.js
index ab0b889..47a9547 100644
--- a/test/intl/date-format/parse-invalid-input.js
+++ b/test/intl/date-format/parse-invalid-input.js
@@ -25,6 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Flags: --intl-extra
+
 // Invalid input is handled properly.
 
 var dtf = new Intl.DateTimeFormat(['en']);
diff --git a/test/intl/date-format/parse-mdy.js b/test/intl/date-format/parse-mdy.js
index 7b1a79a..a248a08 100644
--- a/test/intl/date-format/parse-mdy.js
+++ b/test/intl/date-format/parse-mdy.js
@@ -25,6 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Flags: --intl-extra
+
 // Testing v8Parse method for date only.
 
 function checkDate(date) {
diff --git a/test/intl/extra-flag.js b/test/intl/extra-flag.js
new file mode 100644
index 0000000..3d434a3
--- /dev/null
+++ b/test/intl/extra-flag.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --intl-extra
+
+// Turning on the creates the non-standard properties
+
+var dtf = new Intl.DateTimeFormat(['en']);
+assertTrue('v8Parse' in dtf);
+assertTrue('resolved' in dtf);
+assertTrue(!!dtf.resolved && 'pattern' in dtf.resolved);
+
+var nf = new Intl.NumberFormat(['en']);
+assertTrue('v8Parse' in nf);
+assertTrue('resolved' in nf);
+assertTrue(!!nf.resolved && 'pattern' in nf.resolved);
+
+var col = new Intl.Collator(['en']);
+assertTrue('resolved' in col);
+
+var br = new Intl.v8BreakIterator(['en']);
+assertTrue('resolved' in br);
diff --git a/test/intl/general/case-mapping.js b/test/intl/general/case-mapping.js
new file mode 100644
index 0000000..a73622b
--- /dev/null
+++ b/test/intl/general/case-mapping.js
@@ -0,0 +1,138 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --icu_case_mapping
+
+// Some edge cases that unibrow got wrong
+
+assertEquals("𐐘", "𐑀".toUpperCase());
+assertEquals("𐑀", "𐐘".toLowerCase());
+assertEquals("σ", "Σ".toLowerCase());
+
+// Some different paths in the ICU case conversion fastpath
+
+assertEquals("σς", "\u03A3\u03A3".toLowerCase());
+// Expand sharp s in latin1 fastpath
+assertEquals("ASSB", "A\u00DFB".toUpperCase());
+assertEquals("AB", "Ab".toUpperCase());
+// Find first upper case in fastpath
+assertEquals("ab", "aB".toLowerCase());
+assertEquals("AÜ", "aü".toUpperCase());
+assertEquals("AÜ", "AÜ".toUpperCase());
+assertEquals("aü", "aü".toLowerCase());
+assertEquals("aü", "AÜ".toLowerCase());
+assertEquals("aü", "AÜ".toLowerCase());
+
+// Starts with fastpath, but switches to full Unicode path
+// U+00FF is uppercased to U+0178.
+assertEquals("AŸ", "aÿ".toUpperCase());
+// U+00B5 (µ) is uppercased to U+039C (Μ)
+assertEquals("AΜ", "aµ".toUpperCase());
+
+// Buffer size increase
+assertEquals("CSSBẶ", "cßbặ".toUpperCase());
+assertEquals("FIFLFFIFFL", "\uFB01\uFB02\uFB03\uFB04".toUpperCase());
+// OneByte input with buffer size increase: non-fast path
+assertEquals("ABCSS", "abCß".toLocaleUpperCase("tr"));
+
+// More comprehensive tests for "tr", "az" and "lt" are in
+// test262/intl402/Strings/*
+
+// Buffer size decrease with a single locale or locale list.
+// In Turkic (tr, az), U+0307 preceeded by Capital Letter I is dropped.
+assertEquals("abci", "aBcI\u0307".toLocaleLowerCase("tr"));
+assertEquals("abci", "aBcI\u0307".toLocaleLowerCase("az"));
+assertEquals("abci", "aBcI\u0307".toLocaleLowerCase(["tr", "en"]));
+
+// Cons string
+assertEquals("abcijkl", ("aBcI" + "\u0307jkl").toLocaleLowerCase("tr"));
+assertEquals("abcijkl",
+             ("aB" + "cI" + "\u0307j" + "kl").toLocaleLowerCase("tr"));
+assertEquals("abci\u0307jkl", ("aBcI" + "\u0307jkl").toLocaleLowerCase("en"));
+assertEquals("abci\u0307jkl",
+             ("aB" + "cI" + "\u0307j" + "kl").toLocaleLowerCase("en"));
+assertEquals("abci\u0307jkl", ("aBcI" + "\u0307jkl").toLowerCase());
+assertEquals("abci\u0307jkl",
+             ("aB" + "cI" + "\u0307j" + "kl").toLowerCase());
+
+// "tr" and "az" should behave identically.
+assertEquals("aBcI\u0307".toLocaleLowerCase("tr"),
+             "aBcI\u0307".toLocaleLowerCase("az"));
+// What matters is the first locale in the locale list.
+assertEquals("aBcI\u0307".toLocaleLowerCase(["tr", "en", "fr"]),
+             "aBcI\u0307".toLocaleLowerCase("tr"));
+assertEquals("aBcI\u0307".toLocaleLowerCase(["en", "tr", "az"]),
+             "aBcI\u0307".toLocaleLowerCase("en"));
+assertEquals("aBcI\u0307".toLocaleLowerCase(["en", "tr", "az"]),
+             "aBcI\u0307".toLowerCase());
+
+// An empty locale list is the same as the default locale. Try these tests
+// under Turkish and Greek locale.
+assertEquals("aBcI\u0307".toLocaleLowerCase([]),
+             "aBcI\u0307".toLocaleLowerCase());
+assertEquals("aBcI\u0307".toLocaleLowerCase([]),
+             "aBcI\u0307".toLocaleLowerCase(Intl.GetDefaultLocale));
+assertEquals("άόύώ".toLocaleUpperCase([]), "άόύώ".toLocaleUpperCase());
+assertEquals("άόύώ".toLocaleUpperCase([]),
+             "άόύώ".toLocaleUpperCase(Intl.GetDefaultLocale));
+
+
+// English/root locale keeps U+0307 (combining dot above).
+assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase("en"));
+assertEquals("abci\u0307", "aBcI\u0307".toLocaleLowerCase(["en", "tr"]));
+assertEquals("abci\u0307", "aBcI\u0307".toLowerCase());
+
+// Greek uppercasing: not covered by intl402/String/*, yet. Tonos (U+0301) and
+// other diacritic marks are dropped. This rule is based on the current CLDR's
+// el-Upper transformation, but Greek uppercasing rules are more sophisticated
+// than this. See http://bugs.icu-project.org/trac/ticket/10582 and
+// http://unicode.org/cldr/trac/ticket/7905 .
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el"));
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el-GR"));
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el-Grek"));
+assertEquals("Α", "α\u0301".toLocaleUpperCase("el-Grek-GR"));
+assertEquals("Α", "ά".toLocaleUpperCase("el"));
+assertEquals("ΑΟΥΩ", "άόύώ".toLocaleUpperCase("el"));
+assertEquals("ΑΟΥΩ", "α\u0301ο\u0301υ\u0301ω\u0301".toLocaleUpperCase("el"));
+assertEquals("ΑΟΥΩ", "άόύώ".toLocaleUpperCase("el"));
+assertEquals("ΟΕ", "Ό\u1f15".toLocaleUpperCase("el"));
+assertEquals("ΟΕ", "Ο\u0301ε\u0314\u0301".toLocaleUpperCase("el"));
+
+// Input and output are identical.
+assertEquals("αβγδε", "αβγδε".toLocaleLowerCase("el"));
+assertEquals("ΑΒΓΔΕ", "ΑΒΓΔΕ".toLocaleUpperCase("el"));
+assertEquals("ΑΒΓΔΕАБ𝐀𝐁", "ΑΒΓΔΕАБ𝐀𝐁".toLocaleUpperCase("el"));
+assertEquals("ABCDEÂÓḴ123", "ABCDEÂÓḴ123".toLocaleUpperCase("el"));
+// ASCII-only or Latin-1 only: 1-byte
+assertEquals("ABCDE123", "ABCDE123".toLocaleUpperCase("el"));
+assertEquals("ABCDEÂÓ123", "ABCDEÂÓ123".toLocaleUpperCase("el"));
+
+// To make sure that the input string is not overwritten in place.
+var strings = ["abCdef", "αβγδε", "άόύώ", "аб"];
+for (var s  of strings) {
+  var backupAsArray = s.split("");
+  var uppered = s.toLocaleUpperCase("el");
+  assertEquals(s, backupAsArray.join(""));
+}
+
+// In other locales, U+0301 is preserved.
+assertEquals("Α\u0301Ο\u0301Υ\u0301Ω\u0301",
+             "α\u0301ο\u0301υ\u0301ω\u0301".toLocaleUpperCase("en"));
+assertEquals("Α\u0301Ο\u0301Υ\u0301Ω\u0301",
+             "α\u0301ο\u0301υ\u0301ω\u0301".toUpperCase());
+
+// Plane 1; Deseret and Warang Citi Script.
+assertEquals("\u{10400}\u{118A0}", "\u{10428}\u{118C0}".toUpperCase());
+assertEquals("\u{10428}\u{118C0}", "\u{10400}\u{118A0}".toLowerCase());
+// Mathematical Bold {Capital, Small} Letter A do not change.
+assertEquals("\u{1D400}\u{1D41A}", "\u{1D400}\u{1D41A}".toUpperCase());
+assertEquals("\u{1D400}\u{1D41A}", "\u{1D400}\u{1D41A}".toLowerCase());
+// Plane 1; New characters in Unicode 8.0
+assertEquals("\u{10C80}", "\u{10CC0}".toUpperCase());
+assertEquals("\u{10CC0}", "\u{10C80}".toLowerCase());
+assertEquals("\u{10C80}", "\u{10CC0}".toLocaleUpperCase());
+assertEquals("\u{10CC0}", "\u{10C80}".toLocaleLowerCase());
+assertEquals("\u{10C80}", "\u{10CC0}".toLocaleUpperCase(["tr"]));
+assertEquals("\u{10C80}", "\u{10CC0}".toLocaleUpperCase(["tr"]));
+assertEquals("\u{10CC0}", "\u{10C80}".toLocaleLowerCase());
diff --git a/test/intl/intl.gyp b/test/intl/intl.gyp
index 8fa7f06..f2e107f 100644
--- a/test/intl/intl.gyp
+++ b/test/intl/intl.gyp
@@ -13,8 +13,8 @@
             '../../src/d8.gyp:d8_run',
           ],
           'includes': [
-            '../../build/features.gypi',
-            '../../build/isolate.gypi',
+            '../../gypfiles/features.gypi',
+            '../../gypfiles/isolate.gypi',
           ],
           'sources': [
             'intl.isolate',
diff --git a/test/intl/intl.status b/test/intl/intl.status
index e890085..02ee26b 100644
--- a/test/intl/intl.status
+++ b/test/intl/intl.status
@@ -37,21 +37,9 @@
   'number-format/parse-percent': [FAIL],
 }],  # ALWAYS
 
-##############################################################################
-['system == linux', {
-  # BUG(v8:2899).
-  'collator/default-locale': [PASS, FAIL],
-}],  # 'system == linux'
-
-##############################################################################
-['system == macos', {
-  # BUG(v8:4459).
-  'collator/default-locale': [FAIL],
-}],  # 'system == macos'
-
-##############################################################################
-['arch == arm or arch == arm64', {
-  # BUG(v8:4459).
-  'collator/default-locale': [PASS, FAIL],
-}],  # 'arch == arm or arch == arm64'
+['arch == arm64 and mode == debug and simulator_run == True', {
+  # Ignition.
+  'date-format/timezone': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+  'number-format/check-digit-ranges': [PASS, ['no_snap and mode == debug', NO_IGNITION]],
+}],  # 'arch == arm64 and mode == debug and simulator_run == True'
 ]
diff --git a/test/intl/no-extra-flag.js b/test/intl/no-extra-flag.js
new file mode 100644
index 0000000..6735f84
--- /dev/null
+++ b/test/intl/no-extra-flag.js
@@ -0,0 +1,23 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Flags: --no-intl-extra
+
+// Turning off the flag removes the non-standard properties
+
+var dtf = new Intl.DateTimeFormat(['en']);
+assertFalse('v8Parse' in dtf);
+assertFalse('resolved' in dtf);
+assertFalse(!!dtf.resolved && 'pattern' in dtf.resolved);
+
+var nf = new Intl.NumberFormat(['en']);
+assertFalse('v8Parse' in nf);
+assertFalse('resolved' in nf);
+assertFalse(!!nf.resolved && 'pattern' in nf.resolved);
+
+var col = new Intl.Collator(['en']);
+assertFalse('resolved' in col);
+
+var br = new Intl.v8BreakIterator(['en']);
+assertFalse('resolved' in br);
diff --git a/test/intl/number-format/format-is-bound.js b/test/intl/number-format/format-is-bound.js
index d93ee00..edb6a4b 100644
--- a/test/intl/number-format/format-is-bound.js
+++ b/test/intl/number-format/format-is-bound.js
@@ -28,6 +28,8 @@
 // Create default NumberFormat.
 var nf = new Intl.NumberFormat();
 
+var beforeCount = Object.getOwnPropertyNames(nf).length;
+
 // Array we want to iterate, actual numbers are not important.
 var numberArray = [1, 2, 3];
 
@@ -39,4 +41,4 @@
 nf.format(12345);
 
 // Reading the format doesn't add any additional property keys
-assertEquals(1, Object.getOwnPropertyNames(nf).length);
+assertEquals(beforeCount, Object.getOwnPropertyNames(nf).length);
diff --git a/test/intl/number-format/parse-currency.js b/test/intl/number-format/parse-currency.js
index c87ffea..a57128e 100644
--- a/test/intl/number-format/parse-currency.js
+++ b/test/intl/number-format/parse-currency.js
@@ -28,6 +28,8 @@
 // Currency parsing is not yet supported. We need ICU49 or higher to get
 // it working.
 
+// Flags: --intl-extra
+
 var nf = new Intl.NumberFormat(['en'], {style: 'currency', currency: 'USD'});
 
 assertEquals(undefined, nf.v8Parse('USD 123.43'));
diff --git a/test/intl/number-format/parse-invalid-input.js b/test/intl/number-format/parse-invalid-input.js
index 8c84d0b..251b52a 100644
--- a/test/intl/number-format/parse-invalid-input.js
+++ b/test/intl/number-format/parse-invalid-input.js
@@ -25,6 +25,8 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
+// Flags: --intl-extra
+
 // Invalid input is handled properly.
 
 var nf = new Intl.NumberFormat(['en']);
diff --git a/test/intl/regress-4870.js b/test/intl/regress-4870.js
new file mode 100644
index 0000000..72c095e
--- /dev/null
+++ b/test/intl/regress-4870.js
@@ -0,0 +1,8 @@
+// Copyright 2016 the V8 project authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+assertThrows(() =>
+    Object.getOwnPropertyDescriptor(Intl.Collator.prototype, 'compare')
+      .get.call(new Intl.DateTimeFormat())('a', 'b'),
+    TypeError);
diff --git a/test/intl/testcfg.py b/test/intl/testcfg.py
index 6e4b4f1..c7f17bb 100644
--- a/test/intl/testcfg.py
+++ b/test/intl/testcfg.py
@@ -26,10 +26,12 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import os
+import re
 
 from testrunner.local import testsuite
 from testrunner.objects import testcase
 
+FLAGS_PATTERN = re.compile(r"//\s+Flags:(.*)")
 
 class IntlTestSuite(testsuite.TestSuite):
 
@@ -55,7 +57,11 @@
     return tests
 
   def GetFlagsForTestCase(self, testcase, context):
+    source = self.GetSourceForTest(testcase)
     flags = ["--allow-natives-syntax"] + context.mode_flags
+    flags_match = re.findall(FLAGS_PATTERN, source)
+    for match in flags_match:
+      flags += match.strip().split()
 
     files = []
     files.append(os.path.join(self.root, "assert.js"))
@@ -71,6 +77,10 @@
 
     return testcase.flags + flags
 
+  def GetSourceForTest(self, testcase):
+    filename = os.path.join(self.root, testcase.path + self.suffix())
+    with open(filename) as f:
+      return f.read()
 
 def GetSuite(name, root):
   return IntlTestSuite(name, root)