re2 1.18.2 → 1.18.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/.prettierrc CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "printWidth": 120,
2
+ "printWidth": 80,
3
3
  "singleQuote": true,
4
4
  "bracketSpacing": false,
5
5
  "arrowParens": "avoid",
package/README.md CHANGED
@@ -352,6 +352,7 @@ console.log('re2_res : ' + re2_res); // prints: re2_res : abc,a,b,c
352
352
 
353
353
  ## Release history
354
354
 
355
+ - 1.18.3 *Fixed bug with non-matched groups. Thx, [Dan Setterquist](https://github.com/dset).*
355
356
  - 1.18.2 *Reference to the binary module by its full name.*
356
357
  - 1.18.1 *Support for Node 16, 18, 20 + Darwin arm64 precompiled binaries.*
357
358
  - 1.18.0 *Modified TS bindings, added a type test (thx, [Kenichi Kamiya](https://github.com/kachick) and [Jamie Magee](https://github.com/JamieMagee)).*
package/lib/accessors.cc CHANGED
@@ -39,9 +39,13 @@ NAN_GETTER(WrappedRE2::GetFlags)
39
39
  auto re2 = Nan::ObjectWrap::Unwrap<WrappedRE2>(info.This());
40
40
 
41
41
  std::string flags;
42
+ if (re2->hasIndices)
43
+ {
44
+ flags = "d";
45
+ }
42
46
  if (re2->global)
43
47
  {
44
- flags = "g";
48
+ flags += "g";
45
49
  }
46
50
  if (re2->ignoreCase)
47
51
  {
@@ -135,6 +139,18 @@ NAN_GETTER(WrappedRE2::GetSticky)
135
139
  info.GetReturnValue().Set(re2->sticky);
136
140
  }
137
141
 
142
+ NAN_GETTER(WrappedRE2::GetHasIndices)
143
+ {
144
+ if (!WrappedRE2::HasInstance(info.This()))
145
+ {
146
+ info.GetReturnValue().SetUndefined();
147
+ return;
148
+ }
149
+
150
+ auto re2 = Nan::ObjectWrap::Unwrap<WrappedRE2>(info.This());
151
+ info.GetReturnValue().Set(re2->hasIndices);
152
+ }
153
+
138
154
  NAN_GETTER(WrappedRE2::GetLastIndex)
139
155
  {
140
156
  if (!WrappedRE2::HasInstance(info.This()))
package/lib/addon.cc CHANGED
@@ -23,9 +23,9 @@ static NAN_METHOD(GetUtf16Length)
23
23
  info.GetReturnValue().Set(-1);
24
24
  }
25
25
 
26
- static void cleanup(void* p)
26
+ static void cleanup(void *p)
27
27
  {
28
- v8::Isolate* isolate = static_cast<v8::Isolate*>(p);
28
+ v8::Isolate *isolate = static_cast<v8::Isolate *>(p);
29
29
  auto p_tpl = Nan::GetIsolateData<Nan::Persistent<v8::FunctionTemplate>>(isolate);
30
30
  delete p_tpl;
31
31
  }
@@ -71,6 +71,7 @@ v8::Local<v8::Function> WrappedRE2::Init()
71
71
  Nan::SetAccessor(instanceTemplate, Nan::New("dotAll").ToLocalChecked(), GetDotAll);
72
72
  Nan::SetAccessor(instanceTemplate, Nan::New("unicode").ToLocalChecked(), GetUnicode);
73
73
  Nan::SetAccessor(instanceTemplate, Nan::New("sticky").ToLocalChecked(), GetSticky);
74
+ Nan::SetAccessor(instanceTemplate, Nan::New("hasIndices").ToLocalChecked(), GetHasIndices);
74
75
  Nan::SetAccessor(instanceTemplate, Nan::New("lastIndex").ToLocalChecked(), GetLastIndex, SetLastIndex);
75
76
  Nan::SetAccessor(instanceTemplate, Nan::New("internalSource").ToLocalChecked(), GetInternalSource);
76
77
 
package/lib/exec.cc CHANGED
@@ -52,8 +52,9 @@ NAN_METHOD(WrappedRE2::Exec)
52
52
  {
53
53
  size_t s = getUtf8CharSize(str.data[lastIndex]);
54
54
  lastIndex += s;
55
- if (s == 4 && n >= 2) --n; // this utf8 character will take two utf16 characters
56
- // the decrement above is protected to avoid an overflow of an unsigned integer
55
+ if (s == 4 && n >= 2)
56
+ --n; // this utf8 character will take two utf16 characters
57
+ // the decrement above is protected to avoid an overflow of an unsigned integer
57
58
  }
58
59
  }
59
60
  }
@@ -74,7 +75,7 @@ NAN_METHOD(WrappedRE2::Exec)
74
75
 
75
76
  // form a result
76
77
 
77
- auto result = Nan::New<v8::Array>();
78
+ auto result = Nan::New<v8::Array>(), indices = Nan::New<v8::Array>();
78
79
  int indexOffset = re2->global || re2->sticky ? re2->lastIndex : 0;
79
80
 
80
81
  if (str.isBuffer)
@@ -82,13 +83,24 @@ NAN_METHOD(WrappedRE2::Exec)
82
83
  for (size_t i = 0, n = groups.size(); i < n; ++i)
83
84
  {
84
85
  const auto &item = groups[i];
85
- if (item.data() != NULL)
86
+ const auto data = item.data();
87
+ if (data)
86
88
  {
87
- Nan::Set(result, i, Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked());
89
+ Nan::Set(result, i, Nan::CopyBuffer(data, item.size()).ToLocalChecked());
90
+ if (re2->hasIndices) {
91
+ auto pair = Nan::New<v8::Array>();
92
+ auto offset = data - str.data;
93
+ Nan::Set(pair, 0, Nan::New<v8::Integer>(static_cast<int>(offset)));
94
+ Nan::Set(pair, 1, Nan::New<v8::Integer>(static_cast<int>(offset + item.size())));
95
+ Nan::Set(indices, i, pair);
96
+ }
88
97
  }
89
98
  else
90
99
  {
91
100
  Nan::Set(result, i, Nan::Undefined());
101
+ if (re2->hasIndices) {
102
+ Nan::Set(indices, i, Nan::Undefined());
103
+ }
92
104
  }
93
105
  }
94
106
  Nan::Set(result, Nan::New("index").ToLocalChecked(), Nan::New<v8::Integer>(indexOffset + static_cast<int>(groups[0].data() - str.data)));
@@ -98,18 +110,35 @@ NAN_METHOD(WrappedRE2::Exec)
98
110
  for (size_t i = 0, n = groups.size(); i < n; ++i)
99
111
  {
100
112
  const auto &item = groups[i];
101
- if (item.data() != NULL)
113
+ const auto data = item.data();
114
+ if (data)
102
115
  {
103
- Nan::Set(result, i, Nan::New(item.data(), item.size()).ToLocalChecked());
116
+ Nan::Set(result, i, Nan::New(data, item.size()).ToLocalChecked());
117
+ if (re2->hasIndices) {
118
+ auto pair = Nan::New<v8::Array>();
119
+ auto offset = getUtf16Length(str.data + lastIndex, data);
120
+ auto length = getUtf16Length(data, data + item.size());
121
+ Nan::Set(pair, 0, Nan::New<v8::Integer>(static_cast<int>(offset)));
122
+ Nan::Set(pair, 1, Nan::New<v8::Integer>(static_cast<int>(offset + length)));
123
+ Nan::Set(indices, i, pair);
124
+ }
104
125
  }
105
126
  else
106
127
  {
107
128
  Nan::Set(result, i, Nan::Undefined());
129
+ if (re2->hasIndices) {
130
+ Nan::Set(indices, i, Nan::Undefined());
131
+ }
108
132
  }
109
133
  }
110
134
  Nan::Set(result, Nan::New("index").ToLocalChecked(), Nan::New<v8::Integer>(indexOffset + static_cast<int>(getUtf16Length(str.data + lastIndex, groups[0].data()))));
111
135
  }
