diff --git a/lib/addon.cc b/lib/addon.cc index 0dc7f73..37c8bbf 100644 --- a/lib/addon.cc +++ b/lib/addon.cc @@ -119,6 +119,8 @@ const StrVal &WrappedRE2::prepareArgument(const v8::Local &arg, bool if (lastString == arg && !node::Buffer::HasInstance(arg) && !lastCache.IsEmpty()) { // we have a properly cached string + lastString.ClearWeak(); + lastCache.ClearWeak(); lastStringValue.setIndex(startFrom); return lastStringValue; } @@ -130,7 +132,6 @@ const StrVal &WrappedRE2::prepareArgument(const v8::Local &arg, bool // no need to cache buffers lastString.Reset(arg); - static_cast &>(lastString).SetWeak(); auto argSize = node::Buffer::Length(arg); lastStringValue.reset(arg, argSize, argSize, startFrom, true); @@ -149,14 +150,12 @@ const StrVal &WrappedRE2::prepareArgument(const v8::Local &arg, bool } lastString.Reset(arg); - static_cast &>(lastString).SetWeak(); auto s = t.ToLocalChecked(); auto argLength = Nan::DecodeBytes(s); auto buffer = node::Buffer::New(v8::Isolate::GetCurrent(), s).ToLocalChecked(); lastCache.Reset(buffer); - static_cast &>(lastCache).SetWeak(); auto argSize = node::Buffer::Length(buffer); lastStringValue.reset(buffer, argSize, argLength, startFrom); @@ -164,6 +163,19 @@ const StrVal &WrappedRE2::prepareArgument(const v8::Local &arg, bool return lastStringValue; }; +void WrappedRE2::doneWithLastString() +{ + if (!lastString.IsEmpty()) + { + static_cast &>(lastString).SetWeak(); + } + + if (!lastCache.IsEmpty()) + { + static_cast &>(lastCache).SetWeak(); + } +} + // StrVal void StrVal::setIndex(size_t newIndex) diff --git a/lib/exec.cc b/lib/exec.cc index 29729f8..7d016ae 100644 --- a/lib/exec.cc +++ b/lib/exec.cc @@ -14,7 +14,8 @@ NAN_METHOD(WrappedRE2::Exec) return; } - auto str = re2->prepareArgument(info[0]); + PrepareLastString prep(re2, info[0]); + StrVal& str = prep; if (str.isBad) return; // throws an exception if (re2->global || re2->sticky) diff --git a/lib/match.cc b/lib/match.cc index 59176dc..d92c2d7 100644 --- a/lib/match.cc +++ b/lib/match.cc @@ -14,7 +14,8 @@ NAN_METHOD(WrappedRE2::Match) return; } - auto str = re2->prepareArgument(info[0], re2->global); + PrepareLastString prep(re2, info[0]); + StrVal& str = prep; if (str.isBad) return; // throws an exception if (!str.isValidIndex) diff --git a/lib/replace.cc b/lib/replace.cc index cee3185..2528989 100644 --- a/lib/replace.cc +++ b/lib/replace.cc @@ -497,7 +497,8 @@ NAN_METHOD(WrappedRE2::Replace) return; } - auto replacee = re2->prepareArgument(info[0]); + PrepareLastString prep(re2, info[0]); + StrVal& replacee = prep; if (replacee.isBad) return; // throws an exception if (!replacee.isValidIndex) diff --git a/lib/search.cc b/lib/search.cc index 1d02761..6846ac6 100644 --- a/lib/search.cc +++ b/lib/search.cc @@ -12,7 +12,8 @@ NAN_METHOD(WrappedRE2::Search) return; } - auto str = re2->prepareArgument(info[0], true); + PrepareLastString prep(re2, info[0]); + StrVal& str = prep; if (str.isBad) return; // throws an exception if (!str.data) diff --git a/lib/split.cc b/lib/split.cc index ceaa545..26b595b 100644 --- a/lib/split.cc +++ b/lib/split.cc @@ -19,7 +19,8 @@ NAN_METHOD(WrappedRE2::Split) return; } - auto str = re2->prepareArgument(info[0], true); + PrepareLastString prep(re2, info[0]); + StrVal& str = prep; if (str.isBad) return; // throws an exception size_t limit = std::numeric_limits::max(); diff --git a/lib/test.cc b/lib/test.cc index 8abf584..76c6a6f 100644 --- a/lib/test.cc +++ b/lib/test.cc @@ -14,7 +14,8 @@ NAN_METHOD(WrappedRE2::Test) return; } - auto str = re2->prepareArgument(info[0]); + PrepareLastString prep(re2, info[0]); + StrVal& str = prep; if (str.isBad) return; // throws an exception if (!re2->global && !re2->sticky) diff --git a/lib/wrapped_re2.h b/lib/wrapped_re2.h index 6a6c1c3..50ddd05 100644 --- a/lib/wrapped_re2.h +++ b/lib/wrapped_re2.h @@ -119,6 +119,30 @@ class WrappedRE2 : public Nan::ObjectWrap void dropCache(); const StrVal &prepareArgument(const v8::Local &arg, bool ignoreLastIndex = false); + void doneWithLastString(); + + friend class PrepareLastString; +}; + +struct PrepareLastString +{ + PrepareLastString(WrappedRE2 *re2, const v8::Local &arg, bool ignoreLastIndex = false) : re2(re2) { + re2->prepareArgument(arg, ignoreLastIndex); + } + + ~PrepareLastString() { + re2->doneWithLastString(); + } + + operator const StrVal&() const { + return re2->lastStringValue; + } + + operator StrVal&() { + return re2->lastStringValue; + } + + WrappedRE2 *re2; }; // utilities