1ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Copyright 2013 the V8 project authors. All rights reserved.
2ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Redistribution and use in source and binary forms, with or without
3ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// modification, are permitted provided that the following conditions are
4ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// met:
5ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
6ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//     * Redistributions of source code must retain the above copyright
7ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//       notice, this list of conditions and the following disclaimer.
8ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//     * Redistributions in binary form must reproduce the above
9ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//       copyright notice, this list of conditions and the following
10ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//       disclaimer in the documentation and/or other materials provided
11ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//       with the distribution.
12ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//     * Neither the name of Google Inc. nor the names of its
13ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//       contributors may be used to endorse or promote products derived
14ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//       from this software without specific prior written permission.
15ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//
16ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
28ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Flags: --harmony-strings
29ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
30ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertEquals(1, String.prototype.contains.length);
31ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
32ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar reString = "asdf[a-z]+(asdf)?";
33ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(reString.contains("[a-z]+"));
34ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(reString.contains("(asdf)?"));
35ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
36ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Random greek letters
37ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar twoByteString = "\u039a\u0391\u03a3\u03a3\u0395";
38ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
39ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Test single char pattern
40ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u039a"), "Lamda");
41ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u0391"), "Alpha");
42ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u03a3"), "First Sigma");
43ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u03a3",3), "Second Sigma");
44ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u0395"), "Epsilon");
45ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse(twoByteString.contains("\u0392"), "Not beta");
46ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
47ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Test multi-char pattern
48ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u039a\u0391"), "lambda Alpha");
49ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u0391\u03a3"), "Alpha Sigma");
50ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u03a3\u03a3"), "Sigma Sigma");
51ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u03a3\u0395"), "Sigma Epsilon");
52ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
53ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse(twoByteString.contains("\u0391\u03a3\u0395"),
54ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    "Not Alpha Sigma Epsilon");
55ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
56ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov//single char pattern
57ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(twoByteString.contains("\u0395"));
58ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
59ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.call(null, 'test')", TypeError);
60ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.call(null, null)", TypeError);
61ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.call(undefined, undefined)", TypeError);
62ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
63ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.apply(null, ['test'])", TypeError);
64ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.apply(null, [null])", TypeError);
65ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.apply(undefined, [undefined])", TypeError);
66ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
67ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar TEST_INPUT = [{
68ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Empty string", val: ""
69ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
70ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Number 1234.34", val: 1234.34
71ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
72ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Integer number 0", val: 0
73ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
74ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Negative number -1", val: -1
75ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
76ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Boolean true", val: true
77ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
78ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Boolean false", val: false
79ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
80ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Empty array []", val: []
81ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
82ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Empty object {}", val: {}
83ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}, {
84ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  msg: "Array of size 3", val: new Array(3)
85ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}];
86ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
87ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar i = 0;
88ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar l = TEST_INPUT.length;
89ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
90ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovfor (; i < l; i++) {
91ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  var e = TEST_INPUT[i];
92ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  var v = e.val;
93ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  var s = String(v);
94ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  assertTrue(s.contains(v), e.msg);
95ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  assertTrue(String.prototype.contains.call(v, v), e.msg);
96ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  assertTrue(String.prototype.contains.apply(v, [v]), e.msg);
97ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov}
98ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
99ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov// Test cases found in FF
100ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("a"));
101ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("b"));
102ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("abc"));
103ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("bc"));
104ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("d"));
105ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("abcd"));
106ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("ac"));
107ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("abc", 0));
108ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("bc", 0));
109ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("de", 0));
110ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("bc", 1));
111ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("c", 1));
112ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("a", 1));
113ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("abc", 1));
114ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("c", 2));
115ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("d", 2));
116ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("dcd", 2));
117ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("a", 42));
118ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("a", Infinity));
119ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("ab", -43));
120ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("cd", -42));
121ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("ab", -Infinity));
122ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("cd", -Infinity));
123ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue("abc".contains("ab", NaN));
124ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("abc".contains("cd", NaN));
125ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse("xyzzy".contains("zy\0", 2));
126ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
127ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar dots = Array(10000).join(".");
128ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse(dots.contains("\x01", 10000));
129ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse(dots.contains("\0", 10000));
130ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
131ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar myobj = {
132ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  toString: function () {
133ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return "abc";
134ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  },
135ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  contains: String.prototype.contains
136ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
137ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertTrue(myobj.contains("abc"));
138ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertFalse(myobj.contains("cd"));
139ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
140ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar gotStr = false;
141ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovvar gotPos = false;
142ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganovmyobj = {
143ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  toString: function () {
144ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    assertFalse(gotPos);
145ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    gotStr = true;
146ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov    return "xyz";
147ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  },
148ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  contains: String.prototype.contains
149ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov};
150ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
151ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertEquals("foo[a-z]+(bar)?".contains("[a-z]+"), true);
152ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("'foo[a-z]+(bar)?'.contains(/[a-z]+/)", TypeError);
153ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("'foo/[a-z]+/(bar)?'.contains(/[a-z]+/)", TypeError);
154ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertEquals("foo[a-z]+(bar)?".contains("(bar)?"), true);
155ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("'foo[a-z]+(bar)?'.contains(/(bar)?/)", TypeError);
156ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("'foo[a-z]+/(bar)?/'.contains(/(bar)?/)", TypeError);
157ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
158ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.call({ 'toString': function() { " +
159ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  "throw RangeError(); } }, /./)", RangeError);
160ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.call({ 'toString': function() { " +
161ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  "return 'abc'; } }, /./)", TypeError);
162ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov
163ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.apply({ 'toString': function() { " +
164ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  "throw RangeError(); } }, [/./])", RangeError);
165ee451cb395940862dad63c85adfe8f2fd55e864cSvet GanovassertThrows("String.prototype.contains.apply({ 'toString': function() { " +
166ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov  "return 'abc'; } }, [/./])", TypeError);
167ee451cb395940862dad63c85adfe8f2fd55e864cSvet Ganov