112
136
 
137
+ if (re2->global || re2->sticky)
138
+ {
139
+ re2->lastIndex += str.isBuffer ? groups[0].data() - str.data + groups[0].size() - lastIndex : getUtf16Length(str.data + lastIndex, groups[0].data() + groups[0].size());
140
+ }
141
+
113
142
  Nan::Set(result, Nan::New("input").ToLocalChecked(), info[0]);
114
143
 
115
144
  const auto &groupNames = re2->regexp.CapturingGroupNames();
@@ -128,15 +157,21 @@ NAN_METHOD(WrappedRE2::Exec)
128
157
  }
129
158
 
130
159
  Nan::Set(result, Nan::New("groups").ToLocalChecked(), groups);
160
+
161
+ if (re2->hasIndices) {
162
+ Nan::Set(indices, Nan::New("groups").ToLocalChecked(), groups);
163
+ }
131
164
  }
132
165
  else
133
166
  {
134
167
  Nan::Set(result, Nan::New("groups").ToLocalChecked(), Nan::Undefined());
168
+ if (re2->hasIndices) {
169
+ Nan::Set(indices, Nan::New("groups").ToLocalChecked(), Nan::Undefined());
170
+ }
135
171
  }
136
172
 
137
- if (re2->global || re2->sticky)
138
- {
139
- re2->lastIndex += str.isBuffer ? groups[0].data() - str.data + groups[0].size() - lastIndex : getUtf16Length(str.data + lastIndex, groups[0].data() + groups[0].size());
173
+ if (re2->hasIndices) {
174
+ Nan::Set(result, Nan::New("indices").ToLocalChecked(), indices);
140
175
  }
141
176
 
142
177
  info.GetReturnValue().Set(result);
package/lib/match.cc CHANGED
@@ -61,8 +61,9 @@ NAN_METHOD(WrappedRE2::Match)
61
61
  {
62
62
  size_t s = getUtf8CharSize(a.data[lastIndex]);
63
63
  lastIndex += s;
64
- if (s == 4 && n >= 2) --n; // this utf8 character will take two utf16 characters
65
- // the decrement above is protected to avoid an overflow of an unsigned integer
64
+ if (s == 4 && n >= 2)
65
+ --n; // this utf8 character will take two utf16 characters
66
+ // the decrement above is protected to avoid an overflow of an unsigned integer
66
67
  }
67
68
  anchor = RE2::ANCHOR_START;
68
69
  }
