Skip to content

Commit 6d1acdd

Browse files
authored
Fix reachability calculations for $dynamicRef targets (#2226)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent 407aec4 commit 6d1acdd

File tree

2 files changed

+429
-12
lines changed

2 files changed

+429
-12
lines changed

src/core/jsonschema/frame.cc

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1483,6 +1483,22 @@ auto SchemaFrame::populate_reachability(const SchemaWalker &walker,
14831483
// (2) Build a reverse mapping from reference destinations to their sources
14841484
// ---------------------------------------------------------------------------
14851485

1486+
std::unordered_map<std::string_view, std::vector<const WeakPointer *>>
1487+
dynamic_anchors_by_fragment;
1488+
for (const auto &location : this->locations_) {
1489+
if (location.first.first == SchemaReferenceType::Dynamic &&
1490+
location.second.type == LocationType::Anchor) {
1491+
const auto &uri{location.first.second};
1492+
const auto hash_pos{uri.rfind('#')};
1493+
if (hash_pos != std::string::npos) {
1494+
std::string_view fragment{uri.data() + hash_pos + 1,
1495+
uri.size() - hash_pos - 1};
1496+
dynamic_anchors_by_fragment[fragment].push_back(
1497+
&location.second.pointer);
1498+
}
1499+
}
1500+
}
1501+
14861502
std::vector<std::pair<const WeakPointer *, const WeakPointer *>>
14871503
reference_destinations;
14881504
reference_destinations.reserve(this->references_.size());
@@ -1493,21 +1509,25 @@ auto SchemaFrame::populate_reachability(const SchemaWalker &walker,
14931509
continue;
14941510
}
14951511

1496-
const WeakPointer *destination_pointer{nullptr};
1497-
const auto destination_location{this->locations_.find(
1498-
{SchemaReferenceType::Static, reference.second.destination})};
1499-
if (destination_location != this->locations_.cend()) {
1500-
destination_pointer = &destination_location->second.pointer;
1501-
} else {
1502-
const auto dynamic_destination{this->locations_.find(
1503-
{SchemaReferenceType::Dynamic, reference.second.destination})};
1504-
if (dynamic_destination != this->locations_.cend()) {
1505-
destination_pointer = &dynamic_destination->second.pointer;
1512+
if (reference.first.first == SchemaReferenceType::Dynamic &&
1513+
reference.second.fragment.has_value()) {
1514+
const auto &fragment{reference.second.fragment.value()};
1515+
const auto match{dynamic_anchors_by_fragment.find(fragment)};
1516+
if (match != dynamic_anchors_by_fragment.cend()) {
1517+
for (const auto *destination_pointer : match->second) {
1518+
reference_destinations.emplace_back(&source_pointer,
1519+
destination_pointer);
1520+
}
15061521
}
1522+
1523+
continue;
15071524
}
15081525

1509-
if (destination_pointer != nullptr) {
1510-
reference_destinations.emplace_back(&source_pointer, destination_pointer);
1526+
const auto destination_location{this->locations_.find(
1527+
{SchemaReferenceType::Static, reference.second.destination})};
1528+
if (destination_location != this->locations_.cend()) {
1529+
reference_destinations.emplace_back(
1530+
&source_pointer, &destination_location->second.pointer);
15111531
}
15121532
}
15131533

0 commit comments

Comments
 (0)