re2 1.21.1 → 1.21.2

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 CHANGED
@@ -353,6 +353,7 @@ console.log('re2_res : ' + re2_res); // prints: re2_res : abc,a,b,c
353
353
 
354
354
  ## Release history
355
355
 
356
+ - 1.21.2 *Fixed another memory regression reported by [matthewvalentine](https://github.com/matthewvalentine), thx! Updated deps. Added more tests and benchmarks.*
356
357
  - 1.21.1 *Fixed a memory regression reported by [matthewvalentine](https://github.com/matthewvalentine), thx! Updated deps.*
357
358
  - 1.21.0 *Fixed the performance problem reported by [matthewvalentine](https://github.com/matthewvalentine) (thx!). The change improves performance for multiple use cases.*
358
359
  - 1.20.12 *Updated deps. Maintenance chores. Fixes for buffer-related bugs: `exec()` index (reported by [matthewvalentine](https://github.com/matthewvalentine), thx) and `match()` index.*
package/binding.gyp CHANGED
@@ -5,7 +5,6 @@
5
5
  "sources": [
6
6
  "lib/addon.cc",
7
7
  "lib/accessors.cc",
8
- "lib/str-val.cc",
9
8
  "lib/util.cc",
10
9
  "lib/new.cc",
11
10
  "lib/exec.cc",
package/lib/accessors.cc CHANGED
@@ -28,30 +28,6 @@ NAN_GETTER(WrappedRE2::GetInternalSource)
28
28
  info.GetReturnValue().Set(Nan::New(re2->regexp.pattern()).ToLocalChecked());
29
29
  }
30
30
 
31
- NAN_GETTER(WrappedRE2::GetEnabledCache)
32
- {
33
- if (!WrappedRE2::HasInstance(info.This()))
34
- {
35
- info.GetReturnValue().SetUndefined();
36
- return;
37
- }
38
-
39
- auto re2 = Nan::ObjectWrap::Unwrap<WrappedRE2>(info.This());
40
- info.GetReturnValue().Set(re2->enabledCache);
41
- }
42
-
43
- NAN_GETTER(WrappedRE2::GetIsCached)
44
- {
45
- if (!WrappedRE2::HasInstance(info.This()))
46
- {
47
- info.GetReturnValue().SetUndefined();
48
- return;
49
- }
50
-
51
- auto re2 = Nan::ObjectWrap::Unwrap<WrappedRE2>(info.This());
52
- info.GetReturnValue().Set(!!re2->lastStringValue);
53
- }
54
-
55
31
  NAN_GETTER(WrappedRE2::GetFlags)
56
32
  {
57
33
  if (!WrappedRE2::HasInstance(info.This()))
@@ -63,10 +39,6 @@ NAN_GETTER(WrappedRE2::GetFlags)
63
39
  auto re2 = Nan::ObjectWrap::Unwrap<WrappedRE2>(info.This());
64
40
 
65
41
  std::string flags;
66
- if (re2->enabledCache)
67
- {
68
- flags += "\b";
69
- }
70
42
  if (re2->hasIndices)
71
43
  {
72
44
  flags += "d";
package/lib/addon.cc CHANGED
@@ -1,7 +1,5 @@
1
1
  #include "./wrapped_re2.h"
2
2
 
3
- #include "./str-val.h"
4
-
5
3
  static NAN_METHOD(GetUtf8Length)
6
4
  {
7
5
  auto t = info[0]->ToString(Nan::GetCurrentContext());
@@ -74,8 +72,6 @@ v8::Local<v8::Function> WrappedRE2::Init()
74
72
  Nan::SetAccessor(instanceTemplate, Nan::New("hasIndices").ToLocalChecked(), GetHasIndices);
75
73
  Nan::SetAccessor(instanceTemplate, Nan::New("lastIndex").ToLocalChecked(), GetLastIndex, SetLastIndex);
76
74
  Nan::SetAccessor(instanceTemplate, Nan::New("internalSource").ToLocalChecked(), GetInternalSource);
77
- Nan::SetAccessor(instanceTemplate, Nan::New("enabledCache").ToLocalChecked(), GetEnabledCache);
78
- Nan::SetAccessor(instanceTemplate, Nan::New("isCached").ToLocalChecked(), GetIsCached);
79
75
 
80
76
  auto ctr = Nan::GetFunction(tpl).ToLocalChecked();
81
77
 
@@ -96,77 +92,124 @@ NODE_MODULE_INIT()
96
92
 
97
93
  WrappedRE2::~WrappedRE2()
98
94
  {
99
- for (auto ptr : callbackRegistry)
100
- {
101
- *ptr = nullptr;
102
- }
103
- dropLastString();
95
+ dropCache();
104
96
  }
105
97
 
106
98
  // private methods
107
99
 
108
- WrappedRE2::PtrWrappedRE2 *WrappedRE2::registerCallback()
100
+ void WrappedRE2::dropCache()
109
101
  {
110
- PtrWrappedRE2 *ptr = new PtrWrappedRE2(this);
111
- callbackRegistry.insert(ptr);
112
- return ptr;
102
+ if (!lastString.IsEmpty())
103
+ {
104
+ // lastString.ClearWeak();
105
+ lastString.Reset();
106
+ }
107
+ if (!lastCache.IsEmpty())
108
+ {
109
+ // lastCache.ClearWeak();
110
+ lastCache.Reset();
111
+ }
112
+ lastStringValue.clear();
113
113
  }
114
114
 
115
- void WrappedRE2::unregisterCallback(PtrWrappedRE2 *ptr)
115
+ const StrVal& WrappedRE2::prepareArgument(const v8::Local<v8::Value> &arg, bool ignoreLastIndex)
116
116
  {
117
- callbackRegistry.erase(ptr);
118
- }
117
+ size_t startFrom = ignoreLastIndex ? 0 : lastIndex;
119
118
 
120
- void WrappedRE2::dropLastString()
121
- {
122
- lastString.Reset();
123
- if (lastStringValue)
119
+ if (lastString == arg && !node::Buffer::HasInstance(arg) && !lastCache.IsEmpty())
124
120
  {
125
- delete lastStringValue;
126
- lastStringValue = nullptr;
121
+ // we have a properly cached string
122
+ lastStringValue.setIndex(startFrom);
123
+ return lastStringValue;
127
124
  }
128
- }
129
125
 
130
- void WrappedRE2::weakLastStringCallback(const Nan::WeakCallbackInfo<PtrWrappedRE2> &data)
131
- {
132
- PtrWrappedRE2 *re2 = data.GetParameter();
133
- if (*re2)
126
+ dropCache();
127
+
128
+ if (node::Buffer::HasInstance(arg))
134
129
  {
135
- (*re2)->unregisterCallback(re2);
136
- (*re2)->dropLastString();
130
+ // no need to cache buffers
131
+
132
+ lastString.Reset(arg);
133
+ static_cast<v8::PersistentBase<v8::Value> &>(lastString).SetWeak();
134
+
135
+ auto argSize = node::Buffer::Length(arg);
136
+ lastStringValue.reset(arg, argSize, argSize, startFrom, true);
137
+
138
+ return lastStringValue;
137
139
  }
138
- delete re2;
139
- }
140
140
 
141
- void WrappedRE2::prepareLastString(const v8::Local<v8::Value> &arg, bool ignoreLastIndex)
141
+ // caching the string
142
+
143
+ auto t = arg->ToString(Nan::GetCurrentContext());
144
+ if (t.IsEmpty())
145
+ {
146
+ // do not process bad strings
147
+ lastStringValue.isBad = true;
148
+ return lastStringValue;
149
+ }
150
+
151
+ lastString.Reset(arg);
152
+ static_cast<v8::PersistentBase<v8::Value> &>(lastString).SetWeak();
153
+
154
+ auto s = t.ToLocalChecked();
155
+ auto argLength = Nan::DecodeBytes(s);
156
+
157
+ auto buffer = node::Buffer::New(v8::Isolate::GetCurrent(), s).ToLocalChecked();
158
+ lastCache.Reset(buffer);
159
+ static_cast<v8::PersistentBase<v8::Object> &>(lastCache).SetWeak();
160
+
161
+ auto argSize = node::Buffer::Length(buffer);
162
+ lastStringValue.reset(buffer, argSize, argLength, startFrom);
163
+
164
+ return lastStringValue;
165
+ };
166
+
167
+ // StrVal
168
+
169
+ void StrVal::setIndex(size_t newIndex)
142
170
  {
143
- size_t startFrom = ignoreLastIndex ? 0 : lastIndex;
171
+ isValidIndex = newIndex <= length;
172
+ if (!isValidIndex)
173
+ {
174
+ index = newIndex;
175
+ byteIndex = 0;
176
+ return;
177
+ }
144
178
 
145
- if (node::Buffer::HasInstance(arg))
179
+ if (newIndex == index)
180
+ return;
181
+
182
+ if (isBuffer)
146
183
  {
147
- dropLastString();
148
- lastStringValue = new StrValBuffer(arg, startFrom);
184
+ byteIndex = index = newIndex;
149
185
  return;
150
186
  }
151
187
 
152
188
  // String
153
189
 
154
- // check if the same string is already in the cache
155
- if (lastString == arg && lastStringValue)
190
+ if (!newIndex)
156
191
  {
157
- if (!global && !sticky)
158
- return; // we are good
159
- lastStringValue->setIndex(startFrom);
192
+ byteIndex = index = 0;
160
193
  return;
161
194
  }
162
195
 
163
- dropLastString();
164
-
165
- lastString.Reset(arg);
166
- static_cast<v8::PersistentBase<v8::Value> &>(lastString).SetWeak();
196
+ if (newIndex == length)
197
+ {
198
+ byteIndex = size;
199
+ index = length;
200
+ return;
201
+ }
167
202
 
168
- Nan::Persistent<v8::Value> dummy(arg);
169
- dummy.SetWeak(registerCallback(), weakLastStringCallback, Nan::WeakCallbackType::kParameter);
203
+ byteIndex = index < newIndex ? getUtf16PositionByCounter(data, byteIndex, newIndex - index) : getUtf16PositionByCounter(data, 0, newIndex);
204
+ index = newIndex;
205
+ }
170
206
 
171
- lastStringValue = new StrValString(arg, startFrom);
172
- };
207
+ void StrVal::reset(const v8::Local<v8::Value> &arg, size_t argSize, size_t argLength, size_t newIndex, bool buffer)
208
+ {
209
+ clear();
210
+ isBuffer = buffer;
211
+ size = argSize;
212
+ length = argLength;
213
+ data = node::Buffer::Data(arg);
214
+ setIndex(newIndex);
215
+ }
package/lib/exec.cc CHANGED
@@ -1,5 +1,4 @@
1
1
  #include "./wrapped_re2.h"
2
- #include "./str-val.h"
3
2
 
4
3
  #include <vector>
5
4
 
@@ -15,13 +14,12 @@ NAN_METHOD(WrappedRE2::Exec)
15
14
  return;
16
15
  }
17
16
 
18
- PrepareLastString prepare(re2, info[0]);
19
- StrValBase &str = *re2->lastStringValue;
17
+ auto str = re2->prepareArgument(info[0]);
20
18
  if (str.isBad) return; // throws an exception
21
19
 
22
20
  if (re2->global || re2->sticky)
23
21
  {
24
- if (!str.isIndexValid)
22
+ if (!str.isValidIndex)
25
23
  {
26
24
  re2->lastIndex = 0;
27
25
  info.GetReturnValue().SetNull();
package/lib/match.cc CHANGED
@@ -1,5 +1,4 @@
1
1
  #include "./wrapped_re2.h"
2
- #include "./str-val.h"
3
2
 
4
3
  #include <vector>
5
4
 
@@ -15,11 +14,10 @@ NAN_METHOD(WrappedRE2::Match)
15
14
  return;
16
15
  }
17
16
 
18
- PrepareLastString prepare(re2, info[0], re2->global);
19
- StrValBase &str = *re2->lastStringValue;
17
+ auto str = re2->prepareArgument(info[0], re2->global);
20
18
  if (str.isBad) return; // throws an exception
21
19
 
22
- if (!str.isIndexValid)
20
+ if (!str.isValidIndex)
23
21
  {
24
22
  re2->lastIndex = 0;
25
23
  info.GetReturnValue().SetNull();
package/lib/new.cc CHANGED
@@ -233,7 +233,6 @@ NAN_METHOD(WrappedRE2::New)
233
233
  bool unicode = false;
234
234
  bool sticky = false;
235
235
  bool hasIndices = false;
236
- bool enabledCache = false;
237
236
 
238
237
  auto context = Nan::GetCurrentContext();
239
238
  bool needFlags = true;
@@ -257,9 +256,6 @@ NAN_METHOD(WrappedRE2::New)
257
256
  {
258
257
  switch (data[i])
259
258
  {
260
- case '\b':
261
- enabledCache = true;
262
- break;
263
259
  case 'g':
264
260
  global = true;
265
261
  break;
@@ -343,7 +339,6 @@ NAN_METHOD(WrappedRE2::New)
343
339
 
344
340
  if (needFlags)
345
341
  {
346
- enabledCache = re2->enabledCache;
347
342
  global = re2->global;
348
343
  ignoreCase = re2->ignoreCase;
349
344
  multiline = re2->multiline;
@@ -406,7 +401,7 @@ NAN_METHOD(WrappedRE2::New)
406
401
  options.set_dot_nl(dotAll);
407
402
  options.set_log_errors(false); // inappropriate when embedding
408
403
 
409
- std::unique_ptr<WrappedRE2> re2(new WrappedRE2(re2::StringPiece(data, size), options, source, enabledCache, global, ignoreCase, multiline, dotAll, sticky, hasIndices));
404
+ std::unique_ptr<WrappedRE2> re2(new WrappedRE2(re2::StringPiece(data, size), options, source, global, ignoreCase, multiline, dotAll, sticky, hasIndices));
410
405
  if (!re2->regexp.ok())
411
406
  {
412
407
  return Nan::ThrowSyntaxError(re2->regexp.error().c_str());
package/lib/replace.cc CHANGED
@@ -1,5 +1,4 @@
1
1
  #include "./wrapped_re2.h"
2
- #include "./str-val.h"
3
2
 
4
3
  #include <algorithm>
5
4
  #include <memory>
@@ -213,7 +212,7 @@ inline std::string replace(
213
212
 
214
213
  static Nan::Maybe<std::string> replace(
215
214
  WrappedRE2 *re2,
216
- const StrValBase &replacee,
215
+ const StrVal &replacee,
217
216
  const char *replacer,
218
217
  size_t replacer_size)
219
218
  {
@@ -370,13 +369,19 @@ inline Nan::Maybe<std::string> replace(
370
369
  return Nan::Just(std::string(node::Buffer::Data(result), node::Buffer::Length(result)));
371
370
  }
372
371
 
373
- StrValString val(result);
374
- return Nan::Just(std::string(val.data, val.size));
372
+ auto t = result->ToString(Nan::GetCurrentContext());
373
+ if (t.IsEmpty())
374
+ {
375
+ return Nan::Nothing<std::string>();
376
+ }
377
+
378
+ v8::String::Utf8Value s(v8::Isolate::GetCurrent(), t.ToLocalChecked());
379
+ return Nan::Just(std::string(*s));
375
380
  }
376
381
 
377
382
  static Nan::Maybe<std::string> replace(
378
383
  WrappedRE2 *re2,
379
- const StrValBase &replacee,
384
+ const StrVal &replacee,
380
385
  const Nan::Callback *replacer,
381
386
  const v8::Local<v8::Value> &input,
382
387
  bool useBuffers)
@@ -492,11 +497,10 @@ NAN_METHOD(WrappedRE2::Replace)
492
497
  return;
493
498
  }
494
499
 
495
- PrepareLastString prepare(re2, info[0]);
496
- StrValBase &replacee = *re2->lastStringValue;
500
+ auto replacee = re2->prepareArgument(info[0]);
497
501
  if (replacee.isBad) return; // throws an exception
498
502
 
499
- if (!replacee.isIndexValid)
503
+ if (!replacee.isValidIndex)
500
504
  {
501
505
  info.GetReturnValue().Set(info[0]);
502
506
  return;
@@ -518,15 +522,23 @@ NAN_METHOD(WrappedRE2::Replace)
518
522
  }
519
523
  else
520
524
  {
521
- StrValBase *replacer = StrValBase::New(info[1]);
522
- if (replacer->isBad) return; // throws an exception
523
-
524
- if (!replacer->data)
525
+ v8::Local<v8::Object> replacer;
526
+ if (node::Buffer::HasInstance(info[1]))
525
527
  {
526
- info.GetReturnValue().Set(info[0]);
527
- return;
528
+ replacer = info[1].As<v8::Object>();
529
+ }
530
+ else
531
+ {
532
+ auto t = info[1]->ToString(Nan::GetCurrentContext());
533
+ if (t.IsEmpty())
534
+ return; // throws an exception
535
+ replacer = node::Buffer::New(v8::Isolate::GetCurrent(), t.ToLocalChecked()).ToLocalChecked();
528
536
  }
529
- const auto replaced = replace(re2, replacee, replacer->data, replacer->size);
537
+
538
+ auto data = node::Buffer::Data(replacer);
539
+ auto size = node::Buffer::Length(replacer);
540
+
541
+ const auto replaced = replace(re2, replacee, data, size);
530
542
  if (replaced.IsNothing())
531
543
  {
532
544
  info.GetReturnValue().Set(info[0]);
package/lib/search.cc CHANGED
@@ -1,5 +1,4 @@
1
1
  #include "./wrapped_re2.h"
2
- #include "./str-val.h"
3
2
 
4
3
  NAN_METHOD(WrappedRE2::Search)
5
4
  {
@@ -13,8 +12,7 @@ NAN_METHOD(WrappedRE2::Search)
13
12
  return;
14
13
  }
15
14
 
16
- PrepareLastString prepare(re2, info[0], true);
17
- StrValBase &str = *re2->lastStringValue;
15
+ auto str = re2->prepareArgument(info[0], true);
18
16
  if (str.isBad) return; // throws an exception
19
17
 
20
18
  if (!str.data)
package/lib/split.cc CHANGED
@@ -1,5 +1,4 @@
1
1
  #include "./wrapped_re2.h"
2
- #include "./str-val.h"
3
2
 
4
3
  #include <algorithm>
5
4
  #include <limits>
@@ -20,8 +19,7 @@ NAN_METHOD(WrappedRE2::Split)
20
19
  return;
21
20
  }
22
21
 
23
- PrepareLastString prepare(re2, info[0], true);
24
- StrValBase &str = *re2->lastStringValue;
22
+ auto str = re2->prepareArgument(info[0], true);
25
23
  if (str.isBad) return; // throws an exception
26
24
 
27
25
  size_t limit = std::numeric_limits<size_t>::max();
package/lib/test.cc CHANGED
@@ -1,5 +1,4 @@
1
1
  #include "./wrapped_re2.h"
2
- #include "./str-val.h"
3
2
 
4
3
  #include <vector>
5
4
 
@@ -15,8 +14,7 @@ NAN_METHOD(WrappedRE2::Test)
15
14
  return;
16
15
  }
17
16
 
18
- PrepareLastString prepare(re2, info[0]);
19
- StrValBase &str = *re2->lastStringValue;
17
+ auto str = re2->prepareArgument(info[0]);
20
18
  if (str.isBad) return; // throws an exception
21
19
 
22
20
  if (!re2->global && !re2->sticky)
@@ -25,7 +23,7 @@ NAN_METHOD(WrappedRE2::Test)
25
23
  return;
26
24
  }
27
25
 
28
- if (!str.isIndexValid)
26
+ if (!str.isValidIndex)
29
27
  {
30
28
  re2->lastIndex = 0;
31
29
  info.GetReturnValue().SetNull();
package/lib/to_string.cc CHANGED
@@ -20,10 +20,6 @@ NAN_METHOD(WrappedRE2::ToString)
20
20
  buffer += re2->source;
21
21
  buffer += "/";
22
22
 
23
- if (re2->enabledCache)
24
- {
25
- buffer += "\b";
26
- }
27
23
  if (re2->global)
28
24
  {
29
25
  buffer += "g";
package/lib/util.h CHANGED
@@ -1,5 +1,4 @@
1
- #ifndef UTIL_H_
2
- #define UTIL_H_
1
+ #pragma once
3
2
 
4
3
  #include "./wrapped_re2.h"
5
4
 
@@ -13,5 +12,3 @@ void consoleCall(const v8::Local<v8::String> &methodName, v8::Local<v8::Value> t
13
12
  void printDeprecationWarning(const char *warning);
14
13
 
15
14
  v8::Local<v8::String> callToString(const v8::Local<v8::Object> &object);
16
-
17
- #endif
package/lib/wrapped_re2.h CHANGED
@@ -1,14 +1,30 @@
1
- #ifndef WRAPPED_RE2_H_
2
- #define WRAPPED_RE2_H_
1
+ #pragma once
3
2
 
3
+ #include <string>
4
4
  #include <nan.h>
5
-
6
5
  #include <re2/re2.h>
7
6
 
8
- #include <string>
9
- #include <unordered_set>
7
+ struct StrVal
8
+ {
9
+ char *data;
10
+ size_t size, length;
11
+ size_t index, byteIndex;
12
+ bool isBuffer, isValidIndex, isBad;
10
13
 
11
- struct StrValBase;
14
+ StrVal() : data(NULL), size(0), length(0), index(0), byteIndex(0), isBuffer(false), isValidIndex(false), isBad(false) {}
15
+
16
+ operator re2::StringPiece() const { return re2::StringPiece(data, size); }
17
+
18
+ void setIndex(size_t newIndex = 0);
19
+ void reset(const v8::Local<v8::Value> &arg, size_t size, size_t length, size_t newIndex = 0, bool buffer = false);
20
+
21
+ void clear()
22
+ {
23
+ isBad = isBuffer = isValidIndex = false;
24
+ size = length = index = byteIndex = 0;
25
+ data = nullptr;
26
+ }
27
+ };
12
28
 
13
29
  class WrappedRE2 : public Nan::ObjectWrap
14
30
  {
@@ -17,7 +33,6 @@ private:
17
33
  const re2::StringPiece &pattern,
18
34
  const re2::RE2::Options &options,
19
35
  const std::string &src,
20
- const bool &c,
21
36
  const bool &g,
22
37
  const bool &i,
23
38
  const bool &m,
@@ -25,15 +40,13 @@ private:
25
40
  const bool &y,
26
41
  const bool &d) : regexp(pattern, options),
27
42
  source(src),
28
- enabledCache(c),
29
43
  global(g),
30
44
  ignoreCase(i),
31
45
  multiline(m),
32
46
  dotAll(s),
33
47
  sticky(y),
34
48
  hasIndices(d),
35
- lastIndex(0),
36
- lastStringValue(nullptr) {}
49
+ lastIndex(0) {}
37
50
 
38
51
  static NAN_METHOD(New);
39
52
  static NAN_METHOD(ToString);
@@ -50,8 +63,6 @@ private:
50
63
  static NAN_GETTER(GetLastIndex);
51
64
  static NAN_SETTER(SetLastIndex);
52
65
  static NAN_GETTER(GetInternalSource);
53
- static NAN_GETTER(GetEnabledCache);
54
- static NAN_GETTER(GetIsCached);
55
66
 
56
67
  // RegExp methods
57
68
  static NAN_METHOD(Exec);
@@ -91,7 +102,6 @@ public:
91
102
 
92
103
  re2::RE2 regexp;
93
104
  std::string source;
94
- bool enabledCache;
95
105
  bool global;
96
106
  bool ignoreCase;
97
107
  bool multiline;
@@ -100,38 +110,15 @@ public:
100
110
  bool hasIndices;
101
111
  size_t lastIndex;
102
112
 
103
- friend class PrepareLastString;
113
+ friend struct PrepareLastString;
104
114
 
105
115
  private:
106
116
  Nan::Persistent<v8::Value> lastString; // weak pointer
107
- StrValBase *lastStringValue;
108
-
109
- typedef WrappedRE2 *PtrWrappedRE2;
110
-
111
- std::unordered_set<PtrWrappedRE2 *> callbackRegistry;
112
- PtrWrappedRE2 *registerCallback();
113
- void unregisterCallback(PtrWrappedRE2 *re2);
114
-
115
- static void weakLastStringCallback(const Nan::WeakCallbackInfo<PtrWrappedRE2> &data);
117
+ Nan::Persistent<v8::Object> lastCache; // weak pointer
118
+ StrVal lastStringValue;
116
119
 
117
- void dropLastString();
118
- void prepareLastString(const v8::Local<v8::Value> &arg, bool ignoreLastIndex = false);
119
- };
120
-
121
- struct PrepareLastString
122
- {
123
- PrepareLastString(WrappedRE2 *re2, const v8::Local<v8::Value> &arg, bool ignoreLastIndex = false) : re2(re2)
124
- {
125
- re2->prepareLastString(arg, ignoreLastIndex);
126
- }
127
-
128
- ~PrepareLastString()
129
- {
130
- if (!re2->enabledCache || !(re2->global || re2->sticky))
131
- re2->dropLastString();
132
- }
133
-
134
- WrappedRE2 *re2;
120
+ void dropCache();
121
+ const StrVal &prepareArgument(const v8::Local<v8::Value> &arg, bool ignoreLastIndex = false);
135
122
  };
136
123
 
137
124
  // utilities
@@ -212,4 +199,15 @@ inline size_t getUtf8CharSize(char ch)
212
199
  return ((0xE5000000 >> ((ch >> 3) & 0x1E)) & 3) + 1;
213
200
  }
214
201
 
215
- #endif
202
+ inline size_t getUtf16PositionByCounter(const char *data, size_t from, size_t n)
203
+ {
204
+ for (; n > 0; --n)
205
+ {
206
+ size_t s = getUtf8CharSize(data[from]);
207
+ from += s;
208
+ if (s == 4 && n >= 2)
209
+ --n; // this utf8 character will take two utf16 characters
210
+ // the decrement above is protected to avoid an overflow of an unsigned integer
211
+ }
212
+ return from;
213
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "re2",
3
- "version": "1.21.1",
3
+ "version": "1.21.2",
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",
@@ -28,9 +28,14 @@
28
28
  "test": "node tests/tests.js",
29
29
  "ts-test": "tsc",
30
30
  "save-to-github": "save-to-github-cache --artifact build/Release/re2.node",
31
- "install": "install-from-cache --artifact build/Release/re2.node --host-var RE2_DOWNLOAD_MIRROR --skip-path-var RE2_DOWNLOAD_SKIP_PATH --skip-ver-var RE2_DOWNLOAD_SKIP_VER || node-gyp rebuild",
31
+ "install": "install-from-cache --artifact build/Release/re2.node --host-var RE2_DOWNLOAD_MIRROR --skip-path-var RE2_DOWNLOAD_SKIP_PATH --skip-ver-var RE2_DOWNLOAD_SKIP_VER || node-gyp -j max rebuild",
32
32
  "verify-build": "node scripts/verify-build.js",
33
- "rebuild": "node-gyp rebuild"
33
+ "build:dev": "node-gyp -j max build --debug",
34
+ "build": "node-gyp -j max build",
35
+ "rebuild:dev": "node-gyp -j max rebuild --debug",
36
+ "rebuild": "node-gyp -j max rebuild",
37
+ "clean": "node-gyp clean",
38
+ "reconfigure": "node-gyp configure"
34
39
  },
35
40
  "github": "https://github.com/uhop/node-re2",
36
41
  "repository": {
package/re2.js CHANGED
@@ -1,38 +1,39 @@
1
1
  'use strict';
2
2
 
3
3
  const RE2 = require('./build/Release/re2.node');
4
+ // const RE2 = require('./build/Debug/re2.node');
4
5
 
5
- if (typeof Symbol != 'undefined') {
6
- Symbol.match &&
7
- (RE2.prototype[Symbol.match] = function (str) {
8
- return this.match(str);
9
- });
10
- Symbol.search &&
11
- (RE2.prototype[Symbol.search] = function (str) {
12
- return this.search(str);
13
- });
14
- Symbol.replace &&
15
- (RE2.prototype[Symbol.replace] = function (str, repl) {
16
- return this.replace(str, repl);
17
- });
18
- Symbol.split &&
19
- (RE2.prototype[Symbol.split] = function (str, limit) {
20
- return this.split(str, limit);
21
- });
22
- Symbol.matchAll &&
23
- (RE2.prototype[Symbol.matchAll] = function* (str) {
24
- if (!this.global) {
25
- throw TypeError('String.prototype.matchAll called with a non-global RE2 argument');
26
- }
27
- const re = new RE2(this, this.flags + '\b');
28
- re.lastIndex = this.lastIndex;
29
- for (;;) {
30
- const result = re.exec(str);
31
- if (!result) break;
32
- if (result[0] === '') ++re.lastIndex;
33
- yield result;
34
- }
35
- });
36
- }
6
+ const setAliases = (object, dict) => {
7
+ for (let [name, alias] of Object.entries(dict)) {
8
+ Object.defineProperty(
9
+ object,
10
+ alias,
11
+ Object.getOwnPropertyDescriptor(object, name)
12
+ );
13
+ }
14
+ };
15
+
16
+ setAliases(RE2.prototype, {
17
+ match: Symbol.match,
18
+ search: Symbol.search,
19
+ replace: Symbol.replace,
20
+ split: Symbol.split
21
+ });
22
+
23
+ RE2.prototype[Symbol.matchAll] = function* (str) {
24
+ if (!this.global)
25
+ throw TypeError(
26
+ 'String.prototype.matchAll() is called with a non-global RE2 argument'
27
+ );
28
+
29
+ const re = new RE2(this);
30
+ re.lastIndex = this.lastIndex;
31
+ for (;;) {
32
+ const result = re.exec(str);
33
+ if (!result) break;
34
+ if (result[0] === '') ++re.lastIndex;
35
+ yield result;
36
+ }
37
+ };
37
38
 
38
39
  module.exports = RE2;
package/lib/str-val.cc DELETED
@@ -1,112 +0,0 @@
1
- #include "./str-val.h"
2
-
3
- StrValBuffer::StrValBuffer(const v8::Local<v8::Value> &arg, size_t newIndex) : StrValBase()
4
- {
5
- if (!node::Buffer::HasInstance(arg))
6
- return;
7
-
8
- isBuffer = true;
9
- size = length = node::Buffer::Length(arg);
10
- data = node::Buffer::Data(arg);
11
-
12
- byteIndex = index = newIndex;
13
- isIndexValid = byteIndex < size;
14
- }
15
-
16
- inline size_t getUtf8CharSize(char ch)
17
- {
18
- return ((0xE5000000 >> ((ch >> 3) & 0x1E)) & 3) + 1;
19
- }
20
-
21
- inline size_t countBytes(const char *data, size_t from, size_t n)
22
- {
23
- for (; n > 0; --n)
24
- {
25
- size_t s = getUtf8CharSize(data[from]);
26
- from += s;
27
- if (s == 4 && n >= 2)
28
- --n; // this utf8 character will take two utf16 characters
29
- // the decrement above is protected to avoid an overflow of an unsigned integer
30
- }
31
- return from;
32
- }
33
-
34
- StrValString::StrValString(const v8::Local<v8::Value> &arg, size_t newIndex) : StrValBase()
35
- {
36
- if (node::Buffer::HasInstance(arg))
37
- return;
38
-
39
- auto t = arg->ToString(Nan::GetCurrentContext());
40
- if (t.IsEmpty())
41
- {
42
- isBad = true;
43
- return;
44
- }
45
-
46
- auto s = t.ToLocalChecked();
47
- length = Nan::DecodeBytes(s);
48
- size = Nan::DecodeBytes(s, Nan::UTF8);
49
- buffer.resize(size + 1);
50
- data = &buffer[0];
51
- Nan::DecodeWrite(data, size, s, Nan::UTF8);
52
- buffer[size] = '\0';
53
-
54
- index = newIndex;
55
- isIndexValid = index <= length;
56
-
57
- if (!isIndexValid || !index)
58
- return;
59
-
60
- if (index == length)
61
- {
62
- byteIndex = size;
63
- return;
64
- }
65
-
66
- byteIndex = countBytes(data, 0, index);
67
- }
68
-
69
- void StrValBase::setIndex(size_t newIndex)
70
- {
71
- isIndexValid = newIndex <= length;
72
- if (!isIndexValid)
73
- {
74
- index = newIndex;
75
- byteIndex = 0;
76
- return;
77
- }
78
-
79
- if (newIndex == index)
80
- return;
81
-
82
- if (isBuffer)
83
- {
84
- byteIndex = index = newIndex;
85
- return;
86
- }
87
-
88
- // String
89
-
90
- if (!newIndex)
91
- {
92
- byteIndex = index = 0;
93
- return;
94
- }
95
-
96
- if (newIndex == length)
97
- {
98
- byteIndex = size;
99
- index = length;
100
- return;
101
- }
102
-
103
- byteIndex = index < newIndex ? countBytes(data, byteIndex, newIndex - index) : countBytes(data, 0, newIndex);
104
- index = newIndex;
105
- }
106
-
107
- StrValBase *StrValBase::New(const v8::Local<v8::Value> &arg, size_t newIndex)
108
- {
109
- if (node::Buffer::HasInstance(arg))
110
- return new StrValBuffer(arg, newIndex);
111
- return new StrValString(arg, newIndex);
112
- }
package/lib/str-val.h DELETED
@@ -1,33 +0,0 @@
1
- #pragma once
2
- #include <vector>
3
- #include <nan.h>
4
- #include <re2/re2.h>
5
-
6
- struct StrValBase
7
- {
8
- char *data;
9
- size_t size, length;
10
- size_t index, byteIndex;
11
- bool isBuffer, isIndexValid, isBad;
12
-
13
- StrValBase() : data(NULL), size(0), length(0), index(0), byteIndex(0), isBuffer(false), isIndexValid(false), isBad(false) {}
14
- virtual ~StrValBase() {}
15
-
16
- operator re2::StringPiece() const { return re2::StringPiece(data, size); }
17
-
18
- void setIndex(size_t newIndex = 0);
19
-
20
- static StrValBase *New(const v8::Local<v8::Value> &arg, size_t newIndex = 0);
21
- };
22
-
23
- struct StrValBuffer : public StrValBase
24
- {
25
- StrValBuffer(const v8::Local<v8::Value> &arg, size_t newIndex = 0);
26
- };
27
-
28
- struct StrValString : public StrValBase
29
- {
30
- StrValString(const v8::Local<v8::Value> &arg, size_t newIndex = 0);
31
-
32
- std::vector<char> buffer;
33
- };