summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/latin1
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /js/src/jit-test/tests/latin1
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'js/src/jit-test/tests/latin1')
-rw-r--r--js/src/jit-test/tests/latin1/assorted.js39
-rw-r--r--js/src/jit-test/tests/latin1/basic.js113
-rw-r--r--js/src/jit-test/tests/latin1/bug1033113.js20
-rw-r--r--js/src/jit-test/tests/latin1/compare.js20
-rw-r--r--js/src/jit-test/tests/latin1/date.js29
-rw-r--r--js/src/jit-test/tests/latin1/decompiler.js20
-rw-r--r--js/src/jit-test/tests/latin1/dependent.js92
-rw-r--r--js/src/jit-test/tests/latin1/encode-decode.js57
-rw-r--r--js/src/jit-test/tests/latin1/escape-unescape.js24
-rw-r--r--js/src/jit-test/tests/latin1/eval.js10
-rw-r--r--js/src/jit-test/tests/latin1/function.js16
-rw-r--r--js/src/jit-test/tests/latin1/index.js26
-rw-r--r--js/src/jit-test/tests/latin1/indexOf.js155
-rw-r--r--js/src/jit-test/tests/latin1/indexing.js47
-rw-r--r--js/src/jit-test/tests/latin1/join.js24
-rw-r--r--js/src/jit-test/tests/latin1/json.js75
-rw-r--r--js/src/jit-test/tests/latin1/latin1.js120
-rw-r--r--js/src/jit-test/tests/latin1/other.js34
-rw-r--r--js/src/jit-test/tests/latin1/parseInt-parseFloat.js43
-rw-r--r--js/src/jit-test/tests/latin1/regexp.js47
-rw-r--r--js/src/jit-test/tests/latin1/replace.js145
-rw-r--r--js/src/jit-test/tests/latin1/rope-stringchar.js16
-rw-r--r--js/src/jit-test/tests/latin1/search.js79
-rw-r--r--js/src/jit-test/tests/latin1/split.js27
-rw-r--r--js/src/jit-test/tests/latin1/startsWith-endsWith.js69
-rw-r--r--js/src/jit-test/tests/latin1/structured-clone.js19
-rw-r--r--js/src/jit-test/tests/latin1/toLowerCase-toUpperCase.js57
-rw-r--r--js/src/jit-test/tests/latin1/toNumber.js28
-rw-r--r--js/src/jit-test/tests/latin1/trim.js28
29 files changed, 1479 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/latin1/assorted.js b/js/src/jit-test/tests/latin1/assorted.js
new file mode 100644
index 0000000000..5d6da13030
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/assorted.js
@@ -0,0 +1,39 @@
+// Reflect.parse Latin1
+var ast = Reflect.parse("function f() { return 3; }");
+assertEq(ast.body[0].id.name, "f");
+assertEq(isLatin1(ast.body[0].id.name), true);
+
+// Reflect.parse TwoByte
+var ast = Reflect.parse("function f\u1200() { return 3; }");
+assertEq(ast.body[0].id.name, "f\u1200");
+
+if (Object.prototype.toSource) {
+ // obj.toSource Latin1
+ var o = {};
+ Object.defineProperty(o, "prop", {get: function() { return 1; },
+ set: function() { return 2; },
+ enumerable: true, configurable: true});
+ assertEq(o.toSource(), "({get prop() { return 1; }, set prop() { return 2; }})");
+
+ // obj.toSource TwoByte
+ Object.defineProperty(o, "prop", {get: function() { return "\u1200"; },
+ set: function() { return "\u1200"; },
+ enumerable: true});
+ assertEq(o.toSource(), '({get prop() { return "\\u1200"; }, set prop() { return "\\u1200"; }})');
+
+ var ff = function() { return 10; };
+ ff.toSource = function() { return "((11))"; }
+ Object.defineProperty(o, "prop", {get: ff, set: ff, enumerable: true});
+ assertEq(o.toSource(), "({get prop(11), set prop(11)})");
+}
+
+// XDR
+load(libdir + 'bytecode-cache.js');
+
+// Latin1 string constant
+test = "'string123';";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
+
+// TwoByte string constant
+test = "'string\u1234';";
+evalWithCache(test, { assertEqBytecode: true, assertEqResult : true });
diff --git a/js/src/jit-test/tests/latin1/basic.js b/js/src/jit-test/tests/latin1/basic.js
new file mode 100644
index 0000000000..a11a6cf65d
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/basic.js
@@ -0,0 +1,113 @@
+assertEq(isLatin1("Foo123\u1200"), false);
+
+s = "Foo123";
+assertEq(isLatin1(s), true);
+
+function testEq(s) {
+ assertEq(isLatin1(s), true);
+ assertEq(s === "foo02", false);
+ assertEq(s == "foo02", false);
+
+ // Non-atomized to force char comparison.
+ var nonAtomized = "\u1234foo01\u00c7".substr(1);
+ assertEq(isLatin1(nonAtomized), false);
+ assertEq(s === nonAtomized, true);
+ assertEq(nonAtomized !== s, false);
+ assertEq(nonAtomized == s, true);
+ assertEq(s, nonAtomized);
+
+ nonAtomized = "\u1234foo02".substr(1);
+ assertEq(isLatin1(nonAtomized), false);
+ assertEq(s === nonAtomized, false);
+ assertEq(nonAtomized == s, false);
+}
+
+s = "foo01\u00c7";
+testEq(s);
+testEq(s);
+
+function testConcat() {
+ function concat(s1, s2) {
+ return s1 + s2;
+ }
+
+ // Following tests create fat inline strings.
+ assertEq(concat("abc", "def"), "abcdef");
+ var s1 = "ABC";
+ var s2 = "DEF";
+ assertEq(concat(s1, s2), "ABCDEF");
+ assertEq(concat(s1, "GHI\u0580"), "ABCGHI\u0580");
+ assertEq(concat("GHI\u0580", s2), "GHI\u0580DEF");
+ assertEq(concat(concat("GHI\u0580", s2), s1), "GHI\u0580DEFABC");
+ assertEq(isLatin1(s1), true);
+ assertEq(isLatin1(s2), true);
+
+ // Create a Latin1 rope.
+ var s3 = "0123456789012345678901234567890123456789";
+ var rope = concat(s1, s3);
+ assertEq(isLatin1(rope), true);
+ assertEq(rope, "ABC0123456789012345678901234567890123456789");
+ assertEq(isLatin1(rope), true); // Still Latin1 after flattening.
+
+ // Latin1 + TwoByte => TwoByte rope.
+ assertEq(isLatin1(s3), true);
+ rope = concat(s3, "someTwoByteString\u0580");
+ assertEq(isLatin1(rope), false);
+ assertEq(rope, "0123456789012345678901234567890123456789someTwoByteString\u0580");
+ assertEq(isLatin1(rope), false);
+
+ assertEq(isLatin1(s3), true);
+ rope = concat("twoByteString\u0580", concat(s3, "otherTwoByte\u0580"));
+ assertEq(isLatin1(rope), false);
+ assertEq(rope, "twoByteString\u05800123456789012345678901234567890123456789otherTwoByte\u0580");
+ assertEq(isLatin1(rope), false);
+
+ // Build a Latin1 rope with left-most string an extensible string.
+ var s4 = "adsfasdfjkasdfkjasdfasasdfasdf";
+ for (var i=0; i<5; i++) {
+ s4 = concat(s4, s1);
+ assertEq(s4 === ".".repeat(s4.length), false); // Flatten rope.
+ }
+
+ assertEq(isLatin1(s4), true);
+
+ // Appending a TwoByte string must inflate.
+ s4 = concat(s4, "--\u0580");
+ assertEq(s4, "adsfasdfjkasdfkjasdfasasdfasdfABCABCABCABCABC--\u0580");
+}
+testConcat();
+
+function testFlattenDependent() {
+ function concat(s1, s2) {
+ return s1 + s2;
+ }
+
+ // Create some latin1 strings.
+ var s1 = "Foo0123456789bar012345---";
+ var s2 = "Foo0123456789bar012345+++";
+ assertEq(isLatin1(s1), true);
+ assertEq(isLatin1(s2), true);
+
+ // And some ropes.
+ var rope1 = concat(s1, s1);
+ assertEq(isLatin1(rope1), true);
+
+ var rope2 = concat(rope1, s2);
+ assertEq(isLatin1(rope2), true);
+
+ var rope3 = concat("twoByte\u0581", rope2);
+ assertEq(isLatin1(rope3), false);
+
+ // Flatten everything.
+ assertEq(rope3, "twoByte\u0581Foo0123456789bar012345---Foo0123456789bar012345---Foo0123456789bar012345+++");
+ assertEq(isLatin1(rope3), false);
+
+ // rope1 and rope2 were Latin1, but flattening rope3 turned them into
+ // dependent strings, so rope1 and rope2 must also be TwoByte now.
+ assertEq(isLatin1(rope1), false);
+ assertEq(isLatin1(rope2), false);
+
+ assertEq(rope1, "Foo0123456789bar012345---Foo0123456789bar012345---");
+ assertEq(rope2, "Foo0123456789bar012345---Foo0123456789bar012345---Foo0123456789bar012345+++");
+}
+testFlattenDependent();
diff --git a/js/src/jit-test/tests/latin1/bug1033113.js b/js/src/jit-test/tests/latin1/bug1033113.js
new file mode 100644
index 0000000000..74f1ff53f2
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/bug1033113.js
@@ -0,0 +1,20 @@
+var s = "aaaaaaaaaaaaaaaaaa111aaaa";
+var latin1Rope1 = "foo" + s;
+var latin1Rope2 = "bar" + latin1Rope1;
+var twoByteRope = "\u1200--" + latin1Rope1;
+
+// Flatten twoByteRope.
+assertEq(twoByteRope.lastIndexOf("11"), 25);
+
+// latin1Rope1 is now a TwoByte dependent string.
+assertEq(isLatin1(latin1Rope1), false);
+assertEq(latin1Rope1, "fooaaaaaaaaaaaaaaaaaa111aaaa");
+
+// latin1Rope2 should still be Latin1, but now has a
+// TwoByte descendent (latin1Rope1).
+if (isLatin1(s))
+ assertEq(isLatin1(latin1Rope2), true);
+
+// Flatten latin1Rope2.
+assertEq(latin1Rope2.lastIndexOf("11"), 25);
+assertEq(latin1Rope2, "barfooaaaaaaaaaaaaaaaaaa111aaaa");
diff --git a/js/src/jit-test/tests/latin1/compare.js b/js/src/jit-test/tests/latin1/compare.js
new file mode 100644
index 0000000000..636802b16c
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/compare.js
@@ -0,0 +1,20 @@
+function test() {
+ var arr = [
+ "abc",
+ "abcd",
+ "123\u00ff"
+ ];
+ for (var i = 0; i < arr.length; i++) {
+ for (var j = 0; j < arr.length; j++) {
+ var s1 = arr[i];
+ var s2 = arr[j];
+ var s1tb = "\u1200" + s1;
+ var s2tb = "\u1200" + s2;
+ assertEq(s1 < s2, s1tb < s2tb);
+ assertEq(s1 > s2, s1tb > s2tb);
+ assertEq(s1 <= s2, s1tb <= s2tb);
+ assertEq(s1 >= s2, s1tb >= s2tb);
+ }
+ }
+}
+test();
diff --git a/js/src/jit-test/tests/latin1/date.js b/js/src/jit-test/tests/latin1/date.js
new file mode 100644
index 0000000000..edf0221f93
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/date.js
@@ -0,0 +1,29 @@
+function test(lat1) {
+ assertEq(isLatin1(lat1), true);
+
+ var twoByte = "\u1200" + lat1;
+ twoByte.indexOf("X"); // Flatten.
+ twoByte = twoByte.substr(1);
+
+ assertEq(isLatin1(lat1), true);
+ assertEq(isLatin1(twoByte), false);
+
+ assertEq(Date.parse(lat1), Date.parse(twoByte));
+}
+
+// ISO format
+test("2014-06-06");
+test("2014-06-06T08:30+01:00");
+test("T11:59Z");
+
+// Non-ISO format
+test("06 Jun 2014, 17:20:36");
+test("6 Jun 2014");
+test("Wed Nov 05 21:49:11 GMT-0800 1997");
+test("Jan 30 2014 2:30 PM");
+
+// Invalid
+test("06 Aaa 2014, 17:20:36");
+test("6 Jun 10");
+test("2014-13-06");
+test("2014-06-06T08:30+99:00");
diff --git a/js/src/jit-test/tests/latin1/decompiler.js b/js/src/jit-test/tests/latin1/decompiler.js
new file mode 100644
index 0000000000..35f07847ed
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/decompiler.js
@@ -0,0 +1,20 @@
+// Latin1
+function f(someName) {
+ someName();
+}
+try {
+ f(3);
+} catch(e) {
+ assertEq(e.message.includes("someName"), true);
+}
+
+// TwoByte
+function g(someName\u1200) {
+ someName\u1200();
+}
+try {
+ g(3);
+} catch(e) {
+ // Note: string is deflated; don't check for the \u1200.
+ assertEq(e.message.includes("someName"), true);
+}
diff --git a/js/src/jit-test/tests/latin1/dependent.js b/js/src/jit-test/tests/latin1/dependent.js
new file mode 100644
index 0000000000..f92bc9dc1c
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/dependent.js
@@ -0,0 +1,92 @@
+function testSubstrLatin1() {
+ var s1 = "abcdefghijklmnopqrstuvwxyz12345678900000a";
+
+ // Static strings.
+ assertEq(s1.substr(s1.length - 1), "a");
+ assertEq(s1.substr(s1.length - 2), "0a");
+ assertEq(s1.substr(26, 3), "123");
+
+ // (Fat) inline strings.
+ var s2 = s1.substr(3, 5);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "defgh");
+ s2 = s1.substr(0, 20);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "abcdefghijklmnopqrst");
+
+ // Dependent string.
+ s2 = s1.substr(1, s1.length - 2);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2.length, 39);
+ assertEq(s2, "bcdefghijklmnopqrstuvwxyz12345678900000");
+
+ s2 = s2.substr(2).substr(1);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "efghijklmnopqrstuvwxyz12345678900000");
+}
+testSubstrLatin1();
+
+function testSubstrTwoByte() {
+ // Two byte string.
+ var s1 = "abcdefghijklmnopqrstuvwxyz12345678900000a\u1480";
+ assertEq(isLatin1(s1), false);
+
+ // Static string.
+ var s2 = s1.substr(28, 1);
+ assertEq(s2, "3");
+
+ // Inline string.
+ s2 = s1.substr(3, 5);
+ assertEq(s2, "defgh");
+
+ // Dependent string.
+ s2 = s1.substr(2);
+ assertEq(isLatin1(s2), false);
+ assertEq(s2, "cdefghijklmnopqrstuvwxyz12345678900000a\u1480");
+
+ s2 = s2.substr(2).substr(1);
+ assertEq(isLatin1(s2), false);
+ assertEq(s2, "fghijklmnopqrstuvwxyz12345678900000a\u1480");
+}
+testSubstrTwoByte();
+
+function testSubstring() {
+ var s1 = "abcdefghijklmnopqrstuvwxyz123456789000ab";
+ var s2 = s1.substring(1, 8);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "bcdefgh");
+ s2 = s1.substring(0, s1.length - 1);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "abcdefghijklmnopqrstuvwxyz123456789000a");
+}
+testSubstring();
+
+function testSlice() {
+ var s1 = "abcdefghijklmnopqrstuvwxyz123456789000ABC";
+ var s2 = s1.slice(1, 8);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "bcdefgh");
+ s2 = s1.slice(0, -2);
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "abcdefghijklmnopqrstuvwxyz123456789000A");
+}
+testSlice();
+
+function testUndepend() {
+ // Latin1
+ var s = "abcdefg".repeat(7);
+ s.indexOf("def"); // flatten
+ assertEq(isLatin1(s), true);
+
+ var dep = s.substr(7);
+ var res = dep.replace(/abcdef/g, ""); // StrReplaceRegexpRemove undepends.
+ assertEq(res, "gggggg");
+
+ // TwoByte
+ var s = "abcdefg\u1200".repeat(6);
+ s.indexOf("def"); // flatten
+ var dep = s.substr(8);
+ var res = dep.replace(/abcdefg/g, ""); // StrReplaceRegexpRemove undepends.
+ assertEq(res, "\u1200\u1200\u1200\u1200\u1200");
+}
+testUndepend();
diff --git a/js/src/jit-test/tests/latin1/encode-decode.js b/js/src/jit-test/tests/latin1/encode-decode.js
new file mode 100644
index 0000000000..cb6869654f
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/encode-decode.js
@@ -0,0 +1,57 @@
+// Latin1
+s = "a%2b%20def%00A0";
+
+res = decodeURI(s);
+assertEq(res, "a%2b def\x00A0");
+assertEq(isLatin1(res), true);
+
+res = decodeURIComponent(s);
+assertEq(res, "a+ def\x00A0");
+assertEq(isLatin1(res), true);
+
+// TwoByte
+s += "\u1200";
+assertEq(decodeURI(s), "a%2b def\x00A0\u1200");
+assertEq(decodeURIComponent(s), "a+ def\x00A0\u1200");
+
+// Latin1 malformed
+try {
+ decodeURI("abc%80");
+ assertEq(0, 1);
+} catch(e) {
+ assertEq(e instanceof URIError, true);
+}
+
+// TwoByte malformed
+try {
+ decodeURI("abc%80\u1200");
+ assertEq(0, 1);
+} catch(e) {
+ assertEq(e instanceof URIError, true);
+}
+
+// Latin1
+res = encodeURI("a%2b def\x00A0");
+assertEq(res, "a%252b%20def%00A0");
+assertEq(isLatin1(res), true);
+
+res = encodeURIComponent("a+ def\x00A0");
+assertEq(res, "a%2B%20def%00A0");
+assertEq(isLatin1(res), true);
+
+// TwoByte
+res = encodeURI("a%2b def\x00A0\u1200");
+assertEq(res, "a%252b%20def%00A0%E1%88%80");
+assertEq(isLatin1(res), true);
+
+res = encodeURIComponent("a+ def\x00A0\u1200");
+assertEq(res, "a%2B%20def%00A0%E1%88%80");
+assertEq(isLatin1(res), true);
+
+// TwoByte malformed
+try {
+ encodeURI("a\uDB00");
+ assertEq(0, 1);
+} catch(e) {
+ assertEq(e instanceof URIError, true);
+}
diff --git a/js/src/jit-test/tests/latin1/escape-unescape.js b/js/src/jit-test/tests/latin1/escape-unescape.js
new file mode 100644
index 0000000000..9cab2ddbbb
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/escape-unescape.js
@@ -0,0 +1,24 @@
+// Latin1
+s = "a%2b%20def%00A0";
+res = unescape(s);
+assertEq(res, "a+ def\x00A0");
+assertEq(isLatin1(res), true);
+
+s = "a%2b%20def%00A0%u1200";
+assertEq(unescape(s), "a+ def\x00A0\u1200");
+
+// TwoByte
+s += "\u1200";
+assertEq(unescape(s), "a+ def\x00A0\u1200\u1200");
+
+// Latin1
+s = "abc \u00ff";
+res = escape(s);
+assertEq(res, "abc%20%FF");
+assertEq(isLatin1(res), true);
+
+// TwoByte
+s += "\u1200";
+res = escape(s);
+assertEq(res, "abc%20%FF%u1200");
+assertEq(isLatin1(res), true);
diff --git a/js/src/jit-test/tests/latin1/eval.js b/js/src/jit-test/tests/latin1/eval.js
new file mode 100644
index 0000000000..8b13018d07
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/eval.js
@@ -0,0 +1,10 @@
+function f(s) {
+ var x = 3, y = 5;
+ var z = eval(s);
+ assertEq(z, 8);
+}
+var s = "x + y";
+f(s); // Latin1
+f(s);
+f("x + y;/*\u1200*/"); // TwoByte
+f("x + y;/*\u1200*/");
diff --git a/js/src/jit-test/tests/latin1/function.js b/js/src/jit-test/tests/latin1/function.js
new file mode 100644
index 0000000000..37c74fefbc
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/function.js
@@ -0,0 +1,16 @@
+function test() {
+ var arg1TwoByte = "arg1\u1200";
+ var arg2Latin1 = "arg2";
+
+ var bodyLatin1 = "return arg2 * 3";
+
+ var f = Function(arg1TwoByte, arg2Latin1, bodyLatin1);
+ assertEq(f(10, 20), 60);
+ assertEq(f.toString().includes("arg1\u1200,arg2"), true);
+
+ var bodyTwoByte = "return arg1\u1200 + arg2;";
+ f = Function(arg1TwoByte, arg2Latin1, bodyTwoByte);
+ assertEq(f(30, 40), 70);
+ assertEq(f.toString().includes("arg1\u1200,arg2"), true);
+}
+test();
diff --git a/js/src/jit-test/tests/latin1/index.js b/js/src/jit-test/tests/latin1/index.js
new file mode 100644
index 0000000000..4a8a930280
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/index.js
@@ -0,0 +1,26 @@
+function test() {
+ var arr = new Int8Array(400);
+ var idx = "384";
+
+ arr[idx] = 9;
+ assertEq(arr[idx], 9);
+ arr[idx] = 10;
+ assertEq(arr[384], 10);
+
+ idx = "512";
+ assertEq(arr[idx], undefined);
+ assertEq(arr[(() => "byteLength")()], 400);
+
+ var o = {};
+ Object.defineProperty(o, idx, {value: 123});
+ assertEq(o[512], 123);
+
+ var propLatin1 = "foobar";
+ o[propLatin1] = 3;
+ assertEq(o.foobar, 3);
+
+ var propTwoByte = "foobar\u1200";
+ o[propTwoByte] = 4;
+ assertEq(o.foobar\u1200, 4);
+}
+test();
diff --git a/js/src/jit-test/tests/latin1/indexOf.js b/js/src/jit-test/tests/latin1/indexOf.js
new file mode 100644
index 0000000000..9857f4a7fc
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/indexOf.js
@@ -0,0 +1,155 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+function testLastIndexOf() {
+ var s1 = toLatin1("abcdefgh123456\u0081defg");
+ var s2 = toLatin1("456\u0081de");
+
+ // Latin1 + Latin1
+ assertEq(s1.lastIndexOf(s1), 0);
+ assertEq(s1.lastIndexOf(s2), 11);
+ assertEq(s1.lastIndexOf(s2, 10), -1);
+ assertEq(s2.lastIndexOf(s1), -1);
+
+ // Latin1 + TwoByte
+ assertEq(s1.lastIndexOf("abc\u1234"), -1);
+ assertEq(s1.lastIndexOf("def\u1234".substring(0, 3)), 15);
+ assertEq(s1.lastIndexOf("def\u1234".substring(0, 3), 9), 3);
+
+ // TwoByte + Latin1
+ var s3 = "123456\u0081defg\u1123a456\u0081defg";
+ assertEq(isLatin1(s2), true);
+ assertEq(s3.lastIndexOf(s2), 13);
+ assertEq(s3.lastIndexOf(s2, 12), 3);
+ assertEq(s3.lastIndexOf(toLatin1("defg7")), -1);
+
+ // TwoByte + TwoByte
+ assertEq(s3.lastIndexOf("\u1123a4"), 11);
+ assertEq(s3.lastIndexOf("\u1123a4", 10), -1);
+ assertEq(s3.lastIndexOf("\u1123a\u1098"), -1);
+ assertEq(s3.lastIndexOf(s3), 0);
+}
+testLastIndexOf();
+
+function testIndexOf() {
+ var s1 = toLatin1("abcdefgh123456d\u00AAefghi");
+ var s2 = toLatin1("456d\u00AA");
+
+ // Latin1 + Latin1
+ assertEq(s1.indexOf(s1), 0);
+ assertEq(s1.indexOf(s2), 11);
+ assertEq(s1.indexOf(s2, 12), -1);
+ assertEq(s2.indexOf(s1), -1);
+
+ // Latin1 + TwoByte
+ assertEq(s1.indexOf("abc\u1234"), -1);
+ assertEq(s1.indexOf("def\u1234".substring(0, 3)), 3);
+ assertEq(s1.indexOf("d\u00AAef\u1234".substring(0, 3), 9), 14);
+
+ // TwoByte + Latin1
+ var s3 = "123456d\u00AAefg\u1123a456d\u00AAefg";
+ assertEq(isLatin1(s2), true);
+ assertEq(s3.indexOf(s2), 3);
+ assertEq(s3.indexOf(s2, 11), 13);
+ assertEq(s3.indexOf(toLatin1("d\u00AAefg7")), -1);
+
+ // TwoByte + TwoByte
+ assertEq(s3.indexOf("\u1123a4"), 11);
+ assertEq(s3.indexOf("\u1123a4", 12), -1);
+ assertEq(s3.indexOf("\u1123a\u1098"), -1);
+ assertEq(s3.indexOf(s3), 0);
+}
+testIndexOf();
+
+function testincludes() {
+ var s1 = toLatin1("abcdefgh123456defghi\u00EEj");
+ var s2 = toLatin1("456defghi\u00EE");
+
+ // Latin1 + Latin1
+ assertEq(s1.includes(s1), true);
+ assertEq(s1.includes(s2), true);
+ assertEq(s1.includes(s2, 12), false);
+ assertEq(s2.includes(s1), false);
+
+ // Latin1 + TwoByte
+ assertEq(s1.includes("abc\u1234"), false);
+ assertEq(s1.includes("def\u1234".substring(0, 3)), true);
+ assertEq(s1.includes("def\u1234".substring(0, 3), 9), true);
+
+ // TwoByte + Latin1
+ var s3 = "123456defg\u1123a456defghi\u00EEj";
+ assertEq(isLatin1(s2), true);
+ assertEq(s3.includes(s2), true);
+ assertEq(s3.includes(s2, 13), false);
+ assertEq(s3.includes(toLatin1("defg8")), false);
+
+ // TwoByte + TwoByte
+ assertEq(s3.includes("\u1123a4"), true);
+ assertEq(s3.includes("\u1123a4", 11), false);
+ assertEq(s3.includes("\u1123a\u1098"), false);
+ assertEq(s3.includes(s3), true);
+}
+testincludes();
+
+function testIndexOfBMH() {
+ // BoyerMooreHorspool algorithm is used for large strings.
+ var s = "012345678901234567890123456789".repeat(20);
+ var text = s + "abcdefghijklmnopqrst\u00C1uvwxyz";
+ text.indexOf("333");
+
+ var textL1 = toLatin1(text);
+ var patL1 = toLatin1("cdefghijklmnopqrst\u00C1uvwx");
+
+ // Latin1 + Latin1
+ assertEq(textL1.indexOf(patL1), 602);
+ assertEq(textL1.indexOf(patL1, 603), -1);
+ assertEq(textL1.indexOf(textL1), 0);
+
+ // Latin1 + TwoByte
+ assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy"), 602);
+ assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy", 603), -1);
+ assertEq(textL1.indexOf("cdefghijklmnopqrst\u00C1uvwxy\uaa00", -1), -1);
+
+ // TwoByte + Latin1
+ var textTB = s + "abcdefghijklmnopqrst\u00C1uvwxyz\u1200";
+ text.indexOf("333");
+ assertEq(textTB.indexOf(patL1), 602);
+ assertEq(textTB.indexOf(patL1, 603), -1);
+
+ // TwoByte + TwoByte
+ assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1200"), 603);
+ assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1200", 604), -1);
+ assertEq(textTB.indexOf("defghijklmnopqrst\u00C1uvwxyz\u1201"), -1);
+}
+testIndexOfBMH();
+
+function testIndexOfLargePattern() {
+ // If the pattern length > 128, memcmp is used (text length has to be < 512
+ // or we'll use BoyerMooreHorspool). This is only valid if both
+ // strings have the same encoding.
+ var text = "012345678901234567890123456789".repeat(10) + "abcdefghijklmnopqrst\u00C1uvwxyz";
+ text.indexOf("333"); // flatten
+ var pat = "012345678901234567890123456789".repeat(5) + "abcdefghijklmnopqr";
+ pat.indexOf("333"); // flatten
+
+ // Latin1 + Latin1
+ text = toLatin1(text);
+ pat = toLatin1(pat);
+ assertEq(text.indexOf(pat), 150);
+
+ // Latin1 + TwoByte
+ assertEq(text.indexOf(pat + "\u1200"), -1);
+ assertEq(text.indexOf((pat + "\u1200").slice(0, -1)), 150);
+
+ // TwoByte + Latin1
+ text = text + "\u1100";
+ assertEq(isLatin1(pat), true);
+ assertEq(text.indexOf(pat), 150);
+
+ // TwoByte + TwoByte
+ pat = pat + "st\u00C1uvwxyz\u1100";
+ assertEq(text.indexOf(pat), 150);
+ assertEq(text.indexOf(pat + "\u2000"), -1);
+}
+testIndexOfLargePattern();
diff --git a/js/src/jit-test/tests/latin1/indexing.js b/js/src/jit-test/tests/latin1/indexing.js
new file mode 100644
index 0000000000..c37ed52be9
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/indexing.js
@@ -0,0 +1,47 @@
+function testCharCodeAt() {
+ var s = "abcdefghijklm1234567891000";
+ for (var i=0; i<10; i++)
+ assertEq(s.charCodeAt(i), 97 + i);
+
+ var rope = s + "blah";
+ assertEq(rope.charCodeAt(s.length + 3), 104);
+
+ rope = s + "Foo987";
+ assertEq(rope.charCodeAt(s.length + 4), 56);
+
+ rope = "twoByte\u0580" + s;
+ assertEq(rope.charCodeAt(7), 0x580);
+ assertEq(rope.charCodeAt(14), 103);
+}
+testCharCodeAt();
+
+function testCharAt() {
+ var s = "abcdefghijklm100000002345";
+ assertEq(s.charAt(0), "a");
+ assertEq(s.charAt(s.length-1), "5");
+ assertEq(s.charAt(s.length), "");
+
+ var rope = s + "abcZYX";
+ assertEq(rope.charAt(s.length + 3), "Z");
+
+ rope = s + "Foo987";
+ assertEq(rope.charAt(s.length + 4), "8");
+
+ rope = "twoByte\u0580" + s;
+ assertEq(rope.charAt(7), "\u0580");
+ assertEq(rope.charAt(14), "g");
+}
+testCharAt();
+
+function testIndex(s) {
+ assertEq(s[0], "a");
+ assertEq(s[s.length-1], "6");
+
+ rope = "twoByte\u0512" + s
+ assertEq(rope[7], "\u0512");
+}
+
+var s = "abcdefghijklm123456";
+testIndex(s);
+testIndex(s);
+testIndex(s);
diff --git a/js/src/jit-test/tests/latin1/join.js b/js/src/jit-test/tests/latin1/join.js
new file mode 100644
index 0000000000..ab27a4376b
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/join.js
@@ -0,0 +1,24 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+
+var arrLatin1 = [toLatin1("abc1"), toLatin1("abc\u00A0")];
+var res = arrLatin1.join(toLatin1("sep\u00ff"));
+assertEq(res, "abc1sep\xFFabc\xA0");
+assertEq(isLatin1(res), true);
+
+var arrTwoByte = [toLatin1("abc2"), "def\u1200"];
+assertEq(arrTwoByte.join(toLatin1("sep\u00fe")), "abc2sep\xFEdef\u1200");
+
+res = arrLatin1.join(toLatin1("-"));
+assertEq(res, "abc1-abc\xA0");
+assertEq(isLatin1(res), true);
+
+assertEq(arrTwoByte.join(toLatin1("7")), "abc27def\u1200");
+
+assertEq(arrLatin1.join("\u1200"), "abc1\u1200abc\xA0");
+assertEq(arrTwoByte.join("\u1200"), "abc2\u1200def\u1200");
+
+assertEq(arrLatin1.join("---\u1200"), "abc1---\u1200abc\xA0");
+assertEq(arrTwoByte.join("---\u1200"), "abc2---\u1200def\u1200");
diff --git a/js/src/jit-test/tests/latin1/json.js b/js/src/jit-test/tests/latin1/json.js
new file mode 100644
index 0000000000..88a4f1471e
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/json.js
@@ -0,0 +1,75 @@
+function testBasic() {
+ // Latin1
+ var s = '[1, 2, "foo", "bar\\r\\n", {"xyz": 3}, [1, 2, 3]]';
+ assertEq(isLatin1(s), true);
+ assertEq(JSON.stringify(JSON.parse(s)), '[1,2,"foo","bar\\r\\n",{"xyz":3},[1,2,3]]');
+
+ // TwoByte
+ s = '[1, 2, "foo\u1200", "bar\\r\\n", {"xyz": 3}, [1, 2, 3]]';
+ assertEq(JSON.stringify(JSON.parse(s)), '[1,2,"foo\u1200","bar\\r\\n",{"xyz":3},[1,2,3]]');
+}
+testBasic();
+
+function testErrorPos() {
+ // Make sure the error location is calculated correctly.
+
+ // Latin1
+ var s = '[1, \n2,';
+ try {
+ JSON.parse(s);
+ assertEq(0, 1);
+ } catch(e) {
+ assertEq(e instanceof SyntaxError, true);
+ assertEq(e.toString().includes("line 2 column 3"), true);
+ }
+
+ s = '[1, "\u1300",\n2,';
+ try {
+ JSON.parse(s);
+ assertEq(0, 1);
+ } catch(e) {
+ assertEq(e instanceof SyntaxError, true);
+ assertEq(e.toString().includes("line 2 column 3"), true);
+ }
+}
+testErrorPos();
+
+function testEvalHack() {
+ // Latin1
+ var arr = eval("[1, 2, 3, \"abc\"]");
+ assertEq(JSON.stringify(arr), '[1,2,3,"abc"]');
+ assertEq(isLatin1(JSON.stringify(arr)), true);
+
+ // TwoByte
+ arr = eval("[1, 2, 3, \"abc\u1200\"]");
+ assertEq(JSON.stringify(arr), '[1,2,3,"abc\u1200"]');
+}
+testEvalHack();
+
+function testEvalHackNotJSON() {
+ // Latin1
+ var arr = eval("[]; var q; [1, 2, 3, \"abc\"]");
+ assertEq(JSON.stringify(arr), '[1,2,3,"abc"]');
+
+ // TwoByte
+ arr = eval("[]; var z; [1, 2, 3, \"abc\u1200\"]");
+ assertEq(JSON.stringify(arr), '[1,2,3,"abc\u1200"]');
+
+ var arr = eval("[1, 2, 3, \"abc\u2028\"]");
+ assertEq(arr.length, 4);
+ assertEq(arr[3], "abc\u2028");
+}
+testEvalHackNotJSON();
+
+function testQuote() {
+ // Latin1
+ var s = "abc--\x05-'\"-\n-\u00ff++";
+ var res = JSON.stringify(s);
+ assertEq(res, '"abc--\\u0005-\'\\"-\\n-\xFF++"');
+ assertEq(isLatin1(res), true);
+
+ // TwoByte
+ s += "\uAAAA";
+ assertEq(JSON.stringify(s), '"abc--\\u0005-\'\\"-\\n-\xFF++\uAAAA"');
+}
+testQuote();
diff --git a/js/src/jit-test/tests/latin1/latin1.js b/js/src/jit-test/tests/latin1/latin1.js
new file mode 100644
index 0000000000..ae850f60b4
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/latin1.js
@@ -0,0 +1,120 @@
+function assertLatin1(s) {
+ assertEq(isLatin1(s), true, "String: " + s);
+}
+
+// string literals
+assertLatin1("");
+assertLatin1("x");
+assertLatin1("xy");
+assertLatin1("while");
+assertLatin1("xyaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\u00ff.");
+assertLatin1("-1");
+assertLatin1("50");
+assertLatin1("873939");
+assertLatin1("12.34");
+assertLatin1("NaN");
+
+// int32
+assertLatin1(String(1));
+assertLatin1("" + 40);
+assertLatin1(String(873939));
+assertLatin1(String(-1));
+assertLatin1((-12983).toString());
+assertLatin1(20..toString(16));
+assertLatin1((-20).toString(12));
+assertLatin1(12121..toString(16));
+assertLatin1(12144..toString(2));
+
+// doubles
+assertLatin1(String(12.34));
+assertLatin1(45.6.toString(16));
+assertLatin1(String(-0));
+assertLatin1(NaN.toString());
+assertLatin1("" + -Infinity);
+assertLatin1("a" + 85899345929);
+
+// other types
+assertLatin1(true.toString());
+assertLatin1(String(false));
+assertLatin1(String(null));
+assertLatin1(String(undefined));
+
+// objects
+assertLatin1(Math.toString());
+assertLatin1(({x:1}).toString());
+if (Object.prototype.toSource) {
+ assertLatin1(({x:"foo"}).toSource());
+}
+assertLatin1([1, "bar"].toString());
+
+// typeof
+assertLatin1(typeof "foo");
+assertLatin1(typeof assertEq);
+
+// join
+assertLatin1([1, "foo", null, true].join());
+assertLatin1([1, "foo", null, true].join(":"));
+
+// JSON
+assertLatin1(JSON.stringify({x:1,y:"bar",z:[null],1281298:Math.PI}));
+assertLatin1(JSON.stringify([1, 2, 3], null, "foo"));
+assertLatin1(JSON.stringify({x:1,y:"bar"}, function(k, v) {
+ assertLatin1(k);
+ return v;
+}));
+var arr = [1, 2, 3]; arr.length = 300;
+assertLatin1(JSON.stringify(arr, function(k, v) {
+ assertLatin1(k);
+ return v;
+}));
+
+// Date
+assertLatin1(new Date().toString());
+assertLatin1(new Date().toISOString());
+assertLatin1(Date());
+
+// native functions
+assertLatin1(Math.abs.toString());
+assertLatin1(Object.getOwnPropertyNames.name);
+
+// scripted functions
+function fun1(a, b) { return ["foo\xAA"]; }
+assertLatin1(fun1.toString());
+assertLatin1(fun1.name);
+
+// fromCharCode
+assertLatin1(String.fromCharCode(99));
+assertLatin1(String.fromCharCode(99, 0xff, 1));
+
+// charAt
+assertLatin1("foo\u00ff\u1200".charAt(3));
+
+// RegExps
+var re = /a\.*b[cC]+/g;
+assertLatin1(re.source);
+assertLatin1(re.toString());
+
+// For-in
+var o = {x: 1, y: 2, z\u00ff: 3, 987654: 4, 22: 5};
+for (var prop in o)
+ assertLatin1(prop);
+
+// Object.keys
+assertLatin1(Object.keys(o)[2]);
+
+// Error
+(function foo() {
+ var err;
+ try { this(); } catch(e) { err = e; }
+ assertEq(err.name, "TypeError");
+ assertLatin1(err.name);
+ assertLatin1(err.message);
+ assertLatin1(err.stack);
+ assertLatin1(err.toString());
+
+ try { throw new Error("foo"); } catch(e) { err = e; }
+ assertLatin1(err.name);
+ assertLatin1(err.message);
+ assertLatin1(err.stack);
+ assertLatin1(err.toString());
+})();
diff --git a/js/src/jit-test/tests/latin1/other.js b/js/src/jit-test/tests/latin1/other.js
new file mode 100644
index 0000000000..6713794ec8
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/other.js
@@ -0,0 +1,34 @@
+var s1 = "abcdefg12345";
+var s2 = 'foo"bar';
+
+assertEq(isLatin1(s1), true);
+assertEq(isLatin1(s2), true);
+
+function test() {
+ assertEq(s1.valueOf(), s1);
+
+ assertEq(s1.bold(), "<b>abcdefg12345</b>");
+ assertEq(s1.fontsize("twoByte\u1400"), '<font size="twoByte\u1400">abcdefg12345</font>');
+ assertEq(s1.anchor(s1), '<a name="abcdefg12345">abcdefg12345</a>');
+ assertEq(s1.link(s2), '<a href="foo&quot;bar">abcdefg12345</a>');
+
+ assertEq(s1.concat("abc"), "abcdefg12345abc");
+
+ var s3 = s1.concat(s1, s1);
+ assertEq(isLatin1(s3), true);
+ assertEq(s3, "abcdefg12345abcdefg12345abcdefg12345");
+
+ s3 = s1.concat("twoByte\u1400");
+ assertEq(isLatin1(s3), false);
+ assertEq(s3, "abcdefg12345twoByte\u1400");
+
+ assertEq(s1.codePointAt(3), 100);
+ assertEq(s1.codePointAt(10), 52);
+ assertEq(s1.codePointAt(12), undefined);
+
+ s3 = s1.repeat(5);
+ assertEq(s3, "abcdefg12345abcdefg12345abcdefg12345abcdefg12345abcdefg12345");
+ assertEq(isLatin1(s3), true);
+}
+test();
+test();
diff --git a/js/src/jit-test/tests/latin1/parseInt-parseFloat.js b/js/src/jit-test/tests/latin1/parseInt-parseFloat.js
new file mode 100644
index 0000000000..7240224d12
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/parseInt-parseFloat.js
@@ -0,0 +1,43 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+function testParseInt() {
+ // Latin1
+ assertEq(parseInt(toLatin1("12345abc")), 12345);
+ assertEq(parseInt(toLatin1("0x5")), 0x5);
+ assertEq(parseInt(toLatin1("-123")), -123);
+ assertEq(parseInt(toLatin1("xyz")), NaN);
+ assertEq(parseInt(toLatin1("1234GHI"), 17), 94298);
+ assertEq(parseInt(toLatin1("9007199254749999")), 9007199254750000);
+ assertEq(parseInt(toLatin1(" 9007199254749998"), 16), 10378291982571444000);
+
+ // TwoByte
+ assertEq(parseInt("12345abc\u1200"), 12345);
+ assertEq(parseInt("0x5\u1200"), 0x5);
+ assertEq(parseInt(" -123\u1200"), -123);
+ assertEq(parseInt("\u1200"), NaN);
+ assertEq(parseInt("1234GHI\u1200", 17), 94298);
+ assertEq(parseInt("9007199254749999\u1200"), 9007199254750000);
+ assertEq(parseInt(" 9007199254749998\u1200", 16), 10378291982571444000);
+}
+testParseInt();
+
+function testParseFloat() {
+ // Latin1
+ assertEq(parseFloat(toLatin1("3.1415")), 3.1415);
+ assertEq(parseFloat(toLatin1(" -1234")), -1234);
+ assertEq(parseFloat(toLatin1("\u00AA")), NaN);
+ assertEq(parseFloat(toLatin1("Infinityabc")), Infinity);
+ assertEq(parseFloat(toLatin1("-Infinity")), -Infinity);
+ assertEq(parseFloat(toLatin1("\t\t\t+Infinity")), Infinity);
+
+ // TwoByte
+ assertEq(parseFloat("3.1415\u0FFF"), 3.1415);
+ assertEq(parseFloat(" -1234\u0FFF"), -1234);
+ assertEq(parseFloat("\u00AA\u0FFF"), NaN);
+ assertEq(parseFloat("Infinityabc\u0FFF"), Infinity);
+ assertEq(parseFloat("-Infinity\u0FFF"), -Infinity);
+ assertEq(parseFloat("\t\t\t+Infinity\u0FFF"), Infinity);
+}
+testParseFloat();
diff --git a/js/src/jit-test/tests/latin1/regexp.js b/js/src/jit-test/tests/latin1/regexp.js
new file mode 100644
index 0000000000..809c3817db
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/regexp.js
@@ -0,0 +1,47 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+
+// Latin1
+var re = new RegExp(toLatin1("foo[bB]a\\r"), toLatin1("im"));
+assertEq(isLatin1(re.source), true);
+assertEq(re.source, "foo[bB]a\\r");
+assertEq(re.multiline, true);
+assertEq(re.ignoreCase, true);
+assertEq(re.sticky, false);
+
+// TwoByte
+re = new RegExp("foo[bB]a\\r\u1200", "im");
+assertEq(isLatin1(re.source), false);
+assertEq(re.source, "foo[bB]a\\r\u1200");
+assertEq(re.multiline, true);
+assertEq(re.ignoreCase, true);
+assertEq(re.sticky, false);
+
+re = /b[aA]r/;
+
+// Latin1
+assertEq(toLatin1("foobAr1234").search(re), 3);
+assertEq(toLatin1("bar1234").search(re), 0);
+assertEq(toLatin1("foobbr1234").search(re), -1);
+
+// TwoByte
+assertEq("foobAr1234\u1200".search(re), 3);
+assertEq("bar1234\u1200".search(re), 0);
+assertEq("foobbr1234\u1200".search(re), -1);
+
+re = /abcdefghijklm[0-5]/;
+assertEq(toLatin1("1abcdefghijklm4").search(re), 1);
+assertEq("\u12001abcdefghijklm0".search(re), 2);
+assertEq(toLatin1("1abcdefghijklm8").search(re), -1);
+assertEq("\u12001abcdefghijklm8".search(re), -1);
+
+// If the input is Latin1, case-independent matches should work
+// correctly for characters outside Latin1 with Latin1 equivalents.
+var s = toLatin1("foobar\xff5baz");
+assertEq(s.search(/bar\u0178\d/i), 3);
+
+// Bug 1032067.
+''.match(eval("/(:[aaaaa\cC]\u1200)(?:\S|(?=(\3)))+?/y"));
+assertEq(Function("return /(\uB0DA()})/.toString();")(), "/(\uB0DA()})/");
diff --git a/js/src/jit-test/tests/latin1/replace.js b/js/src/jit-test/tests/latin1/replace.js
new file mode 100644
index 0000000000..fecd958d19
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/replace.js
@@ -0,0 +1,145 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+function testDollarReplacement() {
+ // Latin1 input, pat and replacement
+ var s = toLatin1("Foobarbaz123");
+ var pat = toLatin1("bar");
+ assertEq(s.replace(pat, toLatin1("AA")), "FooAAbaz123");
+ assertEq(s.replace(pat, toLatin1("A$$A")), "FooA$Abaz123");
+ assertEq(s.replace(pat, toLatin1("A$`A")), "FooAFooAbaz123");
+ assertEq(s.replace(pat, toLatin1("A$&A")), "FooAbarAbaz123");
+ assertEq(s.replace(pat, toLatin1("A$'A")), "FooAbaz123Abaz123");
+ assertEq(isLatin1(s.replace(pat, "A$'A")), true);
+
+ // Latin1 input and pat, TwoByte replacement
+ assertEq(s.replace(pat, "A\u1200"), "FooA\u1200baz123");
+ assertEq(s.replace(pat, "A$$\u1200"), "FooA$\u1200baz123");
+ assertEq(s.replace(pat, "A$`\u1200"), "FooAFoo\u1200baz123");
+ assertEq(s.replace(pat, "A$&\u1200"), "FooAbar\u1200baz123");
+ assertEq(s.replace(pat, "A$'\u1200"), "FooAbaz123\u1200baz123");
+
+ // TwoByte input, Latin1 pat and replacement
+ s = "Foobarbaz123\u1200";
+ assertEq(s.replace(pat, toLatin1("A")), "FooAbaz123\u1200");
+ assertEq(s.replace(pat, toLatin1("A$$")), "FooA$baz123\u1200");
+ assertEq(s.replace(pat, toLatin1("A$`")), "FooAFoobaz123\u1200");
+ assertEq(s.replace(pat, toLatin1("A$&")), "FooAbarbaz123\u1200");
+ assertEq(s.replace(pat, toLatin1("A$'")), "FooAbaz123\u1200baz123\u1200");
+
+ // TwoByte input and pat, Latin1 replacement
+ s = "Foobar\u1200baz123";
+ pat += "\u1200";
+ assertEq(s.replace(pat, toLatin1("AB")), "FooABbaz123");
+ assertEq(s.replace(pat, toLatin1("A$$B")), "FooA$Bbaz123");
+ assertEq(s.replace(pat, toLatin1("A$`B")), "FooAFooBbaz123");
+ assertEq(s.replace(pat, toLatin1("A$&B")), "FooAbar\u1200Bbaz123");
+ assertEq(s.replace(pat, toLatin1("A$'B")), "FooAbaz123Bbaz123");
+
+ // TwoByte input, pat and replacement
+ assertEq(s.replace(pat, "A\u1300"), "FooA\u1300baz123");
+ assertEq(s.replace(pat, "A$$\u1300"), "FooA$\u1300baz123");
+ assertEq(s.replace(pat, "A$`\u1300"), "FooAFoo\u1300baz123");
+ assertEq(s.replace(pat, "A$&\u1300"), "FooAbar\u1200\u1300baz123");
+ assertEq(s.replace(pat, "A$'\u1300"), "FooAbaz123\u1300baz123");
+}
+testDollarReplacement();
+
+function testRegExp() {
+ var s = toLatin1("Foobar123bar234");
+ var res = s.replace(/bar\d\d/, "456");
+ assertEq(res, "Foo4563bar234");
+ assertEq(isLatin1(res), true);
+
+ // Latin1 input and replacement
+ var re1 = /bar\d\d/;
+ res = s.replace(re1, toLatin1("789"));
+ assertEq(res, "Foo7893bar234");
+ assertEq(isLatin1(res), true);
+
+ var re2 = /bar\d\d/g;
+ res = s.replace(re2, toLatin1("789\u00ff"));
+ assertEq(res, "Foo789\u00ff3789\u00ff4");
+ assertEq(isLatin1(res), true);
+
+ // Latin1 input, TwoByte replacement
+ assertEq(s.replace(re1, "789\u1200"), "Foo789\u12003bar234");
+ assertEq(s.replace(re2, "789\u1200"), "Foo789\u12003789\u12004");
+
+ // TwoByte input, Latin1 replacement
+ s += "\u1200";
+ assertEq(s.replace(re1, toLatin1("7890")), "Foo78903bar234\u1200");
+ assertEq(s.replace(re2, toLatin1("7890\u00ff")), "Foo7890\u00ff37890\u00ff4\u1200");
+
+ // TwoByte input and replacement
+ assertEq(s.replace(re1, "789\u1200"), "Foo789\u12003bar234\u1200");
+ assertEq(s.replace(re2, "789\u1200"), "Foo789\u12003789\u12004\u1200");
+}
+testRegExp();
+
+function testRegExpDollar() {
+ var s = toLatin1("Foobar123bar2345");
+
+ // Latin1 input and replacement
+ var re1 = /bar\d\d/;
+ var re2 = /bar(\d\d)/g;
+ assertEq(s.replace(re1, toLatin1("--$&--")), "Foo--bar12--3bar2345");
+ assertEq(s.replace(re2, toLatin1("--$'\u00ff--")), "Foo--3bar2345\xFF--3--45\xFF--45");
+ assertEq(s.replace(re2, toLatin1("--$`--")), "Foo--Foo--3--Foobar123--45");
+ assertEq(isLatin1(s.replace(re2, toLatin1("--$`--"))), true);
+
+ // Latin1 input, TwoByte replacement
+ assertEq(s.replace(re1, "\u1200$$"), "Foo\u1200$3bar2345");
+ assertEq(s.replace(re2, "\u1200$1"), "Foo\u1200123\u12002345");
+ assertEq(s.replace(re2, "\u1200$'"), "Foo\u12003bar23453\u12004545");
+
+ // TwoByte input, Latin1 replacement
+ s += "\u1200";
+ assertEq(s.replace(re1, toLatin1("**$&**")), "Foo**bar12**3bar2345\u1200");
+ assertEq(s.replace(re2, toLatin1("**$1**")), "Foo**12**3**23**45\u1200");
+ assertEq(s.replace(re2, toLatin1("**$`**")), "Foo**Foo**3**Foobar123**45\u1200");
+ assertEq(s.replace(re2, toLatin1("**$'$$**")), "Foo**3bar2345\u1200$**3**45\u1200$**45\u1200");
+
+ // TwoByte input and replacement
+ assertEq(s.replace(re1, "**$&**\ueeee"), "Foo**bar12**\ueeee3bar2345\u1200");
+ assertEq(s.replace(re2, "**$1**\ueeee"), "Foo**12**\ueeee3**23**\ueeee45\u1200");
+ assertEq(s.replace(re2, "\ueeee**$`**"), "Foo\ueeee**Foo**3\ueeee**Foobar123**45\u1200");
+ assertEq(s.replace(re2, "\ueeee**$'$$**"), "Foo\ueeee**3bar2345\u1200$**3\ueeee**45\u1200$**45\u1200");
+}
+testRegExpDollar();
+
+function testFlattenPattern() {
+ var s = "abcdef[g]abc";
+
+ // Latin1 pattern
+ var res = s.replace(toLatin1("def[g]"), "--$&--", "gi");
+ assertEq(res, "abc--def[g]--abc");
+ assertEq(isLatin1(res), true);
+
+ // TwoByte pattern
+ s = "abcdef[g]\u1200abc";
+ assertEq(s.replace("def[g]\u1200", "++$&++", "gi"), "abc++def[g]\u1200++abc");
+}
+testFlattenPattern();
+
+function testReplaceEmpty() {
+ // Latin1
+ var s = toLatin1("--abcdefghijkl--abcdefghijkl--abcdefghijkl--abcdefghijkl");
+ var res = s.replace(/abcd[eE]/g, "");
+ assertEq(res, "--fghijkl--fghijkl--fghijkl--fghijkl");
+ assertEq(isLatin1(res), true);
+
+ s = "--abcdEf--";
+ res = s.replace(/abcd[eE]/g, "");
+ assertEq(res, "--f--");
+ assertEq(isLatin1(res), true);
+
+ // TwoByte
+ s = "--abcdefghijkl--abcdefghijkl--abcdefghijkl--abcdefghijkl\u1200";
+ assertEq(s.replace(/abcd[eE]/g, ""), "--fghijkl--fghijkl--fghijkl--fghijkl\u1200");
+
+ s = "--abcdEf--\u1200";
+ assertEq(s.replace(/abcd[eE]/g, ""), "--f--\u1200");
+}
+testReplaceEmpty();
diff --git a/js/src/jit-test/tests/latin1/rope-stringchar.js b/js/src/jit-test/tests/latin1/rope-stringchar.js
new file mode 100644
index 0000000000..d0afa89131
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/rope-stringchar.js
@@ -0,0 +1,16 @@
+function f(a, b) {
+ assertEq(isLatin1(a), true);
+ assertEq(isLatin1(b), false);
+ var c = a + b;
+ assertEq(isLatin1(c), false);
+ assertEq(c[4], 'b');
+ assertEq(c.charCodeAt(4), 98);
+}
+
+function test() {
+ for (var i = 0; i < 15; i++) {
+ f("aaaab\x00\x00\x00\x00\x00\x00", "\u{2603}");
+ }
+}
+
+test();
diff --git a/js/src/jit-test/tests/latin1/search.js b/js/src/jit-test/tests/latin1/search.js
new file mode 100644
index 0000000000..a26c632f27
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/search.js
@@ -0,0 +1,79 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+function testSearchFlat() {
+ var s1 = toLatin1("fooBar12345");
+ var s2 = toLatin1("Bar1");
+
+ // Latin1 + Latin1
+ assertEq(s1.search(s2), 3);
+ assertEq(s2.search(s1), -1);
+ assertEq(s1.search(s1), 0);
+
+ // Latin1 + TwoByte
+ assertEq(s1.search(s2 + "\u1200"), -1);
+ assertEq(s1.search(("12345\u1200").slice(0, -1)), 6);
+
+ // TwoByte + Latin1
+ assertEq("fooBar12345\u1200".search(s1), 0);
+ assertEq("fooBar12345\u1200".search(s2), 3);
+
+ // TwoByte + TwoByte
+ assertEq("fooBar12345\u1200".search("5\u1200"), 10);
+ assertEq("fooBar12345\u1200".search("5\u1201"), -1);
+}
+testSearchFlat();
+
+function testSearchRope() {
+ // Tests for the RopeMatch algorithm.
+ var s1 = "foobarbaz0123456789".repeat(10);
+ s1.indexOf("333"); // flatten
+ s1 = toLatin1(s1);
+
+ var ropeMixed = s1 + "abcdef\u1200";
+ assertEq(isLatin1(ropeMixed), false);
+
+ var abc = toLatin1("abc");
+ var baz = toLatin1("baz");
+
+ // Mixed + Latin1
+ assertEq(ropeMixed.search(abc), 190);
+ assertEq(ropeMixed.search(baz), 6);
+
+ // Mixed + TwoByte
+ assertEq(ropeMixed.search("def\u1200"), 193);
+
+ // Latin1 + Latin1
+ s1 = "foobarbaz0123456789".repeat(10);
+ s1.indexOf("333"); // flatten
+ s1 = toLatin1(s1);
+ var ropeLatin1 = s1 + toLatin1("abcdef\u00AA");
+ assertEq(isLatin1(ropeLatin1), true);
+ assertEq(ropeLatin1.search(abc), 190);
+
+ // Latin1 + TwoByte
+ assertEq(ropeLatin1.search("\u1200bc".substr(1)), 191);
+
+ // TwoByte + Latin1
+ s1 = "foobarbaz0123456789\u11AA".repeat(10);
+ var ropeTwoByte = s1 + "abcdef\u1200";
+ assertEq(ropeTwoByte.search(abc), 200);
+
+ // TwoByte + TwoByte
+ assertEq(ropeTwoByte.search("def\u1200"), 203);
+}
+testSearchRope();
+
+function testSearchStringMatch() {
+ var re = /bar/;
+
+ // Latin1
+ assertEq(toLatin1("foobar1234").search(re), 3);
+ assertEq(toLatin1("foo1234").search(re), -1);
+
+ // TwoByte
+ assertEq("\u1200bar".search(re), 1);
+ assertEq("\u12001234".search(re), -1);
+}
+testSearchStringMatch();
diff --git a/js/src/jit-test/tests/latin1/split.js b/js/src/jit-test/tests/latin1/split.js
new file mode 100644
index 0000000000..d07576e103
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/split.js
@@ -0,0 +1,27 @@
+// Latin1
+var s = "abcdef,g,,";
+var res = s.split(",");
+assertEq(res[0], "abcdef");
+assertEq(isLatin1(res[0]), true);
+assertEq(res[1], "g");
+assertEq(res[2], "");
+assertEq(res[3], "");
+
+s = "abcdef,gh,,";
+res = s.split("\u1200");
+assertEq(res[0], "abcdef,gh,,");
+assertEq(isLatin1(res[0]), true);
+
+// TwoByte
+s = "abcdef\u1200\u1200,g,,";
+res = s.split(",");
+assertEq(res[0], "abcdef\u1200\u1200");
+assertEq(isLatin1(res[0]), false);
+assertEq(res[1], "g");
+assertEq(res[2], "");
+assertEq(res[3], "");
+
+res = s.split("\u1200");
+assertEq(res[0], "abcdef");
+assertEq(res[1], "");
+assertEq(res[2], ",g,,");
diff --git a/js/src/jit-test/tests/latin1/startsWith-endsWith.js b/js/src/jit-test/tests/latin1/startsWith-endsWith.js
new file mode 100644
index 0000000000..eb49bea165
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/startsWith-endsWith.js
@@ -0,0 +1,69 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+function testStartsWith() {
+ var s1 = toLatin1("abc\u0099def");
+ var s2 = toLatin1("abc\u0099d");
+ var s3 = toLatin1("abc\u0098d");
+ var s4 = toLatin1("bc\u0099");
+
+ // Latin1 + Latin1
+ assertEq(s1.startsWith(s2), true);
+ assertEq(s1.startsWith(s3), false);
+ assertEq(s1.startsWith(s4), false);
+ assertEq(s1.startsWith(s4, 1), true);
+ assertEq(s1.startsWith(s1), true);
+
+ // Latin1 + TwoByte
+ assertEq(s1.startsWith("abc\u0099\u1200".slice(0, -1)), true);
+ assertEq(s1.startsWith("abc\u0099e\u1200".slice(0, -1)), false);
+ assertEq(s1.startsWith("bc\u0099\u1200".slice(0, -1), 1), true);
+ assertEq(s1.startsWith("\u1200"), false);
+
+ // TwoByte + Latin1
+ var s5 = "abc\u0099de\u1200";
+ assertEq(s5.startsWith(s1), false);
+ assertEq(s5.startsWith(s2), true);
+ assertEq(s5.startsWith(s4), false);
+ assertEq(s5.startsWith(s4, 1), true);
+
+ // TwoByte + TwoByte
+ assertEq(s5.startsWith(s5), true);
+ assertEq(s5.startsWith("\u1200"), false);
+ assertEq(s5.startsWith("\u1200", 6), true);
+}
+testStartsWith();
+
+function testEndsWith() {
+ var s1 = toLatin1("zabc\u0099defg");
+ var s2 = toLatin1("\u0099defg");
+ var s3 = toLatin1("\u0098defg");
+ var s4 = toLatin1("zabc\u0099def");
+
+ // Latin1 + Latin1
+ assertEq(s1.endsWith(s2), true);
+ assertEq(s1.endsWith(s3), false);
+ assertEq(s1.endsWith(s4), false);
+ assertEq(s1.endsWith(s4, 8), true);
+ assertEq(s1.endsWith(s1), true);
+
+ // Latin1 + TwoByte
+ assertEq(s1.endsWith("abc\u0099defg\u1200".slice(0, -1)), true);
+ assertEq(s1.endsWith("\u1100efg\u1200".slice(0, -1)), false);
+ assertEq(s1.endsWith("bc\u0099\u1200".slice(0, -1), 5), true);
+ assertEq(s1.endsWith("\u1200"), false);
+
+ // TwoByte + Latin1
+ var s5 = "\u1200zabc\u0099defg";
+ assertEq(s5.endsWith(s1), true);
+ assertEq(s5.endsWith(s2), true);
+ assertEq(s5.endsWith(s4), false);
+ assertEq(s5.endsWith(s4, 9), true);
+
+ // TwoByte + TwoByte
+ assertEq(s5.endsWith(s5), true);
+ assertEq(s5.endsWith("\u1200"), false);
+ assertEq(s5.endsWith("\u1200za", 3), true);
+}
+testEndsWith();
diff --git a/js/src/jit-test/tests/latin1/structured-clone.js b/js/src/jit-test/tests/latin1/structured-clone.js
new file mode 100644
index 0000000000..d7ad815a57
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/structured-clone.js
@@ -0,0 +1,19 @@
+// Latin1
+var s = deserialize(serialize("foo123\u00EE"));
+assertEq(s, "foo123\u00EE");
+assertEq(isLatin1(s), true);
+
+var o = deserialize(serialize(new String("foo\u00EE")));
+assertEq(typeof o, "object");
+assertEq(o.valueOf(), "foo\u00EE");
+assertEq(isLatin1(o.valueOf()), true);
+
+// TwoByte
+var s = deserialize(serialize("foo123\u00FF\u1234"));
+assertEq(s, "foo123\u00FF\u1234");
+assertEq(isLatin1(s), false);
+
+var o = deserialize(serialize(new String("foo\uEEEE")));
+assertEq(typeof o, "object");
+assertEq(o.valueOf(), "foo\uEEEE");
+assertEq(isLatin1(o.valueOf()), false);
diff --git a/js/src/jit-test/tests/latin1/toLowerCase-toUpperCase.js b/js/src/jit-test/tests/latin1/toLowerCase-toUpperCase.js
new file mode 100644
index 0000000000..d1855dc3d7
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/toLowerCase-toUpperCase.js
@@ -0,0 +1,57 @@
+function testToLowerCase() {
+ var s1 = "abcdefgABCDEFGH 123456";
+ assertEq(isLatin1(s1), true);
+
+ // Latin1
+ var s2 = s1.toLowerCase();
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "abcdefgabcdefgh 123456");
+
+ s2 = s1.toLocaleLowerCase();
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "abcdefgabcdefgh 123456");
+
+ // TwoByte
+ s2 = "abcdefg\u1200ABCDEFGH 123456\u04AC".toLowerCase();
+ assertEq(s2, "abcdefg\u1200abcdefgh 123456\u04AD");
+
+ s2 = "abcdefg\u1200ABCDEFGH 123456\u04AC".toLocaleLowerCase();
+ assertEq(s2, "abcdefg\u1200abcdefgh 123456\u04AD");
+
+ // For toLowerCase, every Latin1 character maps to a Latin1 character.
+ for (var i=0; i <= 0xff; i++) {
+ var s = "\u1200\u11AA" + String.fromCharCode(i);
+ assertEq(s.toLowerCase().charCodeAt(2) <= 0xff, true);
+ }
+}
+testToLowerCase();
+
+function testToUpperCase() {
+ var s1 = "abcdefgABCDEFGH 12345";
+ assertEq(isLatin1(s1), true);
+
+ // Latin1
+ var s2 = s1.toUpperCase();
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "ABCDEFGABCDEFGH 12345");
+
+ s2 = s1.toLocaleUpperCase();
+ assertEq(isLatin1(s2), true);
+ assertEq(s2, "ABCDEFGABCDEFGH 12345");
+
+ // TwoByte
+ s2 = "abcdefg\u1200ABCDEFGH 12345\u1E0F".toUpperCase();
+ assertEq(s2, "ABCDEFG\u1200ABCDEFGH 12345\u1E0E");
+
+ s2 = "abcdefg\u1200ABCDEFGH 12345\u1E0F".toLocaleUpperCase();
+ assertEq(s2, "ABCDEFG\u1200ABCDEFGH 12345\u1E0E");
+
+ // Tricky case: Latin1 character \u00FF maps to \u0178, a
+ // non-Latin1 character.
+ s1 = "ABC\u00FF";
+ assertEq(isLatin1(s1), true);
+ s2 = s1.toUpperCase();
+ assertEq(isLatin1(s2), false);
+ assertEq(s2, "ABC\u0178");
+}
+testToUpperCase();
diff --git a/js/src/jit-test/tests/latin1/toNumber.js b/js/src/jit-test/tests/latin1/toNumber.js
new file mode 100644
index 0000000000..ab70342739
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/toNumber.js
@@ -0,0 +1,28 @@
+function toLatin1(s) {
+ assertEq(isLatin1(s), true);
+ return s;
+}
+function testToNumber() {
+ // Latin1
+ assertEq(+toLatin1("12345.6"), 12345.6);
+ assertEq(+toLatin1("+123"), 123);
+ assertEq(+toLatin1("0xABC"), 0xABC);
+ assertEq(+toLatin1("112."), 112);
+ assertEq(+toLatin1("112.A"), NaN);
+ assertEq(+toLatin1("-Infinity"), -Infinity);
+
+ // TwoByte
+ function twoByte(s) {
+ s = "\u1200" + s;
+ s = s.substr(1);
+ assertEq(isLatin1(s), false);
+ return s;
+ }
+ assertEq(+twoByte("12345.6"), 12345.6);
+ assertEq(+twoByte("+123"), 123);
+ assertEq(+twoByte("0xABC"), 0xABC);
+ assertEq(+twoByte("112."), 112);
+ assertEq(+twoByte("112.A"), NaN);
+ assertEq(+twoByte("-Infinity"), -Infinity);
+}
+testToNumber();
diff --git a/js/src/jit-test/tests/latin1/trim.js b/js/src/jit-test/tests/latin1/trim.js
new file mode 100644
index 0000000000..79e0830126
--- /dev/null
+++ b/js/src/jit-test/tests/latin1/trim.js
@@ -0,0 +1,28 @@
+function test() {
+ // Latin1
+ var s = " \r\t\n\u00A0foo 123\t \r\n\u00A0";
+ assertEq(isLatin1(s), true);
+
+ var res = s.trim();
+ assertEq(isLatin1(res), true);
+ assertEq(res, "foo 123");
+
+ res = s.trimLeft();
+ assertEq(isLatin1(res), true);
+ assertEq(res, "foo 123\t \r\n\u00A0");
+
+ res = s.trimRight();
+ assertEq(isLatin1(res), true);
+ assertEq(res, " \r\t\n\u00A0foo 123");
+
+ res = "foo 1234".trim();
+ assertEq(isLatin1(res), true);
+ assertEq(res, "foo 1234");
+
+ // TwoByte
+ s = " \r\t\n\u00A0\u2000foo\u1200123\t \r\n\u00A0\u2009";
+ assertEq(s.trim(), "foo\u1200123");
+ assertEq(s.trimLeft(), "foo\u1200123\t \r\n\u00A0\u2009");
+ assertEq(s.trimRight(), " \r\t\n\u00A0\u2000foo\u1200123");
+}
+test();