diff --git a/client/ios/DivKit/DivBlockModelingContext.swift b/client/ios/DivKit/DivBlockModelingContext.swift index a6ad027bc..a5ed17cb0 100644 --- a/client/ios/DivKit/DivBlockModelingContext.swift +++ b/client/ios/DivKit/DivBlockModelingContext.swift @@ -14,7 +14,6 @@ import AppKit public struct DivBlockModelingContext { public let cardId: DivCardID var cardLogId: String? - public internal(set) var parentPath: UIElementPath var parentDivStatePath: DivStatePath? let stateManager: DivStateManager public let blockStateStorage: DivBlockStateStorage @@ -27,7 +26,6 @@ public struct DivBlockModelingContext { let flagsInfo: DivFlagsInfo let extensionHandlers: [String: DivExtensionHandler] let stateInterceptors: [String: DivStateInterceptor] - private let variables: DivVariables let layoutDirection: UserInterfaceLayoutDirection let debugParams: DebugParams let scheduler: Scheduling @@ -39,23 +37,24 @@ public struct DivBlockModelingContext { let tooltipViewFactory: DivTooltipViewFactory? private let variablesStorage: DivVariablesStorage private let variableTracker: DivVariableTracker? + public private (set) var expressionResolver: ExpressionResolver + + public internal(set) var parentPath: UIElementPath { + didSet { + expressionResolver = makeExpressionResolver( + cardId: cardId, + parentPath: parentPath, + variablesStorage: variablesStorage, + persistentValuesStorage: persistentValuesStorage, + errorsStorage: errorsStorage, + variableTracker: variableTracker + ) + } + } var overridenWidth: DivOverridenSize? var overridenHeight: DivOverridenSize? - public var expressionResolver: ExpressionResolver { - ExpressionResolver( - variables: variables, - persistentValuesStorage: persistentValuesStorage, - errorTracker: { [weak errorsStorage] error in - errorsStorage?.add(DivExpressionError(error, path: parentPath)) - }, - variableTracker: { [weak variableTracker] variables in - variableTracker?.onVariablesUsed(cardId: cardId, variables: variables) - } - ) - } - public init( cardId: DivCardID, cardLogId: String? = nil, @@ -86,7 +85,8 @@ public struct DivBlockModelingContext { ) { self.cardId = cardId self.cardLogId = cardLogId - self.parentPath = parentPath ?? UIElementPath(cardId.rawValue) + let parentPath = parentPath ?? UIElementPath(cardId.rawValue) + self.parentPath = parentPath self.parentDivStatePath = parentDivStatePath self.stateManager = stateManager self.blockStateStorage = blockStateStorage @@ -97,7 +97,6 @@ public struct DivBlockModelingContext { self.divCustomBlockFactory = divCustomBlockFactory ?? EmptyDivCustomBlockFactory() self.flagsInfo = flagsInfo self.fontProvider = fontProvider ?? DefaultFontProvider() - self.variables = variablesStorage.makeVariables(for: cardId) self.playerFactory = playerFactory self.debugParams = debugParams self.scheduler = scheduler ?? TimerScheduler() @@ -106,7 +105,8 @@ public struct DivBlockModelingContext { self.errorsStorage = errorsStorage ?? DivErrorsStorage(errors: []) self.layoutDirection = layoutDirection self.variableTracker = variableTracker - self.persistentValuesStorage = persistentValuesStorage ?? DivPersistentValuesStorage() + let persistentValuesStorage = persistentValuesStorage ?? DivPersistentValuesStorage() + self.persistentValuesStorage = persistentValuesStorage self.tooltipViewFactory = tooltipViewFactory self.variablesStorage = variablesStorage @@ -131,6 +131,15 @@ public struct DivBlockModelingContext { stateInterceptorsDictionary[id] = $0 } self.stateInterceptors = stateInterceptorsDictionary + + expressionResolver = makeExpressionResolver( + cardId: cardId, + parentPath: parentPath, + variablesStorage: variablesStorage, + persistentValuesStorage: persistentValuesStorage, + errorsStorage: errorsStorage, + variableTracker: variableTracker + ) } public func getExtensionHandlers(for div: DivBase) -> [DivExtensionHandler] { @@ -208,3 +217,23 @@ public struct DivBlockModelingContext { return Binding(name: variableName.rawValue, value: valueProp) } } + +private func makeExpressionResolver( + cardId: DivCardID, + parentPath: UIElementPath, + variablesStorage: DivVariablesStorage, + persistentValuesStorage: DivPersistentValuesStorage, + errorsStorage: DivErrorsStorage?, + variableTracker: DivVariableTracker? +) -> ExpressionResolver { + ExpressionResolver( + variables: variablesStorage.makeVariables(for: cardId), + persistentValuesStorage: persistentValuesStorage, + errorTracker: { [weak errorsStorage] error in + errorsStorage?.add(DivExpressionError(error, path: parentPath)) + }, + variableTracker: { [weak variableTracker] variables in + variableTracker?.onVariablesUsed(cardId: cardId, variables: variables) + } + ) +} diff --git a/client/ios/DivKit/Expressions/ExpressionResolver.swift b/client/ios/DivKit/Expressions/ExpressionResolver.swift index 0ca3f3a9b..279e713b7 100644 --- a/client/ios/DivKit/Expressions/ExpressionResolver.swift +++ b/client/ios/DivKit/Expressions/ExpressionResolver.swift @@ -23,12 +23,12 @@ public final class ExpressionResolver { variableTracker: @escaping VariableTracker = { _ in } ) { self.variables = variables + self.persistentValuesStorage = persistentValuesStorage self.errorTracker = { DivKitLogger.error($0.description) errorTracker?($0) } self.variableTracker = variableTracker - self.persistentValuesStorage = persistentValuesStorage } public func resolveString(expression: String) -> String { diff --git a/client/ios/DivKit/Expressions/Functions/ValueFunctions.swift b/client/ios/DivKit/Expressions/Functions/ValueFunctions.swift index 220338e57..36f0c910c 100644 --- a/client/ios/DivKit/Expressions/Functions/ValueFunctions.swift +++ b/client/ios/DivKit/Expressions/Functions/ValueFunctions.swift @@ -115,7 +115,7 @@ enum ValueFunctions: String, CaseIterable { extension ExpressionResolver { fileprivate func getValueFunction() -> GetOrDefault { - { name, fallbackValue in + { [unowned self] name, fallbackValue in self.variableTracker([DivVariableName(rawValue: name)]) guard let value = self.getValue(name) else { return fallbackValue @@ -131,7 +131,7 @@ extension ExpressionResolver { fileprivate func getValueFunctionWithTransform( transform: @escaping (U) throws -> T ) -> GetOrDefaultWithTransform { - { name, fallbackValue in + { [unowned self] name, fallbackValue in self.variableTracker([DivVariableName(rawValue: name)]) guard let value = self.getValue(name) else { return try transform(fallbackValue) @@ -145,7 +145,7 @@ extension ExpressionResolver { } fileprivate func getStoredValueFunction() -> GetOrDefault { - { name, fallbackValue in + { [unowned self] name, fallbackValue in guard let value: T = self.getStoredValue(name) else { return fallbackValue } @@ -156,7 +156,7 @@ extension ExpressionResolver { fileprivate func getStoredValueFunctionWithTransform( transform: @escaping (U) throws -> T ) -> GetOrDefaultWithTransform { - { name, fallbackValue in + { [unowned self] name, fallbackValue in guard let value: T = self.getStoredValue(name) else { return try transform(fallbackValue) } diff --git a/client/ios/DivKitExtensionsTests/ShimmerStyleTests.swift b/client/ios/DivKitExtensionsTests/ShimmerStyleTests.swift index 9ec704e11..ad6418890 100644 --- a/client/ios/DivKitExtensionsTests/ShimmerStyleTests.swift +++ b/client/ios/DivKitExtensionsTests/ShimmerStyleTests.swift @@ -7,8 +7,7 @@ import BasePublic final class ShimmerStyleTests: XCTestCase { private let expressionResolver = ExpressionResolver( variables: [:], - persistentValuesStorage: DivPersistentValuesStorage(), - errorTracker: nil + persistentValuesStorage: DivPersistentValuesStorage() ) func test_WhenDecodingEmptyShimmerStyle_DecodesWithDefaultValues() throws {