@@ -88,9 +89,10 @@ NAN_METHOD(WrappedRE2::Match)
88
89
  for (size_t i = 0, n = groups.size(); i < n; ++i)
89
90
  {
90
91
  const auto &item = groups[i];
91
- if (item.data() != NULL)
92
+ const auto data = item.data();
93
+ if (data)
92
94
  {
93
- Nan::Set(result, i, Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked());
95
+ Nan::Set(result, i, Nan::CopyBuffer(data, item.size()).ToLocalChecked());
94
96
  }
95
97
  }
96
98
  if (!re2->global)
@@ -104,9 +106,10 @@ NAN_METHOD(WrappedRE2::Match)
104
106
  for (size_t i = 0, n = groups.size(); i < n; ++i)
105
107
  {
106
108
  const auto &item = groups[i];
107
- if (item.data() != NULL)
109
+ const auto data = item.data();
110
+ if (data)
108
111
  {
109
- Nan::Set(result, i, Nan::New(item.data(), item.size()).ToLocalChecked());
112
+ Nan::Set(result, i, Nan::New(data, item.size()).ToLocalChecked());
110
113
  }
111
114
  }
112
115
  if (!re2->global)
package/lib/new.cc CHANGED
@@ -232,6 +232,7 @@ NAN_METHOD(WrappedRE2::New)
232
232
  bool dotAll = false;
233
233
  bool unicode = false;
234
234
  bool sticky = false;
235
+ bool hasIndices = false;
235
236
 
236
237
  auto context = Nan::GetCurrentContext();
237
238
 
