Add new Harmony methods to String.prototype object.

String.prototype.repeat
String.prototype.startsWith
String.prototype.endsWith
String.prototype.contains

http://people.mozilla.org/~jorendorff/es6-draft.html

BUG=v8:2796,v8:2797,v8:2798,v8:2799
TEST=mjsunit/string-repeat,mjsunit/string-startswith,mjsunit/string-endswith,mjsunit/string-contains
R=mstarzinger@chromium.org

Review URL: https://codereview.chromium.org/21014007

Patch from Ioseb Dzmanashvili <ioseb.dzmanashvili@gmail.com>.

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@15960 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
mstarzinger@chromium.org 2013-07-30 16:33:08 +00:00
parent 306d944e3e
commit 0627d433b0
9 changed files with 660 additions and 1 deletions

View File

@ -2079,6 +2079,11 @@ bool Genesis::InstallExperimentalNatives() {
"native array-iterator.js") == 0) {
if (!CompileExperimentalBuiltin(isolate(), i)) return false;
}
if (FLAG_harmony_strings &&
strcmp(ExperimentalNatives::GetScriptName(i).start(),
"native harmony-string.js") == 0) {
if (!CompileExperimentalBuiltin(isolate(), i)) return false;
}
}
InstallExperimentalNativeFunctions();

View File

@ -173,6 +173,7 @@ DEFINE_bool(harmony_generators, false, "enable harmony generators")
DEFINE_bool(harmony_iteration, false, "enable harmony iteration (for-of)")
DEFINE_bool(harmony_numeric_literals, false,
"enable harmony numeric literals (0o77, 0b11)")
DEFINE_bool(harmony_strings, false, "enable harmony string")
DEFINE_bool(harmony, false, "enable all harmony features (except typeof)")
DEFINE_implication(harmony, harmony_scoping)
DEFINE_implication(harmony, harmony_modules)
@ -183,6 +184,7 @@ DEFINE_implication(harmony, harmony_observation)
DEFINE_implication(harmony, harmony_generators)
DEFINE_implication(harmony, harmony_iteration)
DEFINE_implication(harmony, harmony_numeric_literals)
DEFINE_implication(harmony, harmony_strings)
DEFINE_implication(harmony_modules, harmony_scoping)
DEFINE_implication(harmony_observation, harmony_collections)
// TODO[dslomov] add harmony => harmony_typed_arrays

154
src/harmony-string.js Normal file
View File

@ -0,0 +1,154 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
'use strict';
// This file relies on the fact that the following declaration has been made
// in runtime.js:
// var $String = global.String;
// var $Array = global.Array;
// -------------------------------------------------------------------
// ES6 draft 07-15-13, section 15.5.3.21
function StringRepeat(count) {
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
["String.prototype.repeat"]);
}
var s = TO_STRING_INLINE(this);
var n = ToInteger(count);
if (n < 0 || !NUMBER_IS_FINITE(n)) {
throw MakeRangeError("invalid_count_value", []);
}
var elements = new InternalArray(n);
for (var i = 0; i < n; i++) {
elements[i] = s;
}
return %StringBuilderConcat(elements, n, "");
}
// ES6 draft 07-15-13, section 15.5.3.22
function StringStartsWith(searchString /* position */) { // length == 1
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
["String.prototype.startsWith"]);
}
var s = TO_STRING_INLINE(this);
var ss = TO_STRING_INLINE(searchString);
var pos = 0;
if (%_ArgumentsLength() > 1) {
pos = %_Arguments(1); // position
pos = ToInteger(pos);
}
var s_len = s.length;
var start = MathMin(MathMax(pos, 0), s_len);
var ss_len = ss.length;
if (ss_len + start > s_len) {
return false;
}
return %StringIndexOf(s, ss, start) === start;
}
// ES6 draft 07-15-13, section 15.5.3.23
function StringEndsWith(searchString /* position */) { // length == 1
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
["String.prototype.endsWith"]);
}
var s = TO_STRING_INLINE(this);
var ss = TO_STRING_INLINE(searchString);
var s_len = s.length;
var pos = s_len;
if (%_ArgumentsLength() > 1) {
var arg = %_Arguments(1); // position
if (!IS_UNDEFINED(arg)) {
pos = ToInteger(arg);
}
}
var end = MathMin(MathMax(pos, 0), s_len);
var ss_len = ss.length;
var start = end - ss_len;
if (start < 0) {
return false;
}
return %StringLastIndexOf(s, ss, start) === start;
}
// ES6 draft 07-15-13, section 15.5.3.24
function StringContains(searchString /* position */) { // length == 1
if (IS_NULL_OR_UNDEFINED(this) && !IS_UNDETECTABLE(this)) {
throw MakeTypeError("called_on_null_or_undefined",
["String.prototype.contains"]);
}
var s = TO_STRING_INLINE(this);
var ss = TO_STRING_INLINE(searchString);
var pos = 0;
if (%_ArgumentsLength() > 1) {
pos = %_Arguments(1); // position
pos = ToInteger(pos);
}
var s_len = s.length;
var start = MathMin(MathMax(pos, 0), s_len);
var ss_len = ss.length;
if (ss_len + start > s_len) {
return false;
}
return %StringIndexOf(s, ss, start) !== -1;
}
// -------------------------------------------------------------------
function ExtendStringPrototype() {
%CheckIsBootstrapping();
// Set up the non-enumerable functions on the String prototype object.
InstallFunctions($String.prototype, DONT_ENUM, $Array(
"repeat", StringRepeat,
"startsWith", StringStartsWith,
"endsWith", StringEndsWith,
"contains", StringContains
));
}
ExtendStringPrototype();

