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

Side by Side Diff: sdk/lib/_internal/js_runtime/lib/regexp_helper.dart

Issue 2437863002: Prevent inlining of js_library core.RegExp constructor (Closed)
Patch Set: Created 4 years, 2 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
« no previous file with comments | « sdk/lib/_internal/js_runtime/lib/core_patch.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 part of _js_helper; 5 part of _js_helper;
6 6
7 // Helper method used by internal libraries. 7 // Helper method used by internal libraries.
8 regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp; 8 regExpGetNative(JSSyntaxRegExp regexp) => regexp._nativeRegExp;
9 9
10 /** 10 /**
11 * Returns a native version of the RegExp with the global flag set. 11 * Returns a native version of the RegExp with the global flag set.
12 * 12 *
13 * The RegExp's `lastIndex` property is zero when it is returned. 13 * The RegExp's `lastIndex` property is zero when it is returned.
14 * 14 *
15 * The returned regexp is shared, and its `lastIndex` property may be 15 * The returned regexp is shared, and its `lastIndex` property may be
16 * modified by other uses, so the returned regexp must be used immediately 16 * modified by other uses, so the returned regexp must be used immediately
17 * when it's returned, with no user-provided code run in between. 17 * when it's returned, with no user-provided code run in between.
18 */ 18 */
19 regExpGetGlobalNative(JSSyntaxRegExp regexp) { 19 regExpGetGlobalNative(JSSyntaxRegExp regexp) {
20 var nativeRegexp = regexp._nativeGlobalVersion; 20 var nativeRegexp = regexp._nativeGlobalVersion;
21 JS("void", "#.lastIndex = 0", nativeRegexp); 21 JS('void', '#.lastIndex = 0', nativeRegexp);
22 return nativeRegexp; 22 return nativeRegexp;
23 } 23 }
24 24
25 /** 25 /**
26 * Computes the number of captures in a regexp. 26 * Computes the number of captures in a regexp.
27 * 27 *
28 * This currently involves creating a new RegExp object with a different 28 * This currently involves creating a new RegExp object with a different
29 * source and running it against the empty string (the last part is usually 29 * source and running it against the empty string (the last part is usually
30 * fast). 30 * fast).
31 * 31 *
32 * The JSSyntaxRegExp could cache the result, and set the cache any time 32 * The JSSyntaxRegExp could cache the result, and set the cache any time
33 * it finds a match. 33 * it finds a match.
34 */ 34 */
35 int regExpCaptureCount(JSSyntaxRegExp regexp) { 35 int regExpCaptureCount(JSSyntaxRegExp regexp) {
36 var nativeAnchoredRegExp = regexp._nativeAnchoredVersion; 36 var nativeAnchoredRegExp = regexp._nativeAnchoredVersion;
37 var match = JS('JSExtendableArray', "#.exec('')", nativeAnchoredRegExp); 37 var match = JS('JSExtendableArray', '#.exec("")', nativeAnchoredRegExp);
38 // The native-anchored regexp always have one capture more than the original, 38 // The native-anchored regexp always have one capture more than the original,
39 // and always matches the empty string. 39 // and always matches the empty string.
40 return match.length - 2; 40 return match.length - 2;
41 } 41 }
42 42
43 class JSSyntaxRegExp implements RegExp { 43 class JSSyntaxRegExp implements RegExp {
44 final String pattern; 44 final String pattern;
45 final _nativeRegExp; 45 final _nativeRegExp;
46 var _nativeGlobalRegExp; 46 var _nativeGlobalRegExp;
47 var _nativeAnchoredRegExp; 47 var _nativeAnchoredRegExp;
48 48
49 String toString() => "RegExp/$pattern/"; 49 String toString() => 'RegExp/$pattern/';
50 50
51 JSSyntaxRegExp(String source, 51 JSSyntaxRegExp(String source,
52 { bool multiLine: false, 52 { bool multiLine: false,
53 bool caseSensitive: true }) 53 bool caseSensitive: true })
54 : this.pattern = source, 54 : this.pattern = source,
55 this._nativeRegExp = 55 this._nativeRegExp =
56 makeNative(source, multiLine, caseSensitive, false); 56 makeNative(source, multiLine, caseSensitive, false);
57 57
58 get _nativeGlobalVersion { 58 get _nativeGlobalVersion {
59 if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp; 59 if (_nativeGlobalRegExp != null) return _nativeGlobalRegExp;
60 return _nativeGlobalRegExp = makeNative(pattern, 60 return _nativeGlobalRegExp = makeNative(pattern,
61 _isMultiLine, 61 _isMultiLine,
62 _isCaseSensitive, 62 _isCaseSensitive,
63 true); 63 true);
64 } 64 }
65 65
66 get _nativeAnchoredVersion { 66 get _nativeAnchoredVersion {
67 if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp; 67 if (_nativeAnchoredRegExp != null) return _nativeAnchoredRegExp;
68 // An "anchored version" of a regexp is created by adding "|()" to the 68 // An "anchored version" of a regexp is created by adding "|()" to the
69 // source. This means that the regexp always matches at the first position 69 // source. This means that the regexp always matches at the first position
70 // that it tries, and you can see if the original regexp matched, or it 70 // that it tries, and you can see if the original regexp matched, or it
71 // was the added zero-width match that matched, by looking at the last 71 // was the added zero-width match that matched, by looking at the last
72 // capture. If it is a String, the match participated, otherwise it didn't. 72 // capture. If it is a String, the match participated, otherwise it didn't.
73 return _nativeAnchoredRegExp = makeNative("$pattern|()", 73 return _nativeAnchoredRegExp = makeNative('$pattern|()',
74 _isMultiLine, 74 _isMultiLine,
75 _isCaseSensitive, 75 _isCaseSensitive,
76 true); 76 true);
77 } 77 }
78 78
79 bool get _isMultiLine => JS("bool", "#.multiline", _nativeRegExp); 79 bool get _isMultiLine => JS('bool', '#.multiline', _nativeRegExp);
80 bool get _isCaseSensitive => JS("bool", "!#.ignoreCase", _nativeRegExp); 80 bool get _isCaseSensitive => JS('bool', '!#.ignoreCase', _nativeRegExp);
81 81
82 static makeNative( 82 static makeNative(
83 String source, bool multiLine, bool caseSensitive, bool global) { 83 String source, bool multiLine, bool caseSensitive, bool global) {
84 checkString(source); 84 checkString(source);
85 String m = multiLine == true ? 'm' : ''; 85 String m = multiLine == true ? 'm' : '';
86 String i = caseSensitive == true ? '' : 'i'; 86 String i = caseSensitive == true ? '' : 'i';
87 String g = global ? 'g' : ''; 87 String g = global ? 'g' : '';
88 // We're using the JavaScript's try catch instead of the Dart one to avoid 88 // We're using the JavaScript's try catch instead of the Dart one to avoid
89 // dragging in Dart runtime support just because of using RegExp. 89 // dragging in Dart runtime support just because of using RegExp.
90 var regexp = JS('', 90 var regexp = JS('',
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 checkString(string); 128 checkString(string);
129 checkInt(start); 129 checkInt(start);
130 if (start < 0 || start > string.length) { 130 if (start < 0 || start > string.length) {
131 throw new RangeError.range(start, 0, string.length); 131 throw new RangeError.range(start, 0, string.length);
132 } 132 }
133 return new _AllMatchesIterable(this, string, start); 133 return new _AllMatchesIterable(this, string, start);
134 } 134 }
135 135
136 Match _execGlobal(String string, int start) { 136 Match _execGlobal(String string, int start) {
137 Object regexp = _nativeGlobalVersion; 137 Object regexp = _nativeGlobalVersion;
138 JS("void", "#.lastIndex = #", regexp, start); 138 JS('void', '#.lastIndex = #', regexp, start);
139 List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string); 139 List match = JS('JSExtendableArray|Null', '#.exec(#)', regexp, string);
140 if (match == null) return null; 140 if (match == null) return null;
141 return new _MatchImplementation(this, match); 141 return new _MatchImplementation(this, match);
142 } 142 }
143 143
144 Match _execAnchored(String string, int start) { 144 Match _execAnchored(String string, int start) {
145 Object regexp = _nativeAnchoredVersion; 145 Object regexp = _nativeAnchoredVersion;
146 JS("void", "#.lastIndex = #", regexp, start); 146 JS('void', '#.lastIndex = #', regexp, start);
147 List match = JS("JSExtendableArray|Null", "#.exec(#)", regexp, string); 147 List match = JS('JSExtendableArray|Null', '#.exec(#)', regexp, string);
148 if (match == null) return null; 148 if (match == null) return null;
149 // If the last capture group participated, the original regexp did not 149 // If the last capture group participated, the original regexp did not
150 // match at the start position. 150 // match at the start position.
151 if (match[match.length - 1] != null) return null; 151 if (match.removeLast() != null) return null;
152 match.length -= 1;
153 return new _MatchImplementation(this, match); 152 return new _MatchImplementation(this, match);
154 } 153 }
155 154
156 Match matchAsPrefix(String string, [int start = 0]) { 155 Match matchAsPrefix(String string, [int start = 0]) {
157 if (start < 0 || start > string.length) { 156 if (start < 0 || start > string.length) {
158 throw new RangeError.range(start, 0, string.length); 157 throw new RangeError.range(start, 0, string.length);
159 } 158 }
160 return _execAnchored(string, start); 159 return _execAnchored(string, start);
161 } 160 }
162 161
163 bool get isMultiLine => _isMultiLine; 162 bool get isMultiLine => _isMultiLine;
164 bool get isCaseSensitive => _isCaseSensitive; 163 bool get isCaseSensitive => _isCaseSensitive;
165 } 164 }
166 165
167 class _MatchImplementation implements Match { 166 class _MatchImplementation implements Match {
168 final Pattern pattern; 167 final Pattern pattern;
169 // Contains a JS RegExp match object. 168 // Contains a JS RegExp match object.
170 // It is an Array of String values with extra "index" and "input" properties. 169 // It is an Array of String values with extra 'index' and 'input' properties.
171 final List<String> _match; 170 final List<String> _match;
172 171
173 _MatchImplementation(this.pattern, this._match) { 172 _MatchImplementation(this.pattern, this._match) {
174 assert(JS("var", "#.input", _match) is String); 173 assert(JS('var', '#.input', _match) is String);
175 assert(JS("var", "#.index", _match) is int); 174 assert(JS('var', '#.index', _match) is int);
176 } 175 }
177 176
178 String get input => JS("String", "#.input", _match); 177 String get input => JS('String', '#.input', _match);
179 int get start => JS("int", "#.index", _match); 178
180 int get end => start + _match[0].length; 179 int get start =>
180 JS('returns:int;depends:none;effects:none;gvn:true', '#.index', _match);
181
182 int get end =>
183 start +
184 JS('returns:int;depends:none;effects:none;gvn:true', '#[0].length',
185 _match);
181 186
182 String group(int index) => _match[index]; 187 String group(int index) => _match[index];
183 String operator [](int index) => group(index); 188 String operator [](int index) => group(index);
184 int get groupCount => _match.length - 1; 189 int get groupCount => _match.length - 1;
185 190
186 List<String> groups(List<int> groups) { 191 List<String> groups(List<int> groups) {
187 List<String> out = []; 192 List<String> out = [];
188 for (int i in groups) { 193 for (int i in groups) {
189 out.add(group(i)); 194 out.add(group(i));
190 } 195 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 _current = null; 234 _current = null;
230 _string = null; // Marks iteration as ended. 235 _string = null; // Marks iteration as ended.
231 return false; 236 return false;
232 } 237 }
233 } 238 }
234 239
235 /** Find the first match of [regExp] in [string] at or after [start]. */ 240 /** Find the first match of [regExp] in [string] at or after [start]. */
236 Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) { 241 Match firstMatchAfter(JSSyntaxRegExp regExp, String string, int start) {
237 return regExp._execGlobal(string, start); 242 return regExp._execGlobal(string, start);
238 } 243 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/js_runtime/lib/core_patch.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698