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 +1 -0
- package/binding.gyp +0 -1
- package/lib/accessors.cc +0 -28
- package/lib/addon.cc +92 -49
- package/lib/exec.cc +2 -4
- package/lib/match.cc +2 -4
- package/lib/new.cc +1 -6
- package/lib/replace.cc +27 -15
- package/lib/search.cc +1 -3
- package/lib/split.cc +1 -3
- package/lib/test.cc +2 -4
- package/lib/to_string.cc +0 -4
- package/lib/util.h +1 -4
- package/lib/wrapped_re2.h +40 -42
- package/package.json +8 -3
- package/re2.js +33 -32
- package/lib/str-val.cc +0 -112
- package/lib/str-val.h +0 -33
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
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
|
-
|
|
100
|
-
{
|
|
101
|
-
*ptr = nullptr;
|
|
102
|
-
}
|
|
103
|
-
dropLastString();
|
|
95
|
+
dropCache();
|
|
104
96
|
}
|
|
105
97
|
|
|
106
98
|
// private methods
|
|
107
99
|
|
|
108
|
-
|
|
100
|
+
void WrappedRE2::dropCache()
|
|
109
101
|
{
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
-
|
|
115
|
+
const StrVal& WrappedRE2::prepareArgument(const v8::Local<v8::Value> &arg, bool ignoreLastIndex)
|
|
116
116
|
{
|
|
117
|
-
|
|
118
|
-
}
|
|
117
|
+
size_t startFrom = ignoreLastIndex ? 0 : lastIndex;
|
|
119
118
|
|
|
120
|
-
|
|
121
|
-
{
|
|
122
|
-
lastString.Reset();
|
|
123
|
-
if (lastStringValue)
|
|
119
|
+
if (lastString == arg && !node::Buffer::HasInstance(arg) && !lastCache.IsEmpty())
|
|
124
120
|
{
|
|
125
|
-
|
|
126
|
-
lastStringValue
|
|
121
|
+
// we have a properly cached string
|
|
122
|
+
lastStringValue.setIndex(startFrom);
|
|
123
|
+
return lastStringValue;
|
|
127
124
|
}
|
|
128
|
-
}
|
|
129
125
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if (*re2)
|
|
126
|
+
dropCache();
|
|
127
|
+
|
|
128
|
+
if (node::Buffer::HasInstance(arg))
|
|
134
129
|
{
|
|
135
|
-
|
|
136
|
-
|
|
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
|
-
|
|
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
|
-
|
|
171
|
+
isValidIndex = newIndex <= length;
|
|
172
|
+
if (!isValidIndex)
|
|
173
|
+
{
|
|
174
|
+
index = newIndex;
|
|
175
|
+
byteIndex = 0;
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
144
178
|
|
|
145
|
-
if (
|
|
179
|
+
if (newIndex == index)
|
|
180
|
+
return;
|
|
181
|
+
|
|
182
|
+
if (isBuffer)
|
|
146
183
|
{
|
|
147
|
-
|
|
148
|
-
lastStringValue = new StrValBuffer(arg, startFrom);
|
|
184
|
+
byteIndex = index = newIndex;
|
|
149
185
|
return;
|
|
150
186
|
}
|
|
151
187
|
|
|
152
188
|
// String
|
|
153
189
|
|
|
154
|
-
|
|
155
|
-
if (lastString == arg && lastStringValue)
|
|
190
|
+
if (!newIndex)
|
|
156
191
|
{
|
|
157
|
-
|
|
158
|
-
return; // we are good
|
|
159
|
-
lastStringValue->setIndex(startFrom);
|
|
192
|
+
byteIndex = index = 0;
|
|
160
193
|
return;
|
|
161
194
|
}
|
|
162
195
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
196
|
+
if (newIndex == length)
|
|
197
|
+
{
|
|
198
|
+
byteIndex = size;
|
|
199
|
+
index = length;
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
167
202
|
|
|
168
|
-
|
|
169
|
-
|
|
203
|
+
byteIndex = index < newIndex ? getUtf16PositionByCounter(data, byteIndex, newIndex - index) : getUtf16PositionByCounter(data, 0, newIndex);
|
|
204
|
+
index = newIndex;
|
|
205
|
+
}
|
|
170
206
|
|
|
171
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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,
|
|
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
|
|
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
|
-
|
|
374
|
-
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
522
|
-
if (
|
|
523
|
-
|
|
524
|
-
if (!replacer->data)
|
|
525
|
+
v8::Local<v8::Object> replacer;
|
|
526
|
+
if (node::Buffer::HasInstance(info[1]))
|
|
525
527
|
{
|
|
526
|
-
info.
|
|
527
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
26
|
+
if (!str.isValidIndex)
|
|
29
27
|
{
|
|
30
28
|
re2->lastIndex = 0;
|
|
31
29
|
info.GetReturnValue().SetNull();
|
package/lib/to_string.cc
CHANGED
package/lib/util.h
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
#
|
|
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
|
-
#
|
|
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
|
-
|
|
9
|
-
|
|
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
|
-
|
|
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
|
|
113
|
+
friend struct PrepareLastString;
|
|
104
114
|
|
|
105
115
|
private:
|
|
106
116
|
Nan::Persistent<v8::Value> lastString; // weak pointer
|
|
107
|
-
|
|
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
|
|
118
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
"
|
|
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
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
Symbol.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
};
|