View File

@ -126,6 +126,7 @@ var kMessages = {
stack_overflow: ["Maximum call stack size exceeded"],
invalid_time_value: ["Invalid time value"],
invalid_count_value: ["Invalid count value"],
// SyntaxError
paren_in_arg_string: ["Function arg string contains parenthesis"],
not_isvar: ["builtin %IS_VAR: not a variable"],

View File

@ -0,0 +1,151 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-strings
assertEquals(1, String.prototype.contains.length);
var reString = "asdf[a-z]+(asdf)?";
assertTrue(reString.contains("[a-z]+"));
assertTrue(reString.contains("(asdf)?"));
// Random greek letters
var twoByteString = "\u039a\u0391\u03a3\u03a3\u0395";
// Test single char pattern
assertTrue(twoByteString.contains("\u039a"), "Lamda");
assertTrue(twoByteString.contains("\u0391"), "Alpha");
assertTrue(twoByteString.contains("\u03a3"), "First Sigma");
assertTrue(twoByteString.contains("\u03a3",3), "Second Sigma");
assertTrue(twoByteString.contains("\u0395"), "Epsilon");
assertFalse(twoByteString.contains("\u0392"), "Not beta");
// Test multi-char pattern
assertTrue(twoByteString.contains("\u039a\u0391"), "lambda Alpha");
assertTrue(twoByteString.contains("\u0391\u03a3"), "Alpha Sigma");
assertTrue(twoByteString.contains("\u03a3\u03a3"), "Sigma Sigma");
assertTrue(twoByteString.contains("\u03a3\u0395"), "Sigma Epsilon");
assertFalse(twoByteString.contains("\u0391\u03a3\u0395"),
"Not Alpha Sigma Epsilon");
//single char pattern
assertTrue(twoByteString.contains("\u0395"));
assertThrows("String.prototype.contains.call(null, 'test')", TypeError);
assertThrows("String.prototype.contains.call(null, null)", TypeError);
assertThrows("String.prototype.contains.call(undefined, undefined)", TypeError);
assertThrows("String.prototype.contains.apply(null, ['test'])", TypeError);
assertThrows("String.prototype.contains.apply(null, [null])", TypeError);
assertThrows("String.prototype.contains.apply(undefined, [undefined])", TypeError);
var TEST_INPUT = [{
msg: "Empty string", val: ""
}, {
msg: "Number 1234.34", val: 1234.34
}, {
msg: "Integer number 0", val: 0
}, {
msg: "Negative number -1", val: -1
}, {
msg: "Boolean true", val: true
}, {
msg: "Boolean false", val: false
}, {
msg: "Regular expression /\d+/", val: /\d+/
}, {
msg: "Empty array []", val: []
}, {
msg: "Empty object {}", val: {}
}, {
msg: "Array of size 3", val: new Array(3)
}];
var i = 0;
var l = TEST_INPUT.length;
for (; i < l; i++) {
var e = TEST_INPUT[i];
var v = e.val;
var s = String(v);
assertTrue(s.contains(v), e.msg);
assertTrue(String.prototype.contains.call(v, v), e.msg);
assertTrue(String.prototype.contains.apply(v, [v]), e.msg);
}
// Test cases found in FF
assertTrue("abc".contains("a"));
assertTrue("abc".contains("b"));
assertTrue("abc".contains("abc"));
assertTrue("abc".contains("bc"));
assertFalse("abc".contains("d"));
assertFalse("abc".contains("abcd"));
assertFalse("abc".contains("ac"));
assertTrue("abc".contains("abc", 0));
assertTrue("abc".contains("bc", 0));
assertFalse("abc".contains("de", 0));
assertTrue("abc".contains("bc", 1));
assertTrue("abc".contains("c", 1));
assertFalse("abc".contains("a", 1));
assertFalse("abc".contains("abc", 1));
assertTrue("abc".contains("c", 2));
assertFalse("abc".contains("d", 2));
assertFalse("abc".contains("dcd", 2));
assertFalse("abc".contains("a", 42));
assertFalse("abc".contains("a", Infinity));
assertTrue("abc".contains("ab", -43));
assertFalse("abc".contains("cd", -42));
assertTrue("abc".contains("ab", -Infinity));
assertFalse("abc".contains("cd", -Infinity));
assertTrue("abc".contains("ab", NaN));
assertFalse("abc".contains("cd", NaN));
assertFalse("xyzzy".contains("zy\0", 2));
var dots = Array(10000).join('.');
assertFalse(dots.contains("\x01", 10000));
assertFalse(dots.contains("\0", 10000));
var myobj = {
toString: function () {
return "abc";
},
contains: String.prototype.contains
};
assertTrue(myobj.contains("abc"));
assertFalse(myobj.contains("cd"));
var gotStr = false;
var gotPos = false;
myobj = {
toString: function () {
assertFalse(gotPos);
gotStr = true;
return "xyz";
},
contains: String.prototype.contains
};

View File

@ -0,0 +1,136 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-strings
assertEquals(1, String.prototype.endsWith.length);
var testString = "Hello World";
assertTrue(testString.endsWith(""));
assertTrue(testString.endsWith("World"));
assertFalse(testString.endsWith("world"));
assertFalse(testString.endsWith("Hello World!"));
assertFalse(testString.endsWith(null));
assertFalse(testString.endsWith(undefined));
assertTrue("null".endsWith(null));
assertTrue("undefined".endsWith(undefined));
var georgianUnicodeString = "\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10D7";
assertTrue(georgianUnicodeString.endsWith(georgianUnicodeString));
assertTrue(georgianUnicodeString.endsWith("\u10D4\u10D5\u10D6\u10D7"));
assertFalse(georgianUnicodeString.endsWith("\u10D0"));
assertThrows("String.prototype.endsWith.call(null, 'test')", TypeError);
assertThrows("String.prototype.endsWith.call(null, null)", TypeError);
assertThrows("String.prototype.endsWith.call(undefined, undefined)", TypeError);
assertThrows("String.prototype.endsWith.apply(null, ['test'])", TypeError);
assertThrows("String.prototype.endsWith.apply(null, [null])", TypeError);
assertThrows("String.prototype.endsWith.apply(undefined, [undefined])", TypeError);
var TEST_INPUT = [{
msg: "Empty string", val: ""
}, {
msg: "Number 1234.34", val: 1234.34
}, {
msg: "Integer number 0", val: 0
}, {
msg: "Negative number -1", val: -1
}, {
msg: "Boolean true", val: true
}, {
msg: "Boolean false", val: false
}, {
msg: "Regular expression /\d+/", val: /\d+/
}, {
msg: "Empty array []", val: []
}, {
msg: "Empty object {}", val: {}
}, {
msg: "Array of size 3", val: new Array(3)
}];
function testNonStringValues() {
var i = 0;
var l = TEST_INPUT.length;
for (; i < l; i++) {
var e = TEST_INPUT[i];
var v = e.val;
var s = String(v);
assertTrue(s.endsWith(v), e.msg);
assertTrue(String.prototype.endsWith.call(v, v), e.msg);
assertTrue(String.prototype.endsWith.apply(v, [v]), e.msg);
}
}
testNonStringValues();
var CustomType = function(value) {
this.endsWith = String.prototype.endsWith;
this.toString = function() {
return String(value);
}
};
function testCutomType() {
var i = 0;
var l = TEST_INPUT.length;
for (; i < l; i++) {
var e = TEST_INPUT[i];
var v = e.val;
var o = new CustomType(v);
assertTrue(o.endsWith(v), e.msg);
}
}
testCutomType();
// Test cases found in FF
assertTrue("abc".endsWith("abc"));
assertTrue("abcd".endsWith("bcd"));
assertTrue("abc".endsWith("c"));
assertFalse("abc".endsWith("abcd"));
assertFalse("abc".endsWith("bbc"));
assertFalse("abc".endsWith("b"));
assertTrue("abc".endsWith("abc", 3));
assertTrue("abc".endsWith("bc", 3));
assertFalse("abc".endsWith("a", 3));
assertTrue("abc".endsWith("bc", 3));
assertTrue("abc".endsWith("a", 1));
assertFalse("abc".endsWith("abc", 1));
assertTrue("abc".endsWith("b", 2));
assertFalse("abc".endsWith("d", 2));
assertFalse("abc".endsWith("dcd", 2));
assertFalse("abc".endsWith("a", 42));
assertTrue("abc".endsWith("bc", Infinity));
assertFalse("abc".endsWith("a", Infinity));
assertTrue("abc".endsWith("bc", undefined));
assertFalse("abc".endsWith("bc", -43));
assertFalse("abc".endsWith("bc", -Infinity));
assertFalse("abc".endsWith("bc", NaN));

View File

@ -0,0 +1,74 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-strings
assertEquals("000", String.prototype.repeat.call(0, 3));
assertEquals("-1-1-1", String.prototype.repeat.call(-1, 3));
assertEquals("2.12.12.1", String.prototype.repeat.call(2.1, 3));
assertEquals("", String.prototype.repeat.call([], 3));
assertEquals("1,2,3", String.prototype.repeat.call([1, 2, 3], 1));
assertEquals("true", String.prototype.repeat.call(true, 1));
assertEquals("false", String.prototype.repeat.call(false, 1));
assertEquals("[object Object]", String.prototype.repeat.call({}, 1));
assertEquals("000", String.prototype.repeat.apply(0, [3]));
assertEquals("-1-1-1", String.prototype.repeat.apply(-1, [3]));
assertEquals("2.12.12.1", String.prototype.repeat.apply(2.1, [3]));
assertEquals("", String.prototype.repeat.apply([], [3]));
assertEquals("1,2,3", String.prototype.repeat.apply([1, 2, 3], [1]));
assertEquals("true", String.prototype.repeat.apply(true, [1]));
assertEquals("false", String.prototype.repeat.apply(false, [1]));
assertEquals("[object Object]", String.prototype.repeat.apply({}, [1]));
assertEquals("\u10D8\u10D8\u10D8", "\u10D8".repeat(3));
assertThrows('String.prototype.repeat.call(null, 1)', TypeError);
assertThrows('String.prototype.repeat.call(undefined, 1)', TypeError);
assertThrows('String.prototype.repeat.apply(null, [1])', TypeError);
assertThrows('String.prototype.repeat.apply(undefined, [1])', TypeError);
// Test cases found in FF
assertEquals("abc", "abc".repeat(1));
assertEquals("abcabc", "abc".repeat(2));
assertEquals("abcabcabc", "abc".repeat(3));
assertEquals("aaaaaaaaaa", "a".repeat(10));
assertEquals("", "".repeat(5));
assertEquals("", "abc".repeat(0));
assertEquals("abcabc", "abc".repeat(2.0));
assertThrows('"a".repeat(-1)', RangeError);
assertThrows('"a".repeat(Number.POSITIVE_INFINITY)', RangeError);
var myobj = {
toString: function() {
return "abc";
},
repeat : String.prototype.repeat
};
assertEquals("abc", myobj.repeat(1));
assertEquals("abcabc", myobj.repeat(2));

View File

@ -0,0 +1,135 @@
// Copyright 2013 the V8 project authors. All rights reserved.
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following
// disclaimer in the documentation and/or other materials provided
// with the distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// Flags: --harmony-strings
assertEquals(1, String.prototype.startsWith.length);
var testString = "Hello World";
assertTrue(testString.startsWith(""));
assertTrue(testString.startsWith("Hello"));
assertFalse(testString.startsWith("hello"));
assertFalse(testString.startsWith("Hello World!"));
assertFalse(testString.startsWith(null));
assertFalse(testString.startsWith(undefined));
assertTrue("null".startsWith(null));
assertTrue("undefined".startsWith(undefined));
var georgianUnicodeString = "\u10D0\u10D1\u10D2\u10D3\u10D4\u10D5\u10D6\u10D7";
assertTrue(georgianUnicodeString.startsWith(georgianUnicodeString));
assertTrue(georgianUnicodeString.startsWith("\u10D0\u10D1\u10D2"));
assertFalse(georgianUnicodeString.startsWith("\u10D8"));
assertThrows("String.prototype.startsWith.call(null, 'test')", TypeError);
assertThrows("String.prototype.startsWith.call(null, null)", TypeError);
assertThrows("String.prototype.startsWith.call(undefined, undefined)", TypeError);
assertThrows("String.prototype.startsWith.apply(null, ['test'])", TypeError);
assertThrows("String.prototype.startsWith.apply(null, [null])", TypeError);
assertThrows("String.prototype.startsWith.apply(undefined, [undefined])", TypeError);
var TEST_INPUT = [{
msg: "Empty string", val: ""
}, {
msg: "Number 1234.34", val: 1234.34
}, {
msg: "Integer number 0", val: 0
}, {
msg: "Negative number -1", val: -1
}, {
msg: "Boolean true", val: true
}, {
msg: "Boolean false", val: false
}, {
msg: "Regular expression /\d+/", val: /\d+/
}, {
msg: "Empty array []", val: []
}, {
msg: "Empty object {}", val: {}
}, {
msg: "Array of size 3", val: new Array(3)
}];
function testNonStringValues() {
var i = 0;
var l = TEST_INPUT.length;
for (; i < l; i++) {
var e = TEST_INPUT[i];
var v = e.val;
var s = String(v);
assertTrue(s.startsWith(v), e.msg);
assertTrue(String.prototype.startsWith.call(v, v), e.msg);
assertTrue(String.prototype.startsWith.apply(v, [v]), e.msg);
}
}
testNonStringValues();
var CustomType = function(value) {
this.startsWith = String.prototype.startsWith;
this.toString = function() {
return String(value);
}
};
function testCutomType() {
var i = 0;
var l = TEST_INPUT.length;
for (; i < l; i++) {
var e = TEST_INPUT[i];
var v = e.val;
var o = new CustomType(v);
assertTrue(o.startsWith(v), e.msg);
}
}
testCutomType();
// Test cases found in FF
assertTrue("abc".startsWith("abc"));
assertTrue("abcd".startsWith("abc"));
assertTrue("abc".startsWith("a"));
assertFalse("abc".startsWith("abcd"));
assertFalse("abc".startsWith("bcde"));
assertFalse("abc".startsWith("b"));
assertTrue("abc".startsWith("abc", 0));
assertFalse("abc".startsWith("bc", 0));
assertTrue("abc".startsWith("bc", 1));
assertFalse("abc".startsWith("c", 1));
assertFalse("abc".startsWith("abc", 1));
assertTrue("abc".startsWith("c", 2));
assertFalse("abc".startsWith("d", 2));
assertFalse("abc".startsWith("dcd", 2));
assertFalse("abc".startsWith("a", 42));
assertFalse("abc".startsWith("a", Infinity));
assertTrue("abc".startsWith("a", NaN));
assertFalse("abc".startsWith("b", NaN));
assertTrue("abc".startsWith("ab", -43));
assertTrue("abc".startsWith("ab", -Infinity));
assertFalse("abc".startsWith("bc", -42));
assertFalse("abc".startsWith("bc", -Infinity));

View File

@ -906,7 +906,8 @@
'../../src/arraybuffer.js',
'../../src/typedarray.js',
'../../src/generator.js',
'../../src/array-iterator.js'
'../../src/array-iterator.js',
'../../src/harmony-string.js'
],
'i18n_library_files': [
'../../src/extensions/i18n/header.js',