diff options
author | Ali Ijaz Sheikh <ofrobots@google.com> | 2016-03-01 08:58:05 -0800 |
---|---|---|
committer | Ali Sheikh <ofrobots@lemonhope.roam.corp.google.com> | 2016-03-03 20:35:20 -0800 |
commit | 069e02ab47656b3efd1b6829c65856b2e1c2d1db (patch) | |
tree | eb643e0a2e88fd64bb9fc927423458d2ae96c2db /deps/v8/test/cctest/test-regexp.cc | |
parent | 8938355398c79f583a468284b768652d12ba9bc9 (diff) | |
download | node-new-069e02ab47656b3efd1b6829c65856b2e1c2d1db.tar.gz |
deps: upgrade to V8 4.9.385.18
Pick up the current branch head for V8 4.9
https://github.com/v8/v8/commit/1ecba0f
PR-URL: https://github.com/nodejs/node/pull/4722
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Michaƫl Zasso <mic.besace@gmail.com>
Diffstat (limited to 'deps/v8/test/cctest/test-regexp.cc')
-rw-r--r-- | deps/v8/test/cctest/test-regexp.cc | 229 |
1 files changed, 174 insertions, 55 deletions
diff --git a/deps/v8/test/cctest/test-regexp.cc b/deps/v8/test/cctest/test-regexp.cc index 2e236c20f3..a91058cc24 100644 --- a/deps/v8/test/cctest/test-regexp.cc +++ b/deps/v8/test/cctest/test-regexp.cc @@ -25,21 +25,19 @@ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// TODO(mythria): Remove this define after this flag is turned on globally -#define V8_IMMINENT_DEPRECATION_WARNINGS - #include <cstdlib> #include <sstream> +#include "include/v8.h" #include "src/v8.h" -#include "src/ast.h" +#include "src/ast/ast.h" #include "src/char-predicates-inl.h" #include "src/ostreams.h" -#include "src/parser.h" #include "src/regexp/jsregexp.h" #include "src/regexp/regexp-macro-assembler.h" #include "src/regexp/regexp-macro-assembler-irregexp.h" +#include "src/regexp/regexp-parser.h" #include "src/splay-tree-inl.h" #include "src/string-stream.h" #ifdef V8_INTERPRETED_REGEXP @@ -102,17 +100,21 @@ static bool CheckParse(const char* input) { } -static void CheckParseEq(const char* input, const char* expected) { +static void CheckParseEq(const char* input, const char* expected, + bool unicode = false) { v8::HandleScope scope(CcTest::isolate()); Zone zone; FlatStringReader reader(CcTest::i_isolate(), CStrVector(input)); RegExpCompileData result; CHECK(v8::internal::RegExpParser::ParseRegExp( - CcTest::i_isolate(), &zone, &reader, false, false, &result)); + CcTest::i_isolate(), &zone, &reader, false, unicode, &result)); CHECK(result.tree != NULL); CHECK(result.error.is_null()); std::ostringstream os; result.tree->Print(os, &zone); + if (strcmp(expected, os.str().c_str()) != 0) { + printf("%s | %s\n", expected, os.str().c_str()); + } CHECK_EQ(0, strcmp(expected, os.str().c_str())); } @@ -159,7 +161,11 @@ static MinMaxPair CheckMinMaxMatch(const char* input) { CHECK_EQ(max, min_max.max_match); \ } -TEST(Parser) { + +void TestRegExpParser(bool lookbehind) { + FLAG_harmony_regexp_lookbehind = lookbehind; + FLAG_harmony_unicode_regexps = true; + CHECK_PARSE_ERROR("?"); CheckParseEq("abc", "'abc'"); @@ -191,6 +197,13 @@ TEST(Parser) { CheckParseEq("foo|(bar|baz)|quux", "(| 'foo' (^ (| 'bar' 'baz')) 'quux')"); CheckParseEq("foo(?=bar)baz", "(: 'foo' (-> + 'bar') 'baz')"); CheckParseEq("foo(?!bar)baz", "(: 'foo' (-> - 'bar') 'baz')"); + if (lookbehind) { + CheckParseEq("foo(?<=bar)baz", "(: 'foo' (<- + 'bar') 'baz')"); + CheckParseEq("foo(?<!bar)baz", "(: 'foo' (<- - 'bar') 'baz')"); + } else { + CHECK_PARSE_ERROR("foo(?<=bar)baz"); + CHECK_PARSE_ERROR("foo(?<!bar)baz"); + } CheckParseEq("()", "(^ %)"); CheckParseEq("(?=)", "(-> + %)"); CheckParseEq("[]", "^[\\x00-\\uffff]"); // Doesn't compile on windows @@ -262,14 +275,22 @@ TEST(Parser) { CheckParseEq("(a)\\1", "(: (^ 'a') (<- 1))"); CheckParseEq("(a\\1)", "(^ 'a')"); CheckParseEq("(\\1a)", "(^ 'a')"); + CheckParseEq("(\\2)(\\1)", "(: (^ (<- 2)) (^ (<- 1)))"); CheckParseEq("(?=a)?a", "'a'"); CheckParseEq("(?=a){0,10}a", "'a'"); CheckParseEq("(?=a){1,10}a", "(: (-> + 'a') 'a')"); CheckParseEq("(?=a){9,10}a", "(: (-> + 'a') 'a')"); CheckParseEq("(?!a)?a", "'a'"); - CheckParseEq("\\1(a)", "(^ 'a')"); + CheckParseEq("\\1(a)", "(: (<- 1) (^ 'a'))"); CheckParseEq("(?!(a))\\1", "(: (-> - (^ 'a')) (<- 1))"); - CheckParseEq("(?!\\1(a\\1)\\1)\\1", "(: (-> - (: (^ 'a') (<- 1))) (<- 1))"); + CheckParseEq("(?!\\1(a\\1)\\1)\\1", + "(: (-> - (: (<- 1) (^ 'a') (<- 1))) (<- 1))"); + CheckParseEq("\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1", + "(: (<- 1) (<- 2) (^ (: 'a' (^ 'b') (<- 2))) (<- 1))"); + if (lookbehind) { + CheckParseEq("\\1\\2(a(?<=\\1(b\\1\\2))\\2)\\1", + "(: (<- 1) (<- 2) (^ (: 'a' (<- + (^ 'b')) (<- 2))) (<- 1))"); + } CheckParseEq("[\\0]", "[\\x00]"); CheckParseEq("[\\11]", "[\\x09]"); CheckParseEq("[\\11a]", "[\\x09 a]"); @@ -286,6 +307,15 @@ TEST(Parser) { CheckParseEq("\\u003z", "'u003z'"); CheckParseEq("foo[z]*", "(: 'foo' (# 0 - g [z]))"); + // Unicode regexps + CheckParseEq("\\u{12345}", "'\\ud808\\udf45'", true); + CheckParseEq("\\u{12345}\\u{23456}", "(! '\\ud808\\udf45' '\\ud84d\\udc56')", + true); + CheckParseEq("\\u{12345}|\\u{23456}", "(| '\\ud808\\udf45' '\\ud84d\\udc56')", + true); + CheckParseEq("\\u{12345}{3}", "(# 3 3 g '\\ud808\\udf45')", true); + CheckParseEq("\\u{12345}*", "(# 0 - g '\\ud808\\udf45')", true); + CHECK_SIMPLE("", false); CHECK_SIMPLE("a", true); CHECK_SIMPLE("a|b", false); @@ -361,8 +391,8 @@ TEST(Parser) { CHECK_MIN_MAX("(?:ab)|cde", 2, 3); CHECK_MIN_MAX("(ab)", 2, 2); CHECK_MIN_MAX("(ab|cde)", 2, 3); - CHECK_MIN_MAX("(ab)\\1", 2, 4); - CHECK_MIN_MAX("(ab|cde)\\1", 2, 6); + CHECK_MIN_MAX("(ab)\\1", 2, RegExpTree::kInfinity); + CHECK_MIN_MAX("(ab|cde)\\1", 2, RegExpTree::kInfinity); CHECK_MIN_MAX("(?:ab)?", 0, 2); CHECK_MIN_MAX("(?:ab)*", 0, RegExpTree::kInfinity); CHECK_MIN_MAX("(?:ab)+", 2, RegExpTree::kInfinity); @@ -400,6 +430,16 @@ TEST(Parser) { } +TEST(ParserWithLookbehind) { + TestRegExpParser(true); // Lookbehind enabled. +} + + +TEST(ParserWithoutLookbehind) { + TestRegExpParser(true); // Lookbehind enabled. +} + + TEST(ParserRegression) { CheckParseEq("[A-Z$-][x]", "(! [A-Z $ -] [x])"); CheckParseEq("a{3,4*}", "(: 'a{3,' (# 0 - g '4') '}')"); @@ -790,7 +830,7 @@ TEST(MacroAssemblerNativeSimple) { Label fail, backtrack; m.PushBacktrack(&fail); - m.CheckNotAtStart(NULL); + m.CheckNotAtStart(0, NULL); m.LoadCurrentCharacter(2, NULL); m.CheckNotCharacter('o', NULL); m.LoadCurrentCharacter(1, NULL, false); @@ -857,7 +897,7 @@ TEST(MacroAssemblerNativeSimpleUC16) { Label fail, backtrack; m.PushBacktrack(&fail); - m.CheckNotAtStart(NULL); + m.CheckNotAtStart(0, NULL); m.LoadCurrentCharacter(2, NULL); m.CheckNotCharacter('o', NULL); m.LoadCurrentCharacter(1, NULL, false); @@ -973,12 +1013,12 @@ TEST(MacroAssemblerNativeBackReferenceLATIN1) { m.AdvanceCurrentPosition(2); m.WriteCurrentPositionToRegister(1, 0); Label nomatch; - m.CheckNotBackReference(0, &nomatch); + m.CheckNotBackReference(0, false, &nomatch); m.Fail(); m.Bind(&nomatch); m.AdvanceCurrentPosition(2); Label missing_match; - m.CheckNotBackReference(0, &missing_match); + m.CheckNotBackReference(0, false, &missing_match); m.WriteCurrentPositionToRegister(2, 0); m.Succeed(); m.Bind(&missing_match); @@ -1023,12 +1063,12 @@ TEST(MacroAssemblerNativeBackReferenceUC16) { m.AdvanceCurrentPosition(2); m.WriteCurrentPositionToRegister(1, 0); Label nomatch; - m.CheckNotBackReference(0, &nomatch); + m.CheckNotBackReference(0, false, &nomatch); m.Fail(); m.Bind(&nomatch); m.AdvanceCurrentPosition(2); Label missing_match; - m.CheckNotBackReference(0, &missing_match); + m.CheckNotBackReference(0, false, &missing_match); m.WriteCurrentPositionToRegister(2, 0); m.Succeed(); m.Bind(&missing_match); @@ -1073,7 +1113,7 @@ TEST(MacroAssemblernativeAtStart) { 0); Label not_at_start, newline, fail; - m.CheckNotAtStart(¬_at_start); + m.CheckNotAtStart(0, ¬_at_start); // Check that prevchar = '\n' and current = 'f'. m.CheckCharacter('\n', &newline); m.Bind(&fail); @@ -1138,16 +1178,16 @@ TEST(MacroAssemblerNativeBackRefNoCase) { m.WriteCurrentPositionToRegister(2, 0); m.AdvanceCurrentPosition(3); m.WriteCurrentPositionToRegister(3, 0); - m.CheckNotBackReferenceIgnoreCase(2, &fail); // Match "AbC". - m.CheckNotBackReferenceIgnoreCase(2, &fail); // Match "ABC". + m.CheckNotBackReferenceIgnoreCase(2, false, &fail); // Match "AbC". + m.CheckNotBackReferenceIgnoreCase(2, false, &fail); // Match "ABC". Label expected_fail; - m.CheckNotBackReferenceIgnoreCase(2, &expected_fail); + m.CheckNotBackReferenceIgnoreCase(2, false, &expected_fail); m.Bind(&fail); m.Fail(); m.Bind(&expected_fail); m.AdvanceCurrentPosition(3); // Skip "xYz" - m.CheckNotBackReferenceIgnoreCase(2, &succ); + m.CheckNotBackReferenceIgnoreCase(2, false, &succ); m.Fail(); m.Bind(&succ); @@ -1339,7 +1379,7 @@ TEST(MacroAssemblerNativeLotsOfRegisters) { m.WriteCurrentPositionToRegister(0, 0); m.WriteCurrentPositionToRegister(1, 1); Label done; - m.CheckNotBackReference(0, &done); // Performs a system-stack push. + m.CheckNotBackReference(0, false, &done); // Performs a system-stack push. m.Bind(&done); m.PushRegister(large_number, RegExpMacroAssembler::kNoStackLimitCheck); m.PopRegister(1); @@ -1388,7 +1428,7 @@ TEST(MacroAssembler) { m.Fail(); m.Bind(&start); m.PushBacktrack(&fail); - m.CheckNotAtStart(NULL); + m.CheckNotAtStart(0, NULL); m.LoadCurrentCharacter(0, NULL); m.CheckNotCharacter('f', NULL); m.LoadCurrentCharacter(1, NULL); @@ -1678,26 +1718,26 @@ TEST(CanonicalizeCharacterSets) { list->Add(CharacterRange(30, 40), &zone); list->Add(CharacterRange(50, 60), &zone); set.Canonicalize(); - DCHECK_EQ(3, list->length()); - DCHECK_EQ(10, list->at(0).from()); - DCHECK_EQ(20, list->at(0).to()); - DCHECK_EQ(30, list->at(1).from()); - DCHECK_EQ(40, list->at(1).to()); - DCHECK_EQ(50, list->at(2).from()); - DCHECK_EQ(60, list->at(2).to()); + CHECK_EQ(3, list->length()); + CHECK_EQ(10, list->at(0).from()); + CHECK_EQ(20, list->at(0).to()); + CHECK_EQ(30, list->at(1).from()); + CHECK_EQ(40, list->at(1).to()); + CHECK_EQ(50, list->at(2).from()); + CHECK_EQ(60, list->at(2).to()); list->Rewind(0); list->Add(CharacterRange(10, 20), &zone); list->Add(CharacterRange(50, 60), &zone); list->Add(CharacterRange(30, 40), &zone); set.Canonicalize(); - DCHECK_EQ(3, list->length()); - DCHECK_EQ(10, list->at(0).from()); - DCHECK_EQ(20, list->at(0).to()); - DCHECK_EQ(30, list->at(1).from()); - DCHECK_EQ(40, list->at(1).to()); - DCHECK_EQ(50, list->at(2).from()); - DCHECK_EQ(60, list->at(2).to()); + CHECK_EQ(3, list->length()); + CHECK_EQ(10, list->at(0).from()); + CHECK_EQ(20, list->at(0).to()); + CHECK_EQ(30, list->at(1).from()); + CHECK_EQ(40, list->at(1).to()); + CHECK_EQ(50, list->at(2).from()); + CHECK_EQ(60, list->at(2).to()); list->Rewind(0); list->Add(CharacterRange(30, 40), &zone); @@ -1706,26 +1746,26 @@ TEST(CanonicalizeCharacterSets) { list->Add(CharacterRange(100, 100), &zone); list->Add(CharacterRange(1, 1), &zone); set.Canonicalize(); - DCHECK_EQ(5, list->length()); - DCHECK_EQ(1, list->at(0).from()); - DCHECK_EQ(1, list->at(0).to()); - DCHECK_EQ(10, list->at(1).from()); - DCHECK_EQ(20, list->at(1).to()); - DCHECK_EQ(25, list->at(2).from()); - DCHECK_EQ(25, list->at(2).to()); - DCHECK_EQ(30, list->at(3).from()); - DCHECK_EQ(40, list->at(3).to()); - DCHECK_EQ(100, list->at(4).from()); - DCHECK_EQ(100, list->at(4).to()); + CHECK_EQ(5, list->length()); + CHECK_EQ(1, list->at(0).from()); + CHECK_EQ(1, list->at(0).to()); + CHECK_EQ(10, list->at(1).from()); + CHECK_EQ(20, list->at(1).to()); + CHECK_EQ(25, list->at(2).from()); + CHECK_EQ(25, list->at(2).to()); + CHECK_EQ(30, list->at(3).from()); + CHECK_EQ(40, list->at(3).to()); + CHECK_EQ(100, list->at(4).from()); + CHECK_EQ(100, list->at(4).to()); list->Rewind(0); list->Add(CharacterRange(10, 19), &zone); list->Add(CharacterRange(21, 30), &zone); list->Add(CharacterRange(20, 20), &zone); set.Canonicalize(); - DCHECK_EQ(1, list->length()); - DCHECK_EQ(10, list->at(0).from()); - DCHECK_EQ(30, list->at(0).to()); + CHECK_EQ(1, list->length()); + CHECK_EQ(10, list->at(0).from()); + CHECK_EQ(30, list->at(0).to()); } @@ -1807,8 +1847,8 @@ TEST(CharacterRangeMerge) { offset += 9; } - DCHECK(CharacterRange::IsCanonical(&l1)); - DCHECK(CharacterRange::IsCanonical(&l2)); + CHECK(CharacterRange::IsCanonical(&l1)); + CHECK(CharacterRange::IsCanonical(&l2)); ZoneList<CharacterRange> first_only(4, &zone); ZoneList<CharacterRange> second_only(4, &zone); @@ -1819,3 +1859,82 @@ TEST(CharacterRangeMerge) { TEST(Graph) { Execute("\\b\\w+\\b", false, true, true); } + + +namespace { + +int* global_use_counts = NULL; + +void MockUseCounterCallback(v8::Isolate* isolate, + v8::Isolate::UseCounterFeature feature) { + ++global_use_counts[feature]; +} +} + + +// Test that ES2015 RegExp compatibility fixes are in place, that they +// are not overly broad, and the appropriate UseCounters are incremented +TEST(UseCountRegExp) { + i::FLAG_harmony_regexps = true; + v8::Isolate* isolate = CcTest::isolate(); + v8::HandleScope scope(isolate); + LocalContext env; + int use_counts[v8::Isolate::kUseCounterFeatureCount] = {}; + global_use_counts = use_counts; + CcTest::isolate()->SetUseCounterCallback(MockUseCounterCallback); + + // Compat fix: RegExp.prototype.sticky == undefined; UseCounter tracks it + v8::Local<v8::Value> resultSticky = CompileRun("RegExp.prototype.sticky"); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeStickyGetter]); + CHECK_EQ(0, use_counts[v8::Isolate::kRegExpPrototypeToString]); + CHECK(resultSticky->IsUndefined()); + + // re.sticky has approriate value and doesn't touch UseCounter + v8::Local<v8::Value> resultReSticky = CompileRun("/a/.sticky"); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeStickyGetter]); + CHECK_EQ(0, use_counts[v8::Isolate::kRegExpPrototypeToString]); + CHECK(resultReSticky->IsFalse()); + + // When the getter is caleld on another object, throw an exception + // and don't increment the UseCounter + v8::Local<v8::Value> resultStickyError = CompileRun( + "var exception;" + "try { " + " Object.getOwnPropertyDescriptor(RegExp.prototype, 'sticky')" + " .get.call(null);" + "} catch (e) {" + " exception = e;" + "}" + "exception"); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeStickyGetter]); + CHECK_EQ(0, use_counts[v8::Isolate::kRegExpPrototypeToString]); + CHECK(resultStickyError->IsObject()); + + // RegExp.prototype.toString() returns '/(?:)/' as a compatibility fix; + // a UseCounter is incremented to track it. + v8::Local<v8::Value> resultToString = + CompileRun("RegExp.prototype.toString().length"); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeStickyGetter]); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]); + CHECK(resultToString->IsInt32()); + CHECK_EQ(6, + resultToString->Int32Value(isolate->GetCurrentContext()).FromJust()); + + // .toString() works on normal RegExps + v8::Local<v8::Value> resultReToString = CompileRun("/a/.toString().length"); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeStickyGetter]); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]); + CHECK(resultReToString->IsInt32()); + CHECK_EQ( + 3, resultReToString->Int32Value(isolate->GetCurrentContext()).FromJust()); + + // .toString() throws on non-RegExps that aren't RegExp.prototype + v8::Local<v8::Value> resultToStringError = CompileRun( + "var exception;" + "try { RegExp.prototype.toString.call(null) }" + "catch (e) { exception = e; }" + "exception"); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeStickyGetter]); + CHECK_EQ(1, use_counts[v8::Isolate::kRegExpPrototypeToString]); + CHECK(resultToStringError->IsObject()); +} |