re2 1.17.2 → 1.17.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/replace.cc +44 -41
- package/package.json +1 -1
- package/tests/test_replace.js +278 -227
package/README.md
CHANGED
|
@@ -347,6 +347,7 @@ console.log('re2_res : ' + re2_res); // prints: re2_res : abc,a,b,c
|
|
|
347
347
|
|
|
348
348
|
## Release history
|
|
349
349
|
|
|
350
|
+
- 1.17.3 *Fixed bug with zero-length replacements.*
|
|
350
351
|
- 1.17.2 *Added support for the enhanced local mirroring by updating [install-artifact-from-github](https://github.com/uhop/install-artifact-from-github).*
|
|
351
352
|
- 1.17.1 *Fix for `lastIndex` for U+10000 - U+10FFFF UTF characters. Thx, [omg](https://github.com/omg).*
|
|
352
353
|
- 1.17.0 *Updated GYP, added support for Node 17, updated deps.*
|
package/lib/replace.cc
CHANGED
|
@@ -228,7 +228,9 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
|
|
|
228
228
|
{
|
|
229
229
|
size_t s = getUtf8CharSize(data[lastIndex]);
|
|
230
230
|
lastIndex += s;
|
|
231
|
-
if (s == 4 && n >= 2)
|
|
231
|
+
if (s == 4 && n >= 2) {
|
|
232
|
+
--n; // this utf8 character will take two utf16 characters
|
|
233
|
+
}
|
|
232
234
|
// the decrement above is protected to avoid an overflow of an unsigned integer
|
|
233
235
|
}
|
|
234
236
|
}
|
|
@@ -245,28 +247,30 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
|
|
|
245
247
|
while (lastIndex <= size && re2->regexp.Match(str, lastIndex, size, anchor, &groups[0], groups.size()))
|
|
246
248
|
{
|
|
247
249
|
noMatch = false;
|
|
250
|
+
auto offset = match.data() - data;
|
|
248
251
|
if (!re2->global && re2->sticky)
|
|
249
252
|
{
|
|
250
|
-
re2->lastIndex += replacee.isBuffer ?
|
|
253
|
+
re2->lastIndex += replacee.isBuffer ? offset + match.size() - lastIndex : getUtf16Length(data + lastIndex, match.data() + match.size());
|
|
254
|
+
}
|
|
255
|
+
if (match.data() == data || offset > static_cast<long>(lastIndex))
|
|
256
|
+
{
|
|
257
|
+
result += std::string(data + lastIndex, offset - lastIndex);
|
|
251
258
|
}
|
|
259
|
+
result += replace(replacer, replacer_size, groups, str, namedGroups);
|
|
252
260
|
if (match.size())
|
|
253
261
|
{
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
262
|
+
lastIndex = offset + match.size();
|
|
263
|
+
}
|
|
264
|
+
else if (offset < size)
|
|
265
|
+
{
|
|
266
|
+
auto sym_size = getUtf8CharSize(data[offset]);
|
|
267
|
+
result.append(data + offset, sym_size);
|
|
268
|
+
lastIndex = offset + sym_size;
|
|
260
269
|
}
|
|
261
270
|
else
|
|
262
271
|
{
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
if (lastIndex < size)
|
|
266
|
-
{
|
|
267
|
-
result.append(data + lastIndex, sym_size);
|
|
268
|
-
}
|
|
269
|
-
lastIndex += sym_size;
|
|
272
|
+
lastIndex = size;
|
|
273
|
+
break;
|
|
270
274
|
}
|
|
271
275
|
if (!re2->global)
|
|
272
276
|
{
|
|
@@ -295,7 +299,7 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
|
|
|
295
299
|
|
|
296
300
|
inline Nan::Maybe<std::string> replace(const Nan::Callback *replacer, const std::vector<re2::StringPiece> &groups, const re2::StringPiece &str, const v8::Local<v8::Value> &input, bool useBuffers, const std::map<std::string, int> &namedGroups)
|
|
297
301
|
{
|
|
298
|
-
std::vector<v8::Local<v8::Value
|
|
302
|
+
std::vector<v8::Local<v8::Value> > argv;
|
|
299
303
|
|
|
300
304
|
auto context = Nan::GetCurrentContext();
|
|
301
305
|
|
|
@@ -377,7 +381,9 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
|
|
|
377
381
|
{
|
|
378
382
|
size_t s = getUtf8CharSize(data[lastIndex]);
|
|
379
383
|
lastIndex += s;
|
|
380
|
-
if (s == 4 && n >= 2)
|
|
384
|
+
if (s == 4 && n >= 2) {
|
|
385
|
+
--n; // this utf8 character will take two utf16 characters
|
|
386
|
+
}
|
|
381
387
|
// the decrement above is protected to avoid an overflow of an unsigned integer
|
|
382
388
|
}
|
|
383
389
|
}
|
|
@@ -396,38 +402,35 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
|
|
|
396
402
|
while (lastIndex <= size && re2->regexp.Match(str, lastIndex, size, anchor, &groups[0], groups.size()))
|
|
397
403
|
{
|
|
398
404
|
noMatch = false;
|
|
405
|
+
auto offset = match.data() - data;
|
|
399
406
|
if (!re2->global && re2->sticky)
|
|
400
407
|
{
|
|
401
|
-
re2->lastIndex += replacee.isBuffer ?
|
|
408
|
+
re2->lastIndex += replacee.isBuffer ? offset + match.size() - lastIndex : getUtf16Length(data + lastIndex, match.data() + match.size());
|
|
409
|
+
}
|
|
410
|
+
if (match.data() == data || offset > static_cast<long>(lastIndex))
|
|
411
|
+
{
|
|
412
|
+
result += std::string(data + lastIndex, offset - lastIndex);
|
|
402
413
|
}
|
|
414
|
+
const auto part = replace(replacer, groups, str, input, useBuffers, namedGroups);
|
|
415
|
+
if (part.IsNothing())
|
|
416
|
+
{
|
|
417
|
+
return part;
|
|
418
|
+
}
|
|
419
|
+
result += part.FromJust();
|
|
403
420
|
if (match.size())
|
|
404
421
|
{
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
return part;
|
|
413
|
-
}
|
|
414
|
-
result += part.FromJust();
|
|
415
|
-
lastIndex = match.data() - data + match.size();
|
|
422
|
+
lastIndex = offset + match.size();
|
|
423
|
+
}
|
|
424
|
+
else if (offset < size)
|
|
425
|
+
{
|
|
426
|
+
auto sym_size = getUtf8CharSize(data[offset]);
|
|
427
|
+
result.append(data + offset, sym_size);
|
|
428
|
+
lastIndex = offset + sym_size;
|
|
416
429
|
}
|
|
417
430
|
else
|
|
418
431
|
{
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
{
|
|
422
|
-
return part;
|
|
423
|
-
}
|
|
424
|
-
result += part.FromJust();
|
|
425
|
-
size_t sym_size = getUtf8CharSize(data[lastIndex]);
|
|
426
|
-
if (lastIndex < size)
|
|
427
|
-
{
|
|
428
|
-
result.append(data + lastIndex, sym_size);
|
|
429
|
-
}
|
|
430
|
-
lastIndex += sym_size;
|
|
432
|
+
lastIndex = size;
|
|
433
|
+
break;
|
|
431
434
|
}
|
|
432
435
|
if (!re2->global)
|
|
433
436
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "re2",
|
|
3
|
-
"version": "1.17.
|
|
3
|
+
"version": "1.17.3",
|
|
4
4
|
"description": "Bindings for RE2: fast, safe alternative to backtracking regular expression engines.",
|
|
5
5
|
"homepage": "https://github.com/uhop/node-re2",
|
|
6
6
|
"bugs": "https://github.com/uhop/node-re2/issues",
|
package/tests/test_replace.js
CHANGED
|
@@ -1,233 +1,284 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
var unit = require("heya-unit");
|
|
5
|
-
var RE2 = require("../re2");
|
|
1
|
+
'use strict';
|
|
6
2
|
|
|
3
|
+
var unit = require('heya-unit');
|
|
4
|
+
var RE2 = require('../re2');
|
|
7
5
|
|
|
8
6
|
// tests
|
|
9
7
|
|
|
10
8
|
unit.add(module, [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
9
|
+
// These tests are copied from MDN:
|
|
10
|
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
|
|
11
|
+
|
|
12
|
+
function test_replaceString(t) {
|
|
13
|
+
'use strict';
|
|
14
|
+
|
|
15
|
+
var re = new RE2(/apples/gi);
|
|
16
|
+
var result = re.replace('Apples are round, and apples are juicy.', 'oranges');
|
|
17
|
+
eval(t.TEST("result === 'oranges are round, and oranges are juicy.'"));
|
|
18
|
+
|
|
19
|
+
re = new RE2(/xmas/i);
|
|
20
|
+
result = re.replace('Twas the night before Xmas...', 'Christmas');
|
|
21
|
+
eval(t.TEST("result === 'Twas the night before Christmas...'"));
|
|
22
|
+
|
|
23
|
+
re = new RE2(/(\w+)\s(\w+)/);
|
|
24
|
+
result = re.replace('John Smith', '$2, $1');
|
|
25
|
+
eval(t.TEST("result === 'Smith, John'"));
|
|
26
|
+
},
|
|
27
|
+
function test_replaceFunReplacer(t) {
|
|
28
|
+
'use strict';
|
|
29
|
+
|
|
30
|
+
function replacer(match, p1, p2, p3, offset, string) {
|
|
31
|
+
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
|
|
32
|
+
return [p1, p2, p3].join(' - ');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
var re = new RE2(/([^\d]*)(\d*)([^\w]*)/);
|
|
36
|
+
var result = re.replace('abc12345#$*%', replacer);
|
|
37
|
+
eval(t.TEST("result === 'abc - 12345 - #$*%'"));
|
|
38
|
+
},
|
|
39
|
+
function test_replaceFunUpper(t) {
|
|
40
|
+
'use strict';
|
|
41
|
+
|
|
42
|
+
function upperToHyphenLower(match) {
|
|
43
|
+
return '-' + match.toLowerCase();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
var re = new RE2(/[A-Z]/g);
|
|
47
|
+
var result = re.replace('borderTop', upperToHyphenLower);
|
|
48
|
+
eval(t.TEST("result === 'border-top'"));
|
|
49
|
+
},
|
|
50
|
+
function test_replaceFunConvert(t) {
|
|
51
|
+
'use strict';
|
|
52
|
+
|
|
53
|
+
function convert(str, p1, offset, s) {
|
|
54
|
+
return ((p1 - 32) * 5) / 9 + 'C';
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
var re = new RE2(/(\d+(?:\.\d*)?)F\b/g);
|
|
58
|
+
|
|
59
|
+
eval(t.TEST("re.replace('32F', convert) === '0C'"));
|
|
60
|
+
eval(t.TEST("re.replace('41F', convert) === '5C'"));
|
|
61
|
+
eval(t.TEST("re.replace('50F', convert) === '10C'"));
|
|
62
|
+
eval(t.TEST("re.replace('59F', convert) === '15C'"));
|
|
63
|
+
eval(t.TEST("re.replace('68F', convert) === '20C'"));
|
|
64
|
+
eval(t.TEST("re.replace('77F', convert) === '25C'"));
|
|
65
|
+
eval(t.TEST("re.replace('86F', convert) === '30C'"));
|
|
66
|
+
eval(t.TEST("re.replace('95F', convert) === '35C'"));
|
|
67
|
+
eval(t.TEST("re.replace('104F', convert) === '40C'"));
|
|
68
|
+
eval(t.TEST("re.replace('113F', convert) === '45C'"));
|
|
69
|
+
eval(t.TEST("re.replace('212F', convert) === '100C'"));
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
test: function test_replaceFunLoop(t) {
|
|
73
|
+
'use strict';
|
|
74
|
+
|
|
75
|
+
RE2(/(x_*)|(-)/g).replace('x-x_', function (match, p1, p2) {
|
|
76
|
+
if (p1) {
|
|
77
|
+
t.info('on: ' + p1.length);
|
|
78
|
+
}
|
|
79
|
+
if (p2) {
|
|
80
|
+
t.info('off: 1');
|
|
81
|
+
}
|
|
82
|
+
});
|
|
83
|
+
},
|
|
84
|
+
logs: [{text: 'on: 1'}, {text: 'off: 1'}, {text: 'on: 2'}]
|
|
85
|
+
},
|
|
86
|
+
function test_replaceInvalid(t) {
|
|
87
|
+
'use strict';
|
|
88
|
+
|
|
89
|
+
var re = RE2('');
|
|
90
|
+
|
|
91
|
+
try {
|
|
92
|
+
re.replace(
|
|
93
|
+
{
|
|
94
|
+
toString() {
|
|
95
|
+
throw 'corner1';
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
''
|
|
99
|
+
);
|
|
100
|
+
t.test(false); // shouldn't be here
|
|
101
|
+
} catch (e) {
|
|
102
|
+
eval(t.TEST("e === 'corner1'"));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
try {
|
|
106
|
+
re.replace('', {
|
|
107
|
+
toString() {
|
|
108
|
+
throw 'corner2';
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
t.test(false); // shouldn't be here
|
|
112
|
+
} catch (e) {
|
|
113
|
+
eval(t.TEST("e === 'corner2'"));
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
var arg2Stringified = false;
|
|
117
|
+
|
|
118
|
+
try {
|
|
119
|
+
re.replace(
|
|
120
|
+
{
|
|
121
|
+
toString() {
|
|
122
|
+
throw 'corner1';
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
toString() {
|
|
127
|
+
arg2Stringified = true;
|
|
128
|
+
throw 'corner2';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
);
|
|
132
|
+
t.test(false); // shouldn't be here
|
|
133
|
+
} catch (e) {
|
|
134
|
+
eval(t.TEST("e === 'corner1'"));
|
|
135
|
+
eval(t.TEST('!arg2Stringified'));
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
try {
|
|
139
|
+
re.replace('', () => {
|
|
140
|
+
throw 'corner2';
|
|
141
|
+
});
|
|
142
|
+
t.test(false); // shouldn't be here
|
|
143
|
+
} catch (e) {
|
|
144
|
+
eval(t.TEST("e === 'corner2'"));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
try {
|
|
148
|
+
re.replace('', () => ({
|
|
149
|
+
toString() {
|
|
150
|
+
throw 'corner2';
|
|
151
|
+
}
|
|
152
|
+
}));
|
|
153
|
+
t.test(false); // shouldn't be here
|
|
154
|
+
} catch (e) {
|
|
155
|
+
eval(t.TEST("e === 'corner2'"));
|
|
156
|
+
}
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
// Unicode tests
|
|
160
|
+
|
|
161
|
+
function test_replaceStrUnicode(t) {
|
|
162
|
+
'use strict';
|
|
163
|
+
|
|
164
|
+
var re = new RE2(/яблоки/gi);
|
|
165
|
+
var result = re.replace('Яблоки красны, яблоки сочны.', 'апельсины');
|
|
166
|
+
eval(t.TEST("result === 'апельсины красны, апельсины сочны.'"));
|
|
167
|
+
|
|
168
|
+
re = new RE2(/иван/i);
|
|
169
|
+
result = re.replace('Могуч Иван Иванов...', 'Сидор');
|
|
170
|
+
eval(t.TEST("result === 'Могуч Сидор Иванов...'"));
|
|
171
|
+
|
|
172
|
+
re = new RE2(/иван/gi);
|
|
173
|
+
result = re.replace('Могуч Иван Иванов...', 'Сидор');
|
|
174
|
+
eval(t.TEST("result === 'Могуч Сидор Сидоров...'"));
|
|
175
|
+
|
|
176
|
+
re = new RE2(/([а-яё]+)\s+([а-яё]+)/i);
|
|
177
|
+
result = re.replace('Пётр Петров', '$2, $1');
|
|
178
|
+
eval(t.TEST("result === 'Петров, Пётр'"));
|
|
179
|
+
},
|
|
180
|
+
function test_replaceFunUnicode(t) {
|
|
181
|
+
'use strict';
|
|
182
|
+
|
|
183
|
+
function replacer(match, offset, string) {
|
|
184
|
+
t.test(typeof offset == 'number');
|
|
185
|
+
t.test(typeof string == 'string');
|
|
186
|
+
t.test(offset === 0 || offset === 7);
|
|
187
|
+
t.test(string === 'ИВАН и пЁтр');
|
|
188
|
+
return match.charAt(0).toUpperCase() + match.substr(1).toLowerCase();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
var re = new RE2(/(?:иван|пётр|сидор)/gi);
|
|
192
|
+
var result = re.replace('ИВАН и пЁтр', replacer);
|
|
193
|
+
eval(t.TEST("result === 'Иван и Пётр'"));
|
|
194
|
+
},
|
|
195
|
+
|
|
196
|
+
// Buffer tests
|
|
197
|
+
|
|
198
|
+
function test_replaceStrBuffer(t) {
|
|
199
|
+
'use strict';
|
|
200
|
+
|
|
201
|
+
var re = new RE2(/яблоки/gi);
|
|
202
|
+
var result = re.replace(new Buffer('Яблоки красны, яблоки сочны.'), 'апельсины');
|
|
203
|
+
eval(t.TEST('result instanceof Buffer'));
|
|
204
|
+
eval(t.TEST("result.toString() === 'апельсины красны, апельсины сочны.'"));
|
|
205
|
+
|
|
206
|
+
result = re.replace(new Buffer('Яблоки красны, яблоки сочны.'), new Buffer('апельсины'));
|
|
207
|
+
eval(t.TEST('result instanceof Buffer'));
|
|
208
|
+
eval(t.TEST("result.toString() === 'апельсины красны, апельсины сочны.'"));
|
|
209
|
+
|
|
210
|
+
result = re.replace('Яблоки красны, яблоки сочны.', new Buffer('апельсины'));
|
|
211
|
+
eval(t.TEST("typeof result == 'string'"));
|
|
212
|
+
eval(t.TEST("result === 'апельсины красны, апельсины сочны.'"));
|
|
213
|
+
},
|
|
214
|
+
function test_replaceFunBuffer(t) {
|
|
215
|
+
'use strict';
|
|
216
|
+
|
|
217
|
+
function replacer(match, offset, string) {
|
|
218
|
+
eval(t.TEST('match instanceof Buffer'));
|
|
219
|
+
eval(t.TEST("typeof offset == 'number'"));
|
|
220
|
+
eval(t.TEST("typeof string == 'string'"));
|
|
221
|
+
eval(t.TEST('offset === 0 || offset === 12'));
|
|
222
|
+
eval(t.TEST("string === 'ИВАН и пЁтр'"));
|
|
223
|
+
var s = match.toString();
|
|
224
|
+
return s.charAt(0).toUpperCase() + s.substr(1).toLowerCase();
|
|
225
|
+
}
|
|
226
|
+
replacer.useBuffers = true;
|
|
227
|
+
|
|
228
|
+
var re = new RE2(/(?:иван|пётр|сидор)/gi);
|
|
229
|
+
var result = re.replace('ИВАН и пЁтр', replacer);
|
|
230
|
+
eval(t.TEST("typeof result == 'string'"));
|
|
231
|
+
eval(t.TEST("result === 'Иван и Пётр'"));
|
|
232
|
+
},
|
|
233
|
+
function test_replace0(t) {
|
|
234
|
+
'use strict';
|
|
235
|
+
|
|
236
|
+
function replacer(match) {
|
|
237
|
+
return 'MARKER' + match;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
var re = new RE2(/^/g);
|
|
241
|
+
var result = re.replace('foo bar', 'MARKER');
|
|
242
|
+
eval(t.TEST("result === 'MARKERfoo bar'"));
|
|
243
|
+
result = re.replace('foo bar', replacer);
|
|
244
|
+
eval(t.TEST("result === 'MARKERfoo bar'"));
|
|
245
|
+
|
|
246
|
+
re = new RE2(/$/g);
|
|
247
|
+
result = re.replace('foo bar', 'MARKER');
|
|
248
|
+
eval(t.TEST("result === 'foo barMARKER'"));
|
|
249
|
+
result = re.replace('foo bar', replacer);
|
|
250
|
+
eval(t.TEST("result === 'foo barMARKER'"));
|
|
251
|
+
|
|
252
|
+
re = new RE2(/\b/g);
|
|
253
|
+
result = re.replace('foo bar', 'MARKER');
|
|
254
|
+
eval(t.TEST("result === 'MARKERfooMARKER MARKERbarMARKER'"));
|
|
255
|
+
result = re.replace('foo bar', replacer);
|
|
256
|
+
eval(t.TEST("result === 'MARKERfooMARKER MARKERbarMARKER'"));
|
|
257
|
+
},
|
|
258
|
+
|
|
259
|
+
// Sticky tests
|
|
260
|
+
|
|
261
|
+
function test_replaceSticky(t) {
|
|
262
|
+
'use strict';
|
|
263
|
+
|
|
264
|
+
var re = new RE2(/[A-E]/y);
|
|
265
|
+
|
|
266
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === '!BCDEFABCDEF'"));
|
|
267
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'A!CDEFABCDEF'"));
|
|
268
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'AB!DEFABCDEF'"));
|
|
269
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'ABC!EFABCDEF'"));
|
|
270
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'ABCD!FABCDEF'"));
|
|
271
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === 'ABCDEFABCDEF'"));
|
|
272
|
+
eval(t.TEST("re.replace('ABCDEFABCDEF', '!') === '!BCDEFABCDEF'"));
|
|
273
|
+
|
|
274
|
+
var re2 = new RE2(/[A-E]/gy);
|
|
275
|
+
|
|
276
|
+
eval(t.TEST("re2.replace('ABCDEFABCDEF', '!') === '!!!!!FABCDEF'"));
|
|
277
|
+
eval(t.TEST("re2.replace('FABCDEFABCDE', '!') === 'FABCDEFABCDE'"));
|
|
278
|
+
|
|
279
|
+
re2.lastIndex = 3;
|
|
280
|
+
|
|
281
|
+
eval(t.TEST("re2.replace('ABCDEFABCDEF', '!') === '!!!!!FABCDEF'"));
|
|
282
|
+
eval(t.TEST('re2.lastIndex === 0'));
|
|
283
|
+
}
|
|
233
284
|
]);
|