blob: f38f7b9cb88d991ce5eb82d77544d5fbc1c27b4d [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// Copyright 2014 the V8 project authors. All rights reserved.
2// Redistribution and use in source and binary forms, with or without
3// modification, are permitted provided that the following conditions are
4// met:
5//
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above
9// copyright notice, this list of conditions and the following
10// disclaimer in the documentation and/or other materials provided
11// with the distribution.
12// * Neither the name of Google Inc. nor the names of its
13// contributors may be used to endorse or promote products derived
14// from this software without specific prior written permission.
15//
16// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28assertEquals(1, String.prototype.startsWith.length);
29
30var testString = "Hello World";
31assertTrue(testString.startsWith(""));
32assertTrue(testString.startsWith("Hello"));
33assertFalse(testString.startsWith("hello"));
34assertFalse(testString.startsWith("Hello World!"));
35assertFalse(testString.startsWith(null));
36assertFalse(testString.startsWith(undefined));
37
38assertTrue("null".startsWith(null));
39assertTrue("undefined".startsWith(undefined));
40
41var georgianUnicodeString = "\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10D7";
42assertTrue(georgianUnicodeString.startsWith(georgianUnicodeString));
43assertTrue(georgianUnicodeString.startsWith("\u10D0\u10D1\u10D2"));
44assertFalse(georgianUnicodeString.startsWith("\u10D8"));
45
46assertThrows("String.prototype.startsWith.call(null, 'test')", TypeError);
47assertThrows("String.prototype.startsWith.call(null, null)", TypeError);
48assertThrows("String.prototype.startsWith.call(undefined, undefined)", TypeError);
49
50assertThrows("String.prototype.startsWith.apply(null, ['test'])", TypeError);
51assertThrows("String.prototype.startsWith.apply(null, [null])", TypeError);
52assertThrows("String.prototype.startsWith.apply(undefined, [undefined])", TypeError);
53
54var TEST_INPUT = [{
55 msg: "Empty string", val: ""
56}, {
57 msg: "Number 1234.34", val: 1234.34
58}, {
59 msg: "Integer number 0", val: 0
60}, {
61 msg: "Negative number -1", val: -1
62}, {
63 msg: "Boolean true", val: true
64}, {
65 msg: "Boolean false", val: false
66}, {
67 msg: "Empty array []", val: []
68}, {
69 msg: "Empty object {}", val: {}
70}, {
71 msg: "Array of size 3", val: new Array(3)
72}];
73
74function testNonStringValues() {
75 var i = 0;
76 var l = TEST_INPUT.length;
77
78 for (; i < l; i++) {
79 var e = TEST_INPUT[i];
80 var v = e.val;
81 var s = String(v);
82 assertTrue(s.startsWith(v), e.msg);
83 assertTrue(String.prototype.startsWith.call(v, v), e.msg);
84 assertTrue(String.prototype.startsWith.apply(v, [v]), e.msg);
85 }
86}
87testNonStringValues();
88
89var CustomType = function(value) {
90 this.startsWith = String.prototype.startsWith;
91 this.toString = function() {
92 return String(value);
93 }
94};
95
96function testCutomType() {
97 var i = 0;
98 var l = TEST_INPUT.length;
99
100 for (; i < l; i++) {
101 var e = TEST_INPUT[i];
102 var v = e.val;
103 var o = new CustomType(v);
104 assertTrue(o.startsWith(v), e.msg);
105 }
106}
107testCutomType();
108
109// Test cases found in FF
110assertTrue("abc".startsWith("abc"));
111assertTrue("abcd".startsWith("abc"));
112assertTrue("abc".startsWith("a"));
113assertFalse("abc".startsWith("abcd"));
114assertFalse("abc".startsWith("bcde"));
115assertFalse("abc".startsWith("b"));
116assertTrue("abc".startsWith("abc", 0));
117assertFalse("abc".startsWith("bc", 0));
118assertTrue("abc".startsWith("bc", 1));
119assertFalse("abc".startsWith("c", 1));
120assertFalse("abc".startsWith("abc", 1));
121assertTrue("abc".startsWith("c", 2));
122assertFalse("abc".startsWith("d", 2));
123assertFalse("abc".startsWith("dcd", 2));
124assertFalse("abc".startsWith("a", 42));
125assertFalse("abc".startsWith("a", Infinity));
126assertTrue("abc".startsWith("a", NaN));
127assertFalse("abc".startsWith("b", NaN));
128assertTrue("abc".startsWith("ab", -43));
129assertTrue("abc".startsWith("ab", -Infinity));
130assertFalse("abc".startsWith("bc", -42));
131assertFalse("abc".startsWith("bc", -Infinity));
132
133// Test cases taken from
134// https://github.com/mathiasbynens/String.prototype.startsWith/blob/master/tests/tests.js
135Object.prototype[1] = 2; // try to break `arguments[1]`
136
137assertEquals(String.prototype.startsWith.length, 1);
138assertEquals(String.prototype.propertyIsEnumerable("startsWith"), false);
139
140assertEquals("undefined".startsWith(), true);
141assertEquals("undefined".startsWith(undefined), true);
142assertEquals("undefined".startsWith(null), false);
143assertEquals("null".startsWith(), false);
144assertEquals("null".startsWith(undefined), false);
145assertEquals("null".startsWith(null), true);
146
147assertEquals("abc".startsWith(), false);
148assertEquals("abc".startsWith(""), true);
149assertEquals("abc".startsWith("\0"), false);
150assertEquals("abc".startsWith("a"), true);
151assertEquals("abc".startsWith("b"), false);
152assertEquals("abc".startsWith("ab"), true);
153assertEquals("abc".startsWith("bc"), false);
154assertEquals("abc".startsWith("abc"), true);
155assertEquals("abc".startsWith("bcd"), false);
156assertEquals("abc".startsWith("abcd"), false);
157assertEquals("abc".startsWith("bcde"), false);
158
159assertEquals("abc".startsWith("", NaN), true);
160assertEquals("abc".startsWith("\0", NaN), false);
161assertEquals("abc".startsWith("a", NaN), true);
162assertEquals("abc".startsWith("b", NaN), false);
163assertEquals("abc".startsWith("ab", NaN), true);
164assertEquals("abc".startsWith("bc", NaN), false);
165assertEquals("abc".startsWith("abc", NaN), true);
166assertEquals("abc".startsWith("bcd", NaN), false);
167assertEquals("abc".startsWith("abcd", NaN), false);
168assertEquals("abc".startsWith("bcde", NaN), false);
169
170assertEquals("abc".startsWith("", false), true);
171assertEquals("abc".startsWith("\0", false), false);
172assertEquals("abc".startsWith("a", false), true);
173assertEquals("abc".startsWith("b", false), false);
174assertEquals("abc".startsWith("ab", false), true);
175assertEquals("abc".startsWith("bc", false), false);
176assertEquals("abc".startsWith("abc", false), true);
177assertEquals("abc".startsWith("bcd", false), false);
178assertEquals("abc".startsWith("abcd", false), false);
179assertEquals("abc".startsWith("bcde", false), false);
180
181assertEquals("abc".startsWith("", undefined), true);
182assertEquals("abc".startsWith("\0", undefined), false);
183assertEquals("abc".startsWith("a", undefined), true);
184assertEquals("abc".startsWith("b", undefined), false);
185assertEquals("abc".startsWith("ab", undefined), true);
186assertEquals("abc".startsWith("bc", undefined), false);
187assertEquals("abc".startsWith("abc", undefined), true);
188assertEquals("abc".startsWith("bcd", undefined), false);
189assertEquals("abc".startsWith("abcd", undefined), false);
190assertEquals("abc".startsWith("bcde", undefined), false);
191
192assertEquals("abc".startsWith("", null), true);
193assertEquals("abc".startsWith("\0", null), false);
194assertEquals("abc".startsWith("a", null), true);
195assertEquals("abc".startsWith("b", null), false);
196assertEquals("abc".startsWith("ab", null), true);
197assertEquals("abc".startsWith("bc", null), false);
198assertEquals("abc".startsWith("abc", null), true);
199assertEquals("abc".startsWith("bcd", null), false);
200assertEquals("abc".startsWith("abcd", null), false);
201assertEquals("abc".startsWith("bcde", null), false);
202
203assertEquals("abc".startsWith("", -Infinity), true);
204assertEquals("abc".startsWith("\0", -Infinity), false);
205assertEquals("abc".startsWith("a", -Infinity), true);
206assertEquals("abc".startsWith("b", -Infinity), false);
207assertEquals("abc".startsWith("ab", -Infinity), true);
208assertEquals("abc".startsWith("bc", -Infinity), false);
209assertEquals("abc".startsWith("abc", -Infinity), true);
210assertEquals("abc".startsWith("bcd", -Infinity), false);
211assertEquals("abc".startsWith("abcd", -Infinity), false);
212assertEquals("abc".startsWith("bcde", -Infinity), false);
213
214assertEquals("abc".startsWith("", -1), true);
215assertEquals("abc".startsWith("\0", -1), false);
216assertEquals("abc".startsWith("a", -1), true);
217assertEquals("abc".startsWith("b", -1), false);
218assertEquals("abc".startsWith("ab", -1), true);
219assertEquals("abc".startsWith("bc", -1), false);
220assertEquals("abc".startsWith("abc", -1), true);
221assertEquals("abc".startsWith("bcd", -1), false);
222assertEquals("abc".startsWith("abcd", -1), false);
223assertEquals("abc".startsWith("bcde", -1), false);
224
225assertEquals("abc".startsWith("", -0), true);
226assertEquals("abc".startsWith("\0", -0), false);
227assertEquals("abc".startsWith("a", -0), true);
228assertEquals("abc".startsWith("b", -0), false);
229assertEquals("abc".startsWith("ab", -0), true);
230assertEquals("abc".startsWith("bc", -0), false);
231assertEquals("abc".startsWith("abc", -0), true);
232assertEquals("abc".startsWith("bcd", -0), false);
233assertEquals("abc".startsWith("abcd", -0), false);
234assertEquals("abc".startsWith("bcde", -0), false);
235
236assertEquals("abc".startsWith("", +0), true);
237assertEquals("abc".startsWith("\0", +0), false);
238assertEquals("abc".startsWith("a", +0), true);
239assertEquals("abc".startsWith("b", +0), false);
240assertEquals("abc".startsWith("ab", +0), true);
241assertEquals("abc".startsWith("bc", +0), false);
242assertEquals("abc".startsWith("abc", +0), true);
243assertEquals("abc".startsWith("bcd", +0), false);
244assertEquals("abc".startsWith("abcd", +0), false);
245assertEquals("abc".startsWith("bcde", +0), false);
246
247assertEquals("abc".startsWith("", 1), true);
248assertEquals("abc".startsWith("\0", 1), false);
249assertEquals("abc".startsWith("a", 1), false);
250assertEquals("abc".startsWith("b", 1), true);
251assertEquals("abc".startsWith("ab", 1), false);
252assertEquals("abc".startsWith("bc", 1), true);
253assertEquals("abc".startsWith("abc", 1), false);
254assertEquals("abc".startsWith("bcd", 1), false);
255assertEquals("abc".startsWith("abcd", 1), false);
256assertEquals("abc".startsWith("bcde", 1), false);
257
258assertEquals("abc".startsWith("", +Infinity), true);
259assertEquals("abc".startsWith("\0", +Infinity), false);
260assertEquals("abc".startsWith("a", +Infinity), false);
261assertEquals("abc".startsWith("b", +Infinity), false);
262assertEquals("abc".startsWith("ab", +Infinity), false);
263assertEquals("abc".startsWith("bc", +Infinity), false);
264assertEquals("abc".startsWith("abc", +Infinity), false);
265assertEquals("abc".startsWith("bcd", +Infinity), false);
266assertEquals("abc".startsWith("abcd", +Infinity), false);
267assertEquals("abc".startsWith("bcde", +Infinity), false);
268
269assertEquals("abc".startsWith("", true), true);
270assertEquals("abc".startsWith("\0", true), false);
271assertEquals("abc".startsWith("a", true), false);
272assertEquals("abc".startsWith("b", true), true);
273assertEquals("abc".startsWith("ab", true), false);
274assertEquals("abc".startsWith("bc", true), true);
275assertEquals("abc".startsWith("abc", true), false);
276assertEquals("abc".startsWith("bcd", true), false);
277assertEquals("abc".startsWith("abcd", true), false);
278assertEquals("abc".startsWith("bcde", true), false);
279
280assertEquals("abc".startsWith("", "x"), true);
281assertEquals("abc".startsWith("\0", "x"), false);
282assertEquals("abc".startsWith("a", "x"), true);
283assertEquals("abc".startsWith("b", "x"), false);
284assertEquals("abc".startsWith("ab", "x"), true);
285assertEquals("abc".startsWith("bc", "x"), false);
286assertEquals("abc".startsWith("abc", "x"), true);
287assertEquals("abc".startsWith("bcd", "x"), false);
288assertEquals("abc".startsWith("abcd", "x"), false);
289assertEquals("abc".startsWith("bcde", "x"), false);
290
291assertEquals("[a-z]+(bar)?".startsWith("[a-z]+"), true);
292assertThrows(function() { "[a-z]+(bar)?".startsWith(/[a-z]+/); }, TypeError);
293assertEquals("[a-z]+(bar)?".startsWith("(bar)?", 6), true);
294assertThrows(function() { "[a-z]+(bar)?".startsWith(/(bar)?/); }, TypeError);
295assertThrows(function() { "[a-z]+/(bar)?/".startsWith(/(bar)?/); }, TypeError);
296
297// http://mathiasbynens.be/notes/javascript-unicode#poo-test
298var string = "I\xF1t\xEBrn\xE2ti\xF4n\xE0liz\xE6ti\xF8n\u2603\uD83D\uDCA9";
299assertEquals(string.startsWith(""), true);
300assertEquals(string.startsWith("\xF1t\xEBr"), false);
301assertEquals(string.startsWith("\xF1t\xEBr", 1), true);
302assertEquals(string.startsWith("\xE0liz\xE6"), false);
303assertEquals(string.startsWith("\xE0liz\xE6", 11), true);
304assertEquals(string.startsWith("\xF8n\u2603\uD83D\uDCA9"), false);
305assertEquals(string.startsWith("\xF8n\u2603\uD83D\uDCA9", 18), true);
306assertEquals(string.startsWith("\u2603"), false);
307assertEquals(string.startsWith("\u2603", 20), true);
308assertEquals(string.startsWith("\uD83D\uDCA9"), false);
309assertEquals(string.startsWith("\uD83D\uDCA9", 21), true);
310
311assertThrows(function() {
312 String.prototype.startsWith.call(undefined);
313}, TypeError);
314assertThrows(function() {
315 String.prototype.startsWith.call(undefined, "b");
316}, TypeError);
317assertThrows(function() {
318 String.prototype.startsWith.call(undefined, "b", 4);
319}, TypeError);
320assertThrows(function() {
321 String.prototype.startsWith.call(null);
322}, TypeError);
323assertThrows(function() {
324 String.prototype.startsWith.call(null, "b");
325}, TypeError);
326assertThrows(function() {
327 String.prototype.startsWith.call(null, "b", 4);
328}, TypeError);
329assertEquals(String.prototype.startsWith.call(42, "2"), false);
330assertEquals(String.prototype.startsWith.call(42, "4"), true);
331assertEquals(String.prototype.startsWith.call(42, "b", 4), false);
332assertEquals(String.prototype.startsWith.call(42, "2", 1), true);
333assertEquals(String.prototype.startsWith.call(42, "2", 4), false);
334assertEquals(String.prototype.startsWith.call({
335 "toString": function() { return "abc"; }
336}, "b", 0), false);
337assertEquals(String.prototype.startsWith.call({
338 "toString": function() { return "abc"; }
339}, "b", 1), true);
340assertEquals(String.prototype.startsWith.call({
341 "toString": function() { return "abc"; }
342}, "b", 2), false);
343assertThrows(function() {
344 String.prototype.startsWith.call({
345 "toString": function() { throw RangeError(); }
346 }, /./);
347}, RangeError);
348assertThrows(function() {
349 String.prototype.startsWith.call({
350 "toString": function() { return "abc"; }
351 }, /./);
352}, TypeError);
353
354assertThrows(function() {
355 String.prototype.startsWith.apply(undefined);
356}, TypeError);
357assertThrows(function() {
358 String.prototype.startsWith.apply(undefined, ["b"]);
359}, TypeError);
360assertThrows(function() {
361 String.prototype.startsWith.apply(undefined, ["b", 4]);
362}, TypeError);
363assertThrows(function() {
364 String.prototype.startsWith.apply(null);
365}, TypeError);
366assertThrows(function() {
367 String.prototype.startsWith.apply(null, ["b"]);
368}, TypeError);
369assertThrows(function() {
370 String.prototype.startsWith.apply(null, ["b", 4]);
371}, TypeError);
372assertEquals(String.prototype.startsWith.apply(42, ["2"]), false);
373assertEquals(String.prototype.startsWith.apply(42, ["4"]), true);
374assertEquals(String.prototype.startsWith.apply(42, ["b", 4]), false);
375assertEquals(String.prototype.startsWith.apply(42, ["2", 1]), true);
376assertEquals(String.prototype.startsWith.apply(42, ["2", 4]), false);
377assertEquals(String.prototype.startsWith.apply({
378 "toString": function() {
379 return "abc";
380 }
381}, ["b", 0]), false);
382assertEquals(String.prototype.startsWith.apply({
383 "toString": function() {
384 return "abc";
385 }
386}, ["b", 1]), true);
387assertEquals(String.prototype.startsWith.apply({
388 "toString": function() {
389 return "abc";
390 }
391}, ["b", 2]), false);
392assertThrows(function() {
393 String.prototype.startsWith.apply({
394 "toString": function() { throw RangeError(); }
395 }, [/./]);
396}, RangeError);
397assertThrows(function() {
398 String.prototype.startsWith.apply({
399 "toString": function() { return "abc"; }
400 }, [/./]);
401}, TypeError);
Ben Murdochda12d292016-06-02 14:46:10 +0100402
403// startsWith does its brand checks with Symbol.match
404var re = /./;
405assertThrows(function() {
406 "".startsWith(re);
407}, TypeError);
408re[Symbol.match] = false;
409assertEquals(false, "".startsWith(re));