diff --git a/.mapping.json b/.mapping.json index 21a1b815f..d42fa4100 100644 --- a/.mapping.json +++ b/.mapping.json @@ -28068,6 +28068,8 @@ "test_data/parsing_test_data/templates/links_with_same_name.json":"divkit/public/test_data/parsing_test_data/templates/links_with_same_name.json", "test_data/parsing_test_data/templates/links_with_same_ref_name.json":"divkit/public/test_data/parsing_test_data/templates/links_with_same_ref_name.json", "test_data/parsing_test_data/templates/nested_template_usage.json":"divkit/public/test_data/parsing_test_data/templates/nested_template_usage.json", + "test_data/parsing_test_data/templates/same_link_in_one_template.json":"divkit/public/test_data/parsing_test_data/templates/same_link_in_one_template.json", + "test_data/parsing_test_data/templates/same_link_passed_to_nested_template.json":"divkit/public/test_data/parsing_test_data/templates/same_link_passed_to_nested_template.json", "test_data/parsing_test_data/templates/same_link_used_in_two_places.json":"divkit/public/test_data/parsing_test_data/templates/same_link_used_in_two_places.json", "test_data/parsing_test_data/templates/simple.json":"divkit/public/test_data/parsing_test_data/templates/simple.json", "test_data/parsing_test_data/templates/template_chain.json":"divkit/public/test_data/parsing_test_data/templates/template_chain.json", diff --git a/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift b/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift index 7c9f662c8..72faf7c17 100644 --- a/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift +++ b/client/ios/DivKit/Templates/UntypedDivTemplateResolver.swift @@ -76,35 +76,32 @@ final class UntypedDivTemplateResolver { linkSource: [String: Any] ) -> [String: Any] { var dict = dictionary - var consumedParams = Set() + var linkFieldNames = Set() let linkKeys = dict.keys.filter { $0.hasPrefix("$") } for linkKey in linkKeys { let key = String(linkKey.dropFirst()) + linkFieldNames.insert(key) guard let linkName = dict[linkKey] as? String else { continue } - consumedParams.insert(linkName) guard dict[key] == nil else { continue } guard let value = linkSource[linkName] else { continue } dict[key] = value } - var filteredLinkSource = linkSource - for name in consumedParams { - filteredLinkSource.removeValue(forKey: name) - } - var result: [String: Any] = [:] for (key, value) in dict { guard !key.hasPrefix("$") else { continue } - result[key] = resolveLinksInValue(value, linkSource: filteredLinkSource) + let childSource: [String: Any]? = linkFieldNames.contains(key) ? nil : linkSource + result[key] = resolveLinksInValue(value, linkSource: childSource) } return result } private func resolveLinksInValue( _ value: Any, - linkSource: [String: Any] + linkSource: [String: Any]? ) -> Any { if let dict = value as? [String: Any] { + let effectiveSource = linkSource ?? dict if let type = dict["type"] as? String, let resolvedTemplate = resolveTemplate(named: type).value { var parameterNames = collectParameterNames(from: resolvedTemplate) @@ -113,11 +110,11 @@ final class UntypedDivTemplateResolver { ) return resolveInstanceLinks( in: dict, - linkSource: linkSource, + linkSource: effectiveSource, parameterNames: parameterNames ) } - return resolveLinks(in: dict, linkSource: linkSource) + return resolveLinks(in: dict, linkSource: effectiveSource) } if let array = value as? [Any] { return array.map { resolveLinksInValue($0, linkSource: linkSource) } diff --git a/test_data/parsing_test_data/templates/same_link_in_one_template.json b/test_data/parsing_test_data/templates/same_link_in_one_template.json new file mode 100644 index 000000000..1deb4e81c --- /dev/null +++ b/test_data/parsing_test_data/templates/same_link_in_one_template.json @@ -0,0 +1,47 @@ +{ + "description": "Same ref name (content) used by top-level $-link ($text) and nested non-template $-link ($log_id in actions)", + "templates": { + "action_text": { + "type": "text", + "$text": "content", + "actions": [ + { + "$log_id": "content", + "url": "action://do" + } + ] + } + }, + "card": { + "log_id": "test", + "states": [ + { + "state_id": 0, + "div": { + "type": "action_text", + "content": "button" + } + } + ] + }, + "expected": { + "card": { + "log_id": "test", + "states": [ + { + "state_id": 0, + "div": { + "type": "text", + "text": "button", + "actions": [ + { + "log_id": "button", + "url": "action://do" + } + ] + } + } + ] + } + } +} \ No newline at end of file diff --git a/test_data/parsing_test_data/templates/same_link_passed_to_nested_template.json b/test_data/parsing_test_data/templates/same_link_passed_to_nested_template.json new file mode 100644 index 000000000..dd2d80227 --- /dev/null +++ b/test_data/parsing_test_data/templates/same_link_passed_to_nested_template.json @@ -0,0 +1,50 @@ +{ + "description": "Same ref name (dir) consumed by parent $-link ($orientation) and needed by child template instance ($text)", + "templates": { + "labeled_container": { + "type": "container", + "$orientation": "dir", + "items": [ + { + "type": "labeled_text" + } + ] + }, + "labeled_text": { + "type": "text", + "$text": "dir" + } + }, + "card": { + "log_id": "test", + "states": [ + { + "state_id": 0, + "div": { + "type": "labeled_container", + "dir": "vertical" + } + } + ] + }, + "expected": { + "card": { + "log_id": "test", + "states": [ + { + "state_id": 0, + "div": { + "type": "container", + "orientation": "vertical", + "items": [ + { + "type": "text", + "text": "vertical" + } + ] + } + } + ] + } + } +} \ No newline at end of file