Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: src/jsregexp.cc

Issue 567313003: RegExp: Add support for the ES6-proposed sticky flag (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add tests Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « src/jsregexp.h ('k') | src/objects.h » ('j') | src/regexp.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/ast.h" 7 #include "src/ast.h"
8 #include "src/base/platform/platform.h" 8 #include "src/base/platform/platform.h"
9 #include "src/compilation-cache.h" 9 #include "src/compilation-cache.h"
10 #include "src/compiler.h" 10 #include "src/compiler.h"
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
63 switch (str->Get(i)) { 63 switch (str->Get(i)) {
64 case 'i': 64 case 'i':
65 flags |= JSRegExp::IGNORE_CASE; 65 flags |= JSRegExp::IGNORE_CASE;
66 break; 66 break;
67 case 'g': 67 case 'g':
68 flags |= JSRegExp::GLOBAL; 68 flags |= JSRegExp::GLOBAL;
69 break; 69 break;
70 case 'm': 70 case 'm':
71 flags |= JSRegExp::MULTILINE; 71 flags |= JSRegExp::MULTILINE;
72 break; 72 break;
73 case 'y':
74 if (FLAG_harmony_regexps) flags |= JSRegExp::STICKY;
75 break;
73 } 76 }
74 } 77 }
75 return JSRegExp::Flags(flags); 78 return JSRegExp::Flags(flags);
76 } 79 }
77 80
78 81
79 MUST_USE_RESULT 82 MUST_USE_RESULT
80 static inline MaybeHandle<Object> ThrowRegExpException( 83 static inline MaybeHandle<Object> ThrowRegExpException(
81 Handle<JSRegExp> re, 84 Handle<JSRegExp> re,
82 Handle<String> pattern, 85 Handle<String> pattern,
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 return ThrowRegExpException(re, 181 return ThrowRegExpException(re,
179 pattern, 182 pattern,
180 parse_result.error, 183 parse_result.error,
181 "malformed_regexp"); 184 "malformed_regexp");
182 } 185 }
183 186
184 bool has_been_compiled = false; 187 bool has_been_compiled = false;
185 188
186 if (parse_result.simple && 189 if (parse_result.simple &&
187 !flags.is_ignore_case() && 190 !flags.is_ignore_case() &&
191 !flags.is_sticky() &&
188 !HasFewDifferentCharacters(pattern)) { 192 !HasFewDifferentCharacters(pattern)) {
189 // Parse-tree is a single atom that is equal to the pattern. 193 // Parse-tree is a single atom that is equal to the pattern.
190 AtomCompile(re, pattern, flags, pattern); 194 AtomCompile(re, pattern, flags, pattern);
191 has_been_compiled = true; 195 has_been_compiled = true;
192 } else if (parse_result.tree->IsAtom() && 196 } else if (parse_result.tree->IsAtom() &&
193 !flags.is_ignore_case() && 197 !flags.is_ignore_case() &&
198 !flags.is_sticky() &&
194 parse_result.capture_count == 0) { 199 parse_result.capture_count == 0) {
195 RegExpAtom* atom = parse_result.tree->AsAtom(); 200 RegExpAtom* atom = parse_result.tree->AsAtom();
196 Vector<const uc16> atom_pattern = atom->data(); 201 Vector<const uc16> atom_pattern = atom->data();
197 Handle<String> atom_string; 202 Handle<String> atom_string;
198 ASSIGN_RETURN_ON_EXCEPTION( 203 ASSIGN_RETURN_ON_EXCEPTION(
199 isolate, atom_string, 204 isolate, atom_string,
200 isolate->factory()->NewStringFromTwoByte(atom_pattern), 205 isolate->factory()->NewStringFromTwoByte(atom_pattern),
201 Object); 206 Object);
202 if (!HasFewDifferentCharacters(atom_string)) { 207 if (!HasFewDifferentCharacters(atom_string)) {
203 AtomCompile(re, pattern, flags, atom_string); 208 AtomCompile(re, pattern, flags, atom_string);
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 // Throw an exception if we fail to parse the pattern. 428 // Throw an exception if we fail to parse the pattern.
424 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once. 429 // THIS SHOULD NOT HAPPEN. We already pre-parsed it successfully once.
425 USE(ThrowRegExpException(re, 430 USE(ThrowRegExpException(re,
426 pattern, 431 pattern,
427 compile_data.error, 432 compile_data.error,
428 "malformed_regexp")); 433 "malformed_regexp"));
429 return false; 434 return false;
430 } 435 }
431 RegExpEngine::CompilationResult result = RegExpEngine::Compile( 436 RegExpEngine::CompilationResult result = RegExpEngine::Compile(
432 &compile_data, flags.is_ignore_case(), flags.is_global(), 437 &compile_data, flags.is_ignore_case(), flags.is_global(),
433 flags.is_multiline(), pattern, sample_subject, is_one_byte, &zone); 438 flags.is_multiline(), flags.is_sticky(), pattern, sample_subject,
439 is_one_byte, &zone);
434 if (result.error_message != NULL) { 440 if (result.error_message != NULL) {
435 // Unable to compile regexp. 441 // Unable to compile regexp.
436 Handle<String> error_message = isolate->factory()->NewStringFromUtf8( 442 Handle<String> error_message = isolate->factory()->NewStringFromUtf8(
437 CStrVector(result.error_message)).ToHandleChecked(); 443 CStrVector(result.error_message)).ToHandleChecked();
438 CreateRegExpErrorObjectAndThrow(re, error_message, isolate); 444 CreateRegExpErrorObjectAndThrow(re, error_message, isolate);
439 return false; 445 return false;
440 } 446 }
441 447
442 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data())); 448 Handle<FixedArray> data = Handle<FixedArray>(FixedArray::cast(re->data()));
443 data->set(JSRegExp::code_index(is_one_byte), result.code); 449 data->set(JSRegExp::code_index(is_one_byte), result.code);
(...skipping 5574 matching lines...) Expand 10 before | Expand all | Expand 10 after
6018 6024
6019 6025
6020 void DispatchTableConstructor::VisitAction(ActionNode* that) { 6026 void DispatchTableConstructor::VisitAction(ActionNode* that) {
6021 RegExpNode* target = that->on_success(); 6027 RegExpNode* target = that->on_success();
6022 target->Accept(this); 6028 target->Accept(this);
6023 } 6029 }
6024 6030
6025 6031
6026 RegExpEngine::CompilationResult RegExpEngine::Compile( 6032 RegExpEngine::CompilationResult RegExpEngine::Compile(
6027 RegExpCompileData* data, bool ignore_case, bool is_global, 6033 RegExpCompileData* data, bool ignore_case, bool is_global,
6028 bool is_multiline, Handle<String> pattern, Handle<String> sample_subject, 6034 bool is_multiline, bool is_sticky, Handle<String> pattern,
6029 bool is_one_byte, Zone* zone) { 6035 Handle<String> sample_subject, bool is_one_byte, Zone* zone) {
6030 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) { 6036 if ((data->capture_count + 1) * 2 - 1 > RegExpMacroAssembler::kMaxRegister) {
6031 return IrregexpRegExpTooBig(zone->isolate()); 6037 return IrregexpRegExpTooBig(zone->isolate());
6032 } 6038 }
6033 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone); 6039 RegExpCompiler compiler(data->capture_count, ignore_case, is_one_byte, zone);
6034 6040
6035 // Sample some characters from the middle of the string. 6041 // Sample some characters from the middle of the string.
6036 static const int kSampleSize = 128; 6042 static const int kSampleSize = 128;
6037 6043
6038 sample_subject = String::Flatten(sample_subject); 6044 sample_subject = String::Flatten(sample_subject);
6039 int chars_sampled = 0; 6045 int chars_sampled = 0;
6040 int half_way = (sample_subject->length() - kSampleSize) / 2; 6046 int half_way = (sample_subject->length() - kSampleSize) / 2;
6041 for (int i = Max(0, half_way); 6047 for (int i = Max(0, half_way);
6042 i < sample_subject->length() && chars_sampled < kSampleSize; 6048 i < sample_subject->length() && chars_sampled < kSampleSize;
6043 i++, chars_sampled++) { 6049 i++, chars_sampled++) {
6044 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i)); 6050 compiler.frequency_collator()->CountCharacter(sample_subject->Get(i));
6045 } 6051 }
6046 6052
6047 // Wrap the body of the regexp in capture #0. 6053 // Wrap the body of the regexp in capture #0.
6048 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree, 6054 RegExpNode* captured_body = RegExpCapture::ToNode(data->tree,
6049 0, 6055 0,
6050 &compiler, 6056 &compiler,
6051 compiler.accept()); 6057 compiler.accept());
6052 RegExpNode* node = captured_body; 6058 RegExpNode* node = captured_body;
6053 bool is_end_anchored = data->tree->IsAnchoredAtEnd(); 6059 bool is_end_anchored = data->tree->IsAnchoredAtEnd();
6054 bool is_start_anchored = data->tree->IsAnchoredAtStart(); 6060 bool is_start_anchored = data->tree->IsAnchoredAtStart();
6055 int max_length = data->tree->max_match(); 6061 int max_length = data->tree->max_match();
6056 if (!is_start_anchored) { 6062 if (!is_start_anchored && !is_sticky) {
6057 // Add a .*? at the beginning, outside the body capture, unless 6063 // Add a .*? at the beginning, outside the body capture, unless
6058 // this expression is anchored at the beginning. 6064 // this expression is anchored at the beginning.
Yang 2014/09/15 09:23:16 ... or sticky.
Erik Corry 2014/09/16 17:49:40 Done.
6059 RegExpNode* loop_node = 6065 RegExpNode* loop_node =
6060 RegExpQuantifier::ToNode(0, 6066 RegExpQuantifier::ToNode(0,
6061 RegExpTree::kInfinity, 6067 RegExpTree::kInfinity,
6062 false, 6068 false,
6063 new(zone) RegExpCharacterClass('*'), 6069 new(zone) RegExpCharacterClass('*'),
6064 &compiler, 6070 &compiler,
6065 captured_body, 6071 captured_body,
6066 data->contains_anchor); 6072 data->contains_anchor);
6067 6073
6068 if (data->contains_anchor) { 6074 if (data->contains_anchor) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
6151 } 6157 }
6152 6158
6153 return compiler.Assemble(&macro_assembler, 6159 return compiler.Assemble(&macro_assembler,
6154 node, 6160 node,
6155 data->capture_count, 6161 data->capture_count,
6156 pattern); 6162 pattern);
6157 } 6163 }
6158 6164
6159 6165
6160 }} // namespace v8::internal 6166 }} // namespace v8::internal
OLDNEW
« no previous file with comments | « src/jsregexp.h ('k') | src/objects.h » ('j') | src/regexp.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698