Commit 3b50b824 authored by Ben Kelly's avatar Ben Kelly Committed by Chromium LUCI CQ

Make ScriptRegexp GarbageCollected<>.

It contains a traceable v8 object, yet was previously always owned
via a std::unique_ptr<>.  Current best practice recommends a
GarbageCollected<> type here instead.

Bug: 1141510
Change-Id: Ia823ccc8388ed43c1ca3a90d2ecc841c07ddfe55
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2571810
Commit-Queue: Ben Kelly <wanderview@chromium.org>
Reviewed-by: default avatarJeremy Roman <jbroman@chromium.org>
Cr-Commit-Position: refs/heads/master@{#833504}
parent 18af61b5
......@@ -125,4 +125,8 @@ int ScriptRegexp::Match(const String& string,
return match_offset.As<v8::Int32>()->Value() + start_from;
}
void ScriptRegexp::Trace(Visitor* visitor) const {
visitor->Trace(regex_);
}
} // namespace blink
......@@ -29,7 +29,8 @@
#include "base/macros.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/platform/bindings/scoped_persistent.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
#include "v8/include/v8.h"
......@@ -37,9 +38,7 @@ namespace blink {
enum MultilineMode { kMultilineDisabled, kMultilineEnabled };
class CORE_EXPORT ScriptRegexp {
USING_FAST_MALLOC(ScriptRegexp);
class CORE_EXPORT ScriptRegexp final : public GarbageCollected<ScriptRegexp> {
public:
enum CharacterMode {
BMP, // NOLINT
......@@ -61,8 +60,10 @@ class CORE_EXPORT ScriptRegexp {
// exceptionMessage is available only if !isValid().
String ExceptionMessage() const { return exception_message_; }
void Trace(Visitor* visitor) const;
private:
ScopedPersistent<v8::RegExp> regex_;
TraceWrapperV8Reference<v8::RegExp> regex_;
String exception_message_;
DISALLOW_COPY_AND_ASSIGN(ScriptRegexp);
......
......@@ -33,6 +33,7 @@ class DocumentData final : public GarbageCollected<DocumentData> {
visitor->Trace(floc_service_);
visitor->Trace(has_trust_tokens_answerer_);
visitor->Trace(pending_has_trust_tokens_resolvers_);
visitor->Trace(email_regexp_);
}
private:
......@@ -60,7 +61,7 @@ class DocumentData final : public GarbageCollected<DocumentData> {
pending_has_trust_tokens_resolvers_;
// To do email regex checks.
std::unique_ptr<ScriptRegexp> email_regexp_;
Member<ScriptRegexp> email_regexp_;
friend class Document;
};
......
......@@ -32,6 +32,11 @@
namespace blink {
void BaseTextInputType::Trace(Visitor* visitor) const {
visitor->Trace(regexp_);
TextFieldInputType::Trace(visitor);
}
BaseTextInputType::BaseTextInputType(HTMLInputElement& element)
: TextFieldInputType(element) {}
......@@ -84,9 +89,9 @@ bool BaseTextInputType::PatternMismatch(const String& value) const {
if (raw_pattern.IsNull() || value.IsEmpty())
return false;
if (!regexp_ || pattern_for_regexp_ != raw_pattern) {
std::unique_ptr<ScriptRegexp> raw_regexp(
new ScriptRegexp(raw_pattern, kTextCaseSensitive, kMultilineDisabled,
ScriptRegexp::UTF16));
ScriptRegexp* raw_regexp = MakeGarbageCollected<ScriptRegexp>(
raw_pattern, kTextCaseSensitive, kMultilineDisabled,
ScriptRegexp::UTF16);
if (!raw_regexp->IsValid()) {
GetElement().GetDocument().AddConsoleMessage(
MakeGarbageCollected<ConsoleMessage>(
......@@ -95,13 +100,13 @@ bool BaseTextInputType::PatternMismatch(const String& value) const {
"Pattern attribute value " + raw_pattern +
" is not a valid regular expression: " +
raw_regexp->ExceptionMessage()));
regexp_.reset(raw_regexp.release());
regexp_ = raw_regexp;
pattern_for_regexp_ = raw_pattern;
return false;
}
String pattern = "^(?:" + raw_pattern + ")$";
regexp_.reset(new ScriptRegexp(pattern, kTextCaseSensitive,
kMultilineDisabled, ScriptRegexp::UTF16));
regexp_ = MakeGarbageCollected<ScriptRegexp>(
pattern, kTextCaseSensitive, kMultilineDisabled, ScriptRegexp::UTF16);
pattern_for_regexp_ = raw_pattern;
} else if (!regexp_->IsValid()) {
return false;
......
......@@ -40,6 +40,9 @@ class ScriptRegexp;
// Base of email, password, search, tel, text, and URL types.
// They support maxlength, selection functions, and so on.
class BaseTextInputType : public TextFieldInputType {
public:
void Trace(Visitor* visitor) const override;
protected:
BaseTextInputType(HTMLInputElement&);
~BaseTextInputType() override;
......@@ -57,7 +60,7 @@ class BaseTextInputType : public TextFieldInputType {
// regexp_ and pattern_for_regexp_ are mutable because they are kinds of
// cache.
mutable std::unique_ptr<ScriptRegexp> regexp_;
mutable Member<ScriptRegexp> regexp_;
mutable AtomicString pattern_for_regexp_;
};
......
......@@ -57,8 +57,8 @@ static const int32_t kMaximumDomainNameLength = 255;
// Use the same option as in url/url_canon_icu.cc
static const int32_t kIdnaConversionOption = UIDNA_CHECK_BIDI;
std::unique_ptr<ScriptRegexp> EmailInputType::CreateEmailRegexp() {
return std::make_unique<ScriptRegexp>(kEmailPattern,
ScriptRegexp* EmailInputType::CreateEmailRegexp() {
return MakeGarbageCollected<ScriptRegexp>(kEmailPattern,
kTextCaseUnicodeInsensitive);
}
......
......@@ -44,7 +44,7 @@ class EmailInputType final : public BaseTextInputType {
const String&);
CORE_EXPORT static bool IsValidEmailAddress(const ScriptRegexp&,
const String&);
CORE_EXPORT static std::unique_ptr<ScriptRegexp> CreateEmailRegexp();
CORE_EXPORT static ScriptRegexp* CreateEmailRegexp();
private:
void CountUsage() override;
......
......@@ -12,8 +12,7 @@ namespace blink {
namespace {
void ExpectToSucceed(const String& source) {
std::unique_ptr<ScriptRegexp> email_regexp =
EmailInputType::CreateEmailRegexp();
ScriptRegexp* email_regexp = EmailInputType::CreateEmailRegexp();
String result =
EmailInputType::ConvertEmailAddressToASCII(*email_regexp, source);
EXPECT_NE(source, result);
......@@ -21,8 +20,7 @@ void ExpectToSucceed(const String& source) {
}
void ExpectToFail(const String& source) {
std::unique_ptr<ScriptRegexp> email_regexp =
EmailInputType::CreateEmailRegexp();
ScriptRegexp* email_regexp = EmailInputType::CreateEmailRegexp();
// Conversion failed. The resultant value might contains non-ASCII
// characters, and not a valid email address.
EXPECT_FALSE(EmailInputType::IsValidEmailAddress(
......
......@@ -1565,7 +1565,8 @@ InspectorStyleSheet::BuildObjectForStyleSheetInfo() {
std::unique_ptr<protocol::Array<protocol::CSS::Value>>
InspectorStyleSheet::SelectorsFromSource(CSSRuleSourceData* source_data,
const String& sheet_text) {
ScriptRegexp comment("/\\*[^]*?\\*/", kTextCaseSensitive, kMultilineEnabled);
auto* comment = MakeGarbageCollected<ScriptRegexp>(
"/\\*[^]*?\\*/", kTextCaseSensitive, kMultilineEnabled);
auto result = std::make_unique<protocol::Array<protocol::CSS::Value>>();
const Vector<SourceRange>& ranges = source_data->selector_ranges;
for (wtf_size_t i = 0, size = ranges.size(); i < size; ++i) {
......@@ -1576,7 +1577,7 @@ InspectorStyleSheet::SelectorsFromSource(CSSRuleSourceData* source_data,
// meaningful parts.
int match_length;
int offset = 0;
while ((offset = comment.Match(selector, offset, &match_length)) >= 0)
while ((offset = comment->Match(selector, offset, &match_length)) >= 0)
selector.replace(offset, match_length, "");
std::unique_ptr<protocol::CSS::Value> simple_selector =
......
......@@ -26,7 +26,9 @@ static constexpr size_t kMaximumStringLength = 2 * 1024;
bool PaymentsValidators::IsValidCurrencyCodeFormat(
const String& code,
String* optional_error_message) {
if (ScriptRegexp("^[A-Z]{3}$", kTextCaseUnicodeInsensitive).Match(code) == 0)
auto* regexp = MakeGarbageCollected<ScriptRegexp>(
"^[A-Z]{3}$", kTextCaseUnicodeInsensitive);
if (regexp->Match(code) == 0)
return true;
if (optional_error_message) {
......@@ -41,8 +43,9 @@ bool PaymentsValidators::IsValidCurrencyCodeFormat(
bool PaymentsValidators::IsValidAmountFormat(const String& amount,
const String& item_name,
String* optional_error_message) {
if (ScriptRegexp("^-?[0-9]+(\\.[0-9]+)?$", kTextCaseSensitive)
.Match(amount) == 0)
auto* regexp = MakeGarbageCollected<ScriptRegexp>("^-?[0-9]+(\\.[0-9]+)?$",
kTextCaseSensitive);
if (regexp->Match(amount) == 0)
return true;
if (optional_error_message) {
......@@ -56,7 +59,9 @@ bool PaymentsValidators::IsValidAmountFormat(const String& amount,
bool PaymentsValidators::IsValidCountryCodeFormat(
const String& code,
String* optional_error_message) {
if (ScriptRegexp("^[A-Z]{2}$", kTextCaseSensitive).Match(code) == 0)
auto* regexp =
MakeGarbageCollected<ScriptRegexp>("^[A-Z]{2}$", kTextCaseSensitive);
if (regexp->Match(code) == 0)
return true;
if (optional_error_message)
......@@ -147,9 +152,9 @@ bool PaymentsValidators::IsValidMethodFormat(const String& identifier) {
if (!url.IsValid()) {
// Syntax for a valid standardized PMI:
// https://www.w3.org/TR/payment-method-id/#dfn-syntax-of-a-standardized-payment-method-identifier
return ScriptRegexp("^[a-z]+[0-9a-z]*(-[a-z]+[0-9a-z]*)*$",
kTextCaseSensitive)
.Match(identifier) == 0;
auto* regexp = MakeGarbageCollected<ScriptRegexp>(
"^[a-z]+[0-9a-z]*(-[a-z]+[0-9a-z]*)*$", kTextCaseSensitive);
return regexp->Match(identifier) == 0;
}
// URL PMI validation rules:
......
......@@ -18,16 +18,20 @@ namespace blink {
// A struct representing all the information needed to match a particular
// component of a URL.
struct URLPattern::Component {
class URLPattern::Component final
: public GarbageCollected<URLPattern::Component> {
public:
void Trace(Visitor* visitor) const { visitor->Trace(regexp); }
// The pattern compiled down to a js regular expression.
std::unique_ptr<ScriptRegexp> regexp;
Member<ScriptRegexp> regexp;
// The names to be applied to the regular expression capture groups. Note,
// liburlpattern regular expressions do not use named capture groups directly.
WTF::Vector<String> name_list;
Component(std::unique_ptr<ScriptRegexp> r, WTF::Vector<String> n)
: regexp(std::move(r)), name_list(std::move(n)) {}
Component(ScriptRegexp* r, WTF::Vector<String> n)
: regexp(r), name_list(std::move(n)) {}
};
namespace {
......@@ -176,73 +180,71 @@ URLPattern* URLPattern::Create(const URLPatternInit* init,
// be used for matching. Components that match any input may have a
// nullptr Component struct pointer.
auto protocol_component = CompilePattern(
auto* protocol_component = CompilePattern(
protocol, kDefaultPattern, "protocol", DefaultOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
auto username_component = CompilePattern(
auto* username_component = CompilePattern(
username, kDefaultPattern, "username", DefaultOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
auto password_component = CompilePattern(
auto* password_component = CompilePattern(
password, kDefaultPattern, "password", DefaultOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
auto hostname_component =
auto* hostname_component =
CompilePattern(hostname, kDefaultPattern, "hostname", HostnameOptions(),
exception_state);
if (exception_state.HadException())
return nullptr;
auto port_component = CompilePattern(port, kDefaultPattern, "port",
auto* port_component = CompilePattern(port, kDefaultPattern, "port",
DefaultOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
auto pathname_component =
auto* pathname_component =
CompilePattern(pathname, kDefaultPathnamePattern, "pathname",
PathnameOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
auto search_component = CompilePattern(search, kDefaultPattern, "search",
auto* search_component = CompilePattern(search, kDefaultPattern, "search",
DefaultOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
auto hash_component = CompilePattern(hash, kDefaultPattern, "hash",
auto* hash_component = CompilePattern(hash, kDefaultPattern, "hash",
DefaultOptions(), exception_state);
if (exception_state.HadException())
return nullptr;
return MakeGarbageCollected<URLPattern>(
std::move(protocol_component), std::move(username_component),
std::move(password_component), std::move(hostname_component),
std::move(port_component), std::move(pathname_component),
std::move(search_component), std::move(hash_component),
base::PassKey<URLPattern>());
protocol_component, username_component, password_component,
hostname_component, port_component, pathname_component, search_component,
hash_component, base::PassKey<URLPattern>());
}
URLPattern::URLPattern(std::unique_ptr<Component> protocol,
std::unique_ptr<Component> username,
std::unique_ptr<Component> password,
std::unique_ptr<Component> hostname,
std::unique_ptr<Component> port,
std::unique_ptr<Component> pathname,
std::unique_ptr<Component> search,
std::unique_ptr<Component> hash,
URLPattern::URLPattern(Component* protocol,
Component* username,
Component* password,
Component* hostname,
Component* port,
Component* pathname,
Component* search,
Component* hash,
base::PassKey<URLPattern> key)
: protocol_(std::move(protocol)),
username_(std::move(username)),
password_(std::move(password)),
hostname_(std::move(hostname)),
port_(std::move(port)),
pathname_(std::move(pathname)),
search_(std::move(search)),
hash_(std::move(hash)) {}
: protocol_(protocol),
username_(username),
password_(password),
hostname_(hostname),
port_(port),
pathname_(pathname),
search_(search),
hash_(hash) {}
bool URLPattern::test(const USVStringOrURLPatternInit& input,
ExceptionState& exception_state) {
......@@ -336,8 +338,20 @@ String URLPattern::toRegExp(const String& component,
return String();
}
void URLPattern::Trace(Visitor* visitor) const {
visitor->Trace(protocol_);
visitor->Trace(username_);
visitor->Trace(password_);
visitor->Trace(hostname_);
visitor->Trace(port_);
visitor->Trace(pathname_);
visitor->Trace(search_);
visitor->Trace(hash_);
ScriptWrappable::Trace(visitor);
}
// static
std::unique_ptr<URLPattern::Component> URLPattern::CompilePattern(
URLPattern::Component* URLPattern::CompilePattern(
const String& pattern,
const String& default_pattern,
StringView component,
......@@ -368,7 +382,7 @@ std::unique_ptr<URLPattern::Component> URLPattern::CompilePattern(
auto case_sensitive = options.sensitive ? WTF::kTextCaseSensitive
: WTF::kTextCaseASCIIInsensitive;
DCHECK(base::IsStringASCII(regexp_string));
auto regexp = std::make_unique<ScriptRegexp>(
ScriptRegexp* regexp = MakeGarbageCollected<ScriptRegexp>(
String(regexp_string.data(), regexp_string.size()), case_sensitive);
if (!regexp->IsValid()) {
// TODO: Figure out which embedded regex expression caused the failure
......@@ -386,7 +400,7 @@ std::unique_ptr<URLPattern::Component> URLPattern::CompilePattern(
wtf_name_list.push_back(String(name.data(), name.size()));
}
return std::make_unique<URLPattern::Component>(std::move(regexp),
return MakeGarbageCollected<URLPattern::Component>(std::move(regexp),
std::move(wtf_name_list));
}
......
......@@ -21,20 +21,20 @@ class USVStringOrURLPatternInit;
class URLPattern : public ScriptWrappable {
DEFINE_WRAPPERTYPEINFO();
struct Component;
class Component;
public:
static URLPattern* Create(const URLPatternInit* init,
ExceptionState& exception_state);
URLPattern(std::unique_ptr<Component> protocol,
std::unique_ptr<Component> username,
std::unique_ptr<Component> password,
std::unique_ptr<Component> hostname,
std::unique_ptr<Component> port,
std::unique_ptr<Component> pathname,
std::unique_ptr<Component> search,
std::unique_ptr<Component> hash,
URLPattern(Component* protocol,
Component* username,
Component* password,
Component* hostname,
Component* port,
Component* pathname,
Component* search,
Component* hash,
base::PassKey<URLPattern> key);
bool test(const USVStringOrURLPatternInit& input,
......@@ -45,6 +45,8 @@ class URLPattern : public ScriptWrappable {
// TODO: define a stringifier
void Trace(Visitor* visitor) const override;
private:
// A utility function that takes a given |pattern| and compiles it into a
// Component structure. If the |pattern| matches the given |default_pattern|
......@@ -52,8 +54,7 @@ class URLPattern : public ScriptWrappable {
// the Component is not constructed and the nullptr value should be treated as
// matching any input value for the component. The |component| string is used
// for exception messages. The |options| control how the pattern is compiled.
static std::unique_ptr<Component> CompilePattern(
const String& pattern,
static Component* CompilePattern(const String& pattern,
const String& default_pattern,
StringView component,
const liburlpattern::Options& options,
......@@ -61,14 +62,14 @@ class URLPattern : public ScriptWrappable {
// The compiled patterns for each URL component. If a Component member is
// nullptr then it should be treated as a wildcard matching any input.
std::unique_ptr<Component> protocol_;
std::unique_ptr<Component> username_;
std::unique_ptr<Component> password_;
std::unique_ptr<Component> hostname_;
std::unique_ptr<Component> port_;
std::unique_ptr<Component> pathname_;
std::unique_ptr<Component> search_;
std::unique_ptr<Component> hash_;
Member<Component> protocol_;
Member<Component> username_;
Member<Component> password_;
Member<Component> hostname_;
Member<Component> port_;
Member<Component> pathname_;
Member<Component> search_;
Member<Component> hash_;
};
} // namespace blink
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment