diff options
Diffstat (limited to 'js/src/jit-test/tests/latin1')
29 files changed, 1496 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/latin1/asm.js b/js/src/jit-test/tests/latin1/asm.js new file mode 100644 index 000000000..ace4e7f52 --- /dev/null +++ b/js/src/jit-test/tests/latin1/asm.js @@ -0,0 +1,33 @@ +load(libdir + "asm.js"); + +setCachingEnabled(true); +if (!isAsmJSCompilationAvailable() || !isCachingEnabled()) + quit(); + +// Test Latin1 and TwoByte PropertyName serialization. + +// Latin1 +var body1 = "'use asm'; function funName() { return 42 } return funName"; +var m = new Function(body1); +assertEq(isAsmJSModule(m), true); +assertEq(m()(), 42); +var m = new Function(body1); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +assertEq(m()(), 42); + +var f = m(); +assertEq(isLatin1(f.name), true); +assertEq(f.name, "funName"); + +// TwoByte +var body1 = "'use asm'; function funName\u1200() { return 42 } return funName\u1200"; +var m = new Function(body1); +assertEq(isAsmJSModule(m), true); +assertEq(m()(), 42); +var m = new Function(body1); +assertEq(isAsmJSModuleLoadedFromCache(m), true); +assertEq(m()(), 42); + +var f = m(); +assertEq(isLatin1(f.name), false); +assertEq(f.name, "funName\u1200"); 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 000000000..cef79cb96 --- /dev/null +++ b/js/src/jit-test/tests/latin1/assorted.js @@ -0,0 +1,37 @@ +// 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"); + +// 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(), "({prop:((11)), 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 000000000..a11a6cf65 --- /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 000000000..74f1ff53f --- /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 000000000..636802b16 --- /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 000000000..edf0221f9 --- /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 000000000..35f07847e --- /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 000000000..f92bc9dc1 --- /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 000000000..cb6869654 --- /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 000000000..9cab2ddbb --- /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 000000000..8b13018d0 --- /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 000000000..a0dedf251 --- /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.toSource().includes("arg1\u1200, arg2"), true); + + var bodyTwoByte = "return arg1\u1200 + arg2;"; + f = Function(arg1TwoByte, arg2Latin1, bodyTwoByte); + assertEq(f(30, 40), 70); + assertEq(f.toSource().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 000000000..4a8a93028 --- /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 000000000..9857f4a7f --- /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 000000000..c37ed52be --- /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 000000000..ab27a4376 --- /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 000000000..16559890d --- /dev/null +++ b/js/src/jit-test/tests/latin1/json.js @@ -0,0 +1,79 @@ +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"]'); + + try { + eval("[1, 2, 3, \"abc\u2028\"]"); + throw new Error("U+2028 shouldn't eval"); + } catch (e) { + assertEq(e instanceof SyntaxError, true, + "should have thrown a SyntaxError, instead got " + e); + } +} +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 000000000..f0af0062c --- /dev/null +++ b/js/src/jit-test/tests/latin1/latin1.js @@ -0,0 +1,118 @@ +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()); +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 000000000..6713794ec --- /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"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 000000000..7240224d1 --- /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 000000000..809c3817d --- /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 000000000..fecd958d1 --- /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/search.js b/js/src/jit-test/tests/latin1/search.js new file mode 100644 index 000000000..a26c632f2 --- /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 000000000..d07576e10 --- /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 000000000..eb49bea16 --- /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 000000000..d7ad815a5 --- /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 000000000..d1855dc3d --- /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 000000000..ab7034273 --- /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 000000000..79e083012 --- /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(); |