@@ -272,6 +273,9 @@ NAN_METHOD(WrappedRE2::New)
272
273
  case 'y':
273
274
  sticky = true;
274
275
  break;
276
+ case 'd':
277
+ hasIndices = true;
278
+ break;
275
279
  }
276
280
  }
277
281
  size = 0;
@@ -306,6 +310,7 @@ NAN_METHOD(WrappedRE2::New)
306
310
  dotAll = bool(flags & v8::RegExp::kDotAll);
307
311
  unicode = bool(flags & v8::RegExp::kUnicode);
308
312
  sticky = bool(flags & v8::RegExp::kSticky);
313
+ hasIndices = bool(flags & v8::RegExp::kHasIndices);
309
314
  }
310
315
  else if (info[0]->IsObject() && !info[0]->IsString())
311
316
  {
@@ -332,6 +337,7 @@ NAN_METHOD(WrappedRE2::New)
332
337
  dotAll = re2->dotAll;
333
338
  unicode = true;
334
339
  sticky = re2->sticky;
340
+ hasIndices = re2->hasIndices;
335
341
  }
336
342
  }
337
343
  else if (info[0]->IsString())
@@ -385,7 +391,7 @@ NAN_METHOD(WrappedRE2::New)
385
391
  options.set_dot_nl(dotAll);
386
392
  options.set_log_errors(false); // inappropriate when embedding
387
393
 
388
- std::unique_ptr<WrappedRE2> re2(new WrappedRE2(re2::StringPiece(data, size), options, source, global, ignoreCase, multiline, dotAll, sticky));
394
+ std::unique_ptr<WrappedRE2> re2(new WrappedRE2(re2::StringPiece(data, size), options, source, global, ignoreCase, multiline, dotAll, sticky, hasIndices));
389
395
  if (!re2->regexp.ok())
390
396
  {
391
397
  return Nan::ThrowSyntaxError(re2->regexp.error().c_str());
package/lib/replace.cc CHANGED
@@ -228,7 +228,8 @@ 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
+ {
232
233
  --n; // this utf8 character will take two utf16 characters
233
234
  }
234
235
  // the decrement above is protected to avoid an overflow of an unsigned integer
@@ -299,7 +300,7 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
299
300
 
300
301
  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)
301
302
  {
302
- std::vector<v8::Local<v8::Value> > argv;
303
+ std::vector<v8::Local<v8::Value>> argv;
303
304
 
304
305
  auto context = Nan::GetCurrentContext();
305
306
 
@@ -308,7 +309,15 @@ inline Nan::Maybe<std::string> replace(const Nan::Callback *replacer, const std:
308
309
  for (size_t i = 0, n = groups.size(); i < n; ++i)
309
310
  {
310
311
  const auto &item = groups[i];
311
- argv.push_back(Nan::CopyBuffer(item.data(), item.size()).ToLocalChecked());
312
+ const auto data = item.data();
313
+ if (data)
314
+ {
315
+ argv.push_back(Nan::CopyBuffer(data, item.size()).ToLocalChecked());
316
+ }
317
+ else
318
+ {
319
+ argv.push_back(Nan::Undefined());
320
+ }
312
321
  }
313
322
  argv.push_back(Nan::New(static_cast<int>(groups[0].data() - str.data())));
314
323
  }
@@ -317,7 +326,15 @@ inline Nan::Maybe<std::string> replace(const Nan::Callback *replacer, const std:
317
326
  for (size_t i = 0, n = groups.size(); i < n; ++i)
318
327
  {
319
328
  const auto &item = groups[i];
320
- argv.push_back(Nan::New(item.data(), item.size()).ToLocalChecked());
329
+ const auto data = item.data();
330
+ if (data)
331
+ {
332
+ argv.push_back(Nan::New(data, item.size()).ToLocalChecked());
333
+ }
334
+ else
335
+ {
336
+ argv.push_back(Nan::Undefined());
337
+ }
321
338
  }
322
339
  argv.push_back(Nan::New(static_cast<int>(getUtf16Length(str.data(), groups[0].data()))));
323
340
  }
@@ -381,7 +398,8 @@ static Nan::Maybe<std::string> replace(WrappedRE2 *re2, const StrVal &replacee,
381
398
  {
382
399
  size_t s = getUtf8CharSize(data[lastIndex]);
383
400
  lastIndex += s;
384
- if (s == 4 && n >= 2) {
401
+ if (s == 4 && n >= 2)
402
+ {
385
403
  --n; // this utf8 character will take two utf16 characters
386
404
  }
387
405
  // the decrement above is protected to avoid an overflow of an unsigned integer
package/lib/wrapped_re2.h CHANGED
@@ -11,8 +11,8 @@ class WrappedRE2 : public Nan::ObjectWrap
11
11
  {
12
12
  private:
13
13
  WrappedRE2(const re2::StringPiece &pattern, const re2::RE2::Options &options, const std::string &src,
14
- const bool &g, const bool &i, const bool &m, const bool &s, const bool &y) : regexp(pattern, options),
15
- source(src), global(g), ignoreCase(i), multiline(m), dotAll(s), sticky(y), lastIndex(0) {}
14
+ const bool &g, const bool &i, const bool &m, const bool &s, const bool &y, const bool &d) : regexp(pattern, options),
15
+ source(src), global(g), ignoreCase(i), multiline(m), dotAll(s), sticky(y), hasIndices(d), lastIndex(0) {}
16
16
 
17
17
  static NAN_METHOD(New);
18
18
  static NAN_METHOD(ToString);
@@ -25,6 +25,7 @@ private:
25
25
  static NAN_GETTER(GetDotAll);
26
26
  static NAN_GETTER(GetUnicode);
27
27
  static NAN_GETTER(GetSticky);
28
+ static NAN_GETTER(GetHasIndices);
28
29
  static NAN_GETTER(GetLastIndex);
29
30
  static NAN_SETTER(SetLastIndex);
30
31
  static NAN_GETTER(GetInternalSource);
@@ -70,6 +71,7 @@ public:
70
71
  bool multiline;
71
72
  bool dotAll;
72
73
  bool sticky;
74
+ bool hasIndices;
73
75
  size_t lastIndex;
74
76
  };
75
77
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "re2",
3
- "version": "1.18.2",
3
+ "version": "1.18.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",
@@ -280,5 +280,43 @@ unit.add(module, [
280
280
 
281
281
  eval(t.TEST("re2.replace('ABCDEFABCDEF', '!') === '!!!!!FABCDEF'"));
282
282
  eval(t.TEST('re2.lastIndex === 0'));
283
+ },
284
+
285
+ // Non-matches
286
+
287
+ function test_ReplaceOneNonMatch(t) {
288
+ 'use strict';
289
+
290
+ function replacer(match, capture, offset, string) {
291
+ t.test(typeof offset == 'number');
292
+ t.test(typeof match == 'string');
293
+ t.test(typeof string == 'string');
294
+ t.test(typeof capture == 'undefined');
295
+ t.test(offset === 0);
296
+ t.test(string === 'hello ');
297
+ return '';
298
+ }
299
+
300
+ var re = new RE2(/hello (world)?/);
301
+ re.replace('hello ', replacer);
302
+ },
303
+ function test_ReplaceTwoNonMatches(t) {
304
+ 'use strict';
305
+
306
+ function replacer(match, capture1, capture2, offset, string) {
307
+ t.test(typeof offset == 'number');
308
+ t.test(typeof match == 'string');
309
+ t.test(typeof string == 'string');
310
+ t.test(typeof capture1 == 'undefined');
311
+ t.test(typeof capture2 == 'undefined');
312
+ t.test(offset === 1);
313
+ t.test(match === 'b & y');
314
+ t.test(string === 'ab & yz');
315
+ return '';
316
+ }
317
+
318
+ var re = new RE2(/b(1)? & (2)?y/);
319
+ var result = re.replace('ab & yz', replacer);
320
+ eval(t.TEST("result === 'az'"));
283
321
  }
284
322
  ]);