From 01ec3d815da75ed0eb24cac0243ecebe8338083d Mon Sep 17 00:00:00 2001 From: grechka62 Date: Wed, 14 May 2025 19:22:15 +0300 Subject: [PATCH] Support expressions in variables initialization commit_hash:1af4f28b41a00effe9c777281d3937e9e9581676 --- .../main/java/com/yandex/div/DivVariables.kt | 17 +-- .../main/java/com/yandex/div/data/Variable.kt | 17 +-- .../expression/ExpressionsRuntimeProvider.kt | 27 ++--- .../expression/local/DivRuntimeVisitor.kt | 2 +- .../div/core/expression/local/RuntimeStore.kt | 104 +++++++++--------- .../yandex/div/core/expression/local/utils.kt | 9 -- .../variables/DivVariablesParser.kt | 30 +++-- .../java/com/yandex/div/core/util/DivUtil.kt | 19 ---- .../core/expression/local/RuntimeStoreTest.kt | 16 +-- .../core/view2/local/LocalVariablesTest.kt | 4 +- .../IntegrationMultiplatformTest.kt | 5 +- schema/div-variable.json | 9 -- .../decl_extressions_nesting.json | 1 + .../decl_extressions_simple.json | 1 + .../decl_extressions_transitive.json | 1 + 15 files changed, 119 insertions(+), 143 deletions(-) diff --git a/client/android/div-data/src/main/java/com/yandex/div/DivVariables.kt b/client/android/div-data/src/main/java/com/yandex/div/DivVariables.kt index d297a9671..3df56ddf9 100644 --- a/client/android/div-data/src/main/java/com/yandex/div/DivVariables.kt +++ b/client/android/div-data/src/main/java/com/yandex/div/DivVariables.kt @@ -5,6 +5,7 @@ package com.yandex.div import android.net.Uri import androidx.annotation.ColorInt +import com.yandex.div.json.expressions.Expression import com.yandex.div2.ArrayVariable import com.yandex.div2.BoolVariable import com.yandex.div2.ColorVariable @@ -18,33 +19,33 @@ import org.json.JSONArray import org.json.JSONObject fun integerVariable(name: String, value: Long): DivVariable.Integer { - return DivVariable.Integer(IntegerVariable(name, value)) + return DivVariable.Integer(IntegerVariable(name, Expression.constant(value))) } fun numberVariable(name: String, value: Double): DivVariable.Number { - return DivVariable.Number(NumberVariable(name, value)) + return DivVariable.Number(NumberVariable(name, Expression.constant(value))) } fun boolVariable(name: String, value: Boolean): DivVariable.Bool { - return DivVariable.Bool(BoolVariable(name, value)) + return DivVariable.Bool(BoolVariable(name, Expression.constant(value))) } fun stringVariable(name: String, value: String): DivVariable.Str { - return DivVariable.Str(StrVariable(name, value)) + return DivVariable.Str(StrVariable(name, Expression.constant(value))) } fun colorVariable(name: String, @ColorInt value: Int): DivVariable.Color { - return DivVariable.Color(ColorVariable(name, value)) + return DivVariable.Color(ColorVariable(name, Expression.constant(value))) } fun urlVariable(name: String, value: Uri): DivVariable.Url { - return DivVariable.Url(UrlVariable(name, value)) + return DivVariable.Url(UrlVariable(name, Expression.constant(value))) } internal fun dictVariable(name: String, value: JSONObject): DivVariable.Dict { - return DivVariable.Dict(DictVariable(name, value)) + return DivVariable.Dict(DictVariable(name, Expression.constant(value))) } internal fun arrayVariable(name: String, value: JSONArray): DivVariable.Array { - return DivVariable.Array(ArrayVariable(name, value)) + return DivVariable.Array(ArrayVariable(name, Expression.constant(value))) } diff --git a/client/android/div-data/src/main/java/com/yandex/div/data/Variable.kt b/client/android/div-data/src/main/java/com/yandex/div/data/Variable.kt index 5cd2155f9..79744ed16 100644 --- a/client/android/div-data/src/main/java/com/yandex/div/data/Variable.kt +++ b/client/android/div-data/src/main/java/com/yandex/div/data/Variable.kt @@ -10,6 +10,7 @@ import com.yandex.div.internal.Assert import com.yandex.div.internal.parser.STRING_TO_COLOR_INT import com.yandex.div.internal.util.toBoolean import com.yandex.div.json.JSONSerializable +import com.yandex.div.json.expressions.Expression import com.yandex.div2.BoolVariable import org.json.JSONArray import org.json.JSONException @@ -321,14 +322,14 @@ sealed class Variable { fun writeToJSON(): JSONObject { val serializable: JSONSerializable = when (this) { - is ArrayVariable -> com.yandex.div2.ArrayVariable(this.name, this.value) - is BooleanVariable -> BoolVariable(this.name, this.value) - is ColorVariable -> com.yandex.div2.ColorVariable(this.name, this.value.value) - is DictVariable -> com.yandex.div2.DictVariable(this.name, this.value) - is DoubleVariable -> com.yandex.div2.NumberVariable(this.name, this.value) - is IntegerVariable -> com.yandex.div2.IntegerVariable(this.name, this.value) - is StringVariable -> com.yandex.div2.StrVariable(this.name, this.value) - is UrlVariable -> com.yandex.div2.UrlVariable(this.name, this.value) + is ArrayVariable -> com.yandex.div2.ArrayVariable(this.name, Expression.constant(this.value)) + is BooleanVariable -> BoolVariable(this.name, Expression.constant(this.value)) + is ColorVariable -> com.yandex.div2.ColorVariable(this.name, Expression.constant(this.value.value)) + is DictVariable -> com.yandex.div2.DictVariable(this.name, Expression.constant(this.value)) + is DoubleVariable -> com.yandex.div2.NumberVariable(this.name, Expression.constant(this.value)) + is IntegerVariable -> com.yandex.div2.IntegerVariable(this.name, Expression.constant(this.value)) + is StringVariable -> com.yandex.div2.StrVariable(this.name, Expression.constant(this.value)) + is UrlVariable -> com.yandex.div2.UrlVariable(this.name, Expression.constant(this.value)) } return serializable.writeToJSON() diff --git a/client/android/div/src/main/java/com/yandex/div/core/expression/ExpressionsRuntimeProvider.kt b/client/android/div/src/main/java/com/yandex/div/core/expression/ExpressionsRuntimeProvider.kt index 87cf0b054..632416530 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/expression/ExpressionsRuntimeProvider.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/expression/ExpressionsRuntimeProvider.kt @@ -20,6 +20,7 @@ import com.yandex.div.data.VariableDeclarationException import com.yandex.div.evaluable.EvaluationContext import com.yandex.div.evaluable.Evaluator import com.yandex.div.evaluable.function.GeneratedBuiltinFunctionProvider +import com.yandex.div.json.expressions.ExpressionResolver import com.yandex.div2.DivData import com.yandex.div2.DivVariable import java.util.Collections @@ -45,7 +46,7 @@ internal class ExpressionsRuntimeProvider @Inject constructor( val result = runtimes.getOrPut(tag.id) { createRuntimeFor(data, tag) } val errorCollector = errorCollectors.getOrCreate(tag, data) divDataTags.getOrPut(div2View, ::mutableSetOf).add(tag.id) - ensureVariablesSynced(result.variableController, data, errorCollector) + ensureVariablesSynced(result.variableController, result.expressionResolver, data, errorCollector) result.triggersController?.ensureTriggersSynced(data.variableTriggers ?: emptyList()) return result } @@ -69,13 +70,14 @@ internal class ExpressionsRuntimeProvider @Inject constructor( private fun ensureVariablesSynced( v: VariableController, + resolver: ExpressionResolver, data: DivData, errorCollector: ErrorCollector ) { data.variables?.forEach { val existingVariable = v.getMutableVariable(it.name) ?: run { try { - v.declare(it.toVariable()) + v.declare(it.toVariable(resolver)) } catch (e: VariableDeclarationException) { errorCollector.logError(e) } @@ -110,17 +112,8 @@ internal class ExpressionsRuntimeProvider @Inject constructor( private fun createRuntimeFor(data: DivData, tag: DivDataTag): ExpressionsRuntime { val errorCollector = errorCollectors.getOrCreate(tag, data) - val variableController = VariableControllerImpl().apply { - data.variables?.forEach { divVariable: DivVariable -> - try { - declare(divVariable.toVariable()) - } catch (e: VariableDeclarationException) { - errorCollector.logError(e) - } - } - - addSource(divVariableController.variableSource) - } + val variableController = VariableControllerImpl() + variableController.addSource(divVariableController.variableSource) val functionProvider = FunctionProviderDecorator(GeneratedBuiltinFunctionProvider) val evaluationContext = EvaluationContext( @@ -155,6 +148,14 @@ internal class ExpressionsRuntimeProvider @Inject constructor( onCreateCallback = callback, ) + data.variables?.forEach { divVariable: DivVariable -> + try { + variableController.declare(divVariable.toVariable(expressionResolver)) + } catch (e: VariableDeclarationException) { + errorCollector.logError(e) + } + } + val triggersController = TriggersController( variableController, expressionResolver, diff --git a/client/android/div/src/main/java/com/yandex/div/core/expression/local/DivRuntimeVisitor.kt b/client/android/div/src/main/java/com/yandex/div/core/expression/local/DivRuntimeVisitor.kt index fbb98e7f8..e9fa24cfb 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/expression/local/DivRuntimeVisitor.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/expression/local/DivRuntimeVisitor.kt @@ -122,7 +122,7 @@ internal class DivRuntimeVisitor @Inject constructor( div: Div, divView: Div2View, path: String, - parentRuntime: ExpressionsRuntime? + parentRuntime: ExpressionsRuntime ): ExpressionsRuntime? { if (!div.needLocalRuntime) return parentRuntime diff --git a/client/android/div/src/main/java/com/yandex/div/core/expression/local/RuntimeStore.kt b/client/android/div/src/main/java/com/yandex/div/core/expression/local/RuntimeStore.kt index add9f0dc9..a27ba06c0 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/expression/local/RuntimeStore.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/expression/local/RuntimeStore.kt @@ -6,20 +6,18 @@ import com.yandex.div.core.ObserverList import com.yandex.div.core.expression.ExpressionResolverImpl import com.yandex.div.core.expression.ExpressionsRuntime import com.yandex.div.core.expression.triggers.TriggersController +import com.yandex.div.core.expression.variables.VariableController import com.yandex.div.core.expression.variables.VariableControllerImpl +import com.yandex.div.core.expression.variables.toVariable import com.yandex.div.core.util.toLocalFunctions -import com.yandex.div.core.util.toVariables -import com.yandex.div.core.view2.Div2View import com.yandex.div.core.view2.divs.DivActionBinder import com.yandex.div.core.view2.errors.ErrorCollector -import com.yandex.div.data.Variable import com.yandex.div.evaluable.EvaluationContext import com.yandex.div.evaluable.Evaluator import com.yandex.div.internal.Assert import com.yandex.div.json.expressions.ExpressionResolver import com.yandex.div2.Div import com.yandex.div2.DivBase -import com.yandex.div2.DivFunction import com.yandex.div2.DivTrigger private const val ERROR_UNKNOWN_RESOLVER = @@ -67,18 +65,33 @@ internal class RuntimeStore( } /** - * Returns runtime if it have been store before, otherwise creates new runtime using - * @param parentRuntime or @param parentResolver. - * - * NOTE: Always provide parentResolver or parentRuntime. - * Otherwise, if runtime wasn't created it will be created using rootRuntime + * Returns runtime if it have been stored before, otherwise creates new runtime using + * @param parentResolver */ internal fun getOrCreateRuntime( path: String, div: Div, - parentResolver: ExpressionResolver? = null, - parentRuntime: ExpressionsRuntime? = null, - ) = tree.getNode(path)?.runtime ?: getRuntimeOrCreateChild(path, div, null, parentResolver, parentRuntime) + parentResolver: ExpressionResolver, + ): ExpressionsRuntime? { + path.runtime?.let { return it } + + val parentRuntime = getRuntimeWithOrNull(parentResolver) + val runtime = parentRuntime ?: rootRuntime ?: run { + reportError(ERROR_ROOT_RUNTIME_NOT_SPECIFIED) + return null + } + + return getRuntimeOrCreateChild(path, div, runtime, parentRuntime) + } + + /** + * Returns runtime if it have been stored before, otherwise creates new runtime using + * @param parentRuntime + */ + internal fun getOrCreateRuntime(path: String, div: Div, parentRuntime: ExpressionsRuntime) = + path.runtime ?: getRuntimeOrCreateChild(path, div, parentRuntime, parentRuntime) + + private val String.runtime get() = tree.getNode(this)?.runtime internal fun getRuntimeWithOrNull(resolver: ExpressionResolver) = resolverToRuntime[resolver] @@ -103,7 +116,7 @@ internal class RuntimeStore( path: String, div: Div?, resolver: ExpressionResolver, - parentResolver: ExpressionResolver?, + parentResolver: ExpressionResolver, ): ExpressionsRuntime? { val runtimeForPath = tree.getNode(path)?.runtime if (resolver == runtimeForPath?.expressionResolver) return runtimeForPath @@ -114,7 +127,7 @@ internal class RuntimeStore( } runtimeForPath?.let { tree.removeRuntimeAndCleanup(divView, it, path) } - return getRuntimeOrCreateChild(path, div, existingRuntime, parentResolver) + return getRuntimeOrCreateChild(path, div, existingRuntime, getRuntimeWithOrNull(parentResolver)) } internal fun cleanup(divView: DivViewFacade) { @@ -137,15 +150,11 @@ internal class RuntimeStore( baseRuntime: ExpressionsRuntime, parentRuntime: ExpressionsRuntime?, path: String, - variables: List?, - variablesTriggers: List?, - functions: List?, + div: DivBase, ): ExpressionsRuntime { val localVariableController = VariableControllerImpl(baseRuntime.variableController) - if (!variables.isNullOrEmpty()) { - variables.forEach { localVariableController.declare(it) } - } + val functions = div.functions var functionProvider = baseRuntime.functionProvider if (!functions.isNullOrEmpty()) { functionProvider += functions.toLocalFunctions() @@ -168,50 +177,37 @@ internal class RuntimeStore( onCreateCallback = onCreateCallback, ) - val triggerController = if (variablesTriggers.isNullOrEmpty()) { - null - } else { - TriggersController( - localVariableController, - resolver, - evaluator, - errorCollector, - div2Logger, - divActionBinder - ).apply { - ensureTriggersSynced(variablesTriggers) - } + div.variables?.forEach { + localVariableController.declare(it.toVariable(resolver)) } + val triggerController = div.variableTriggers.toTriggersController(localVariableController, resolver, evaluator) + return ExpressionsRuntime(resolver, localVariableController, triggerController, functionProvider, this).also { putRuntime(it, path, parentRuntime) } } + private fun List?.toTriggersController( + variableController: VariableController, + resolver: ExpressionResolver, + evaluator: Evaluator, + ): TriggersController? { + if (isNullOrEmpty()) return null + val controller = + TriggersController(variableController, resolver, evaluator, errorCollector, div2Logger, divActionBinder) + controller.ensureTriggersSynced(this) + return controller + } + private fun getRuntimeOrCreateChild( path: String, div: Div?, - existingRuntime: ExpressionsRuntime? = null, - parentResolver: ExpressionResolver? = null, - parentRuntime: ExpressionsRuntime? = null, - ): ExpressionsRuntime? { - val runtime = existingRuntime - ?: parentRuntime - ?: parentResolver?.let { getRuntimeWithOrNull(it) } - ?: rootRuntime - ?: run { - reportError(ERROR_ROOT_RUNTIME_NOT_SPECIFIED) - return null - } - - val parentRuntime = parentRuntime ?: parentResolver?.let { getRuntimeWithOrNull(it) } - - val variables = div?.value()?.variables?.toVariables() - val variableTriggers = div?.value()?.variableTriggers - val functions = div?.value()?.functions - - if (needLocalRuntime(variables, variableTriggers, functions)) { - return createChildRuntime(runtime, parentRuntime, path, variables, variableTriggers, functions) + runtime: ExpressionsRuntime, + parentRuntime: ExpressionsRuntime?, + ): ExpressionsRuntime { + if (div != null && div.needLocalRuntime) { + return createChildRuntime(runtime, parentRuntime, path, div.value()) } tree.storeRuntime(runtime, parentRuntime, path) diff --git a/client/android/div/src/main/java/com/yandex/div/core/expression/local/utils.kt b/client/android/div/src/main/java/com/yandex/div/core/expression/local/utils.kt index 80e0ab60c..1f7e4b382 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/expression/local/utils.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/expression/local/utils.kt @@ -1,15 +1,6 @@ package com.yandex.div.core.expression.local -import com.yandex.div.data.Variable import com.yandex.div2.Div -import com.yandex.div2.DivFunction -import com.yandex.div2.DivTrigger internal val Div.needLocalRuntime get() = !value().run { variables.isNullOrEmpty() && variableTriggers.isNullOrEmpty() && functions.isNullOrEmpty() } - -internal fun needLocalRuntime( - variables: List?, - variableTriggers: List?, - functions: List? -) = !(variables.isNullOrEmpty() && variableTriggers.isNullOrEmpty() && functions.isNullOrEmpty()) diff --git a/client/android/div/src/main/java/com/yandex/div/core/expression/variables/DivVariablesParser.kt b/client/android/div/src/main/java/com/yandex/div/core/expression/variables/DivVariablesParser.kt index 4af045a72..b61016d18 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/expression/variables/DivVariablesParser.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/expression/variables/DivVariablesParser.kt @@ -6,6 +6,7 @@ import com.yandex.div.data.Variable import com.yandex.div.internal.parser.JsonParser import com.yandex.div.json.ParsingErrorLogger import com.yandex.div.json.ParsingException +import com.yandex.div.json.expressions.ExpressionResolver import com.yandex.div2.DivVariable import org.json.JSONArray import org.json.JSONObject @@ -16,7 +17,14 @@ object DivVariablesParser { * @param variablesArray json-array of variables for parsing. */ @Throws(ParsingException::class) - fun parse(variablesArray: JSONArray, logger: ParsingErrorLogger): List { + fun parse(variablesArray: JSONArray, logger: ParsingErrorLogger) = + parse(variablesArray, ExpressionResolver.EMPTY, logger) + + /** + * @param variablesArray json-array of variables for parsing. + */ + @Throws(ParsingException::class) + fun parse(variablesArray: JSONArray, resolver: ExpressionResolver, logger: ParsingErrorLogger): List { val env = DivParsingEnvironment(logger) val listValidator: (value: List) -> Boolean = { true } val key = "variables" @@ -25,49 +33,49 @@ object DivVariablesParser { } val divVariables: List = JsonParser.readList( jsonObject, key, DivVariable.CREATOR, listValidator, logger, env) - return divVariables.map { it.toVariable() } + return divVariables.map { it.toVariable(resolver) } } } -internal fun DivVariable.toVariable(): Variable { +internal fun DivVariable.toVariable(resolver: ExpressionResolver): Variable { return when (this) { is DivVariable.Bool -> { Variable.BooleanVariable( - this.value.name, this.value.value) + this.value.name, this.value.value.evaluate(resolver)) } is DivVariable.Integer -> { Variable.IntegerVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } is DivVariable.Number -> { Variable.DoubleVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } is DivVariable.Str -> { Variable.StringVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } is DivVariable.Color -> { Variable.ColorVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } is DivVariable.Url -> { Variable.UrlVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } is DivVariable.Dict -> { Variable.DictVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } is DivVariable.Array -> { Variable.ArrayVariable( - this.value.name, this.value.value + this.value.name, this.value.value.evaluate(resolver) ) } } diff --git a/client/android/div/src/main/java/com/yandex/div/core/util/DivUtil.kt b/client/android/div/src/main/java/com/yandex/div/core/util/DivUtil.kt index 20d76ff9a..be226bcb0 100644 --- a/client/android/div/src/main/java/com/yandex/div/core/util/DivUtil.kt +++ b/client/android/div/src/main/java/com/yandex/div/core/util/DivUtil.kt @@ -1,20 +1,15 @@ package com.yandex.div.core.util import android.util.DisplayMetrics -import android.view.View -import android.view.ViewGroup import android.view.animation.Interpolator import android.view.animation.LinearInterpolator -import androidx.core.view.children import com.yandex.div.core.animation.EaseInInterpolator import com.yandex.div.core.animation.EaseInOutInterpolator import com.yandex.div.core.animation.EaseInterpolator import com.yandex.div.core.animation.EaseOutInterpolator import com.yandex.div.core.animation.SpringInterpolator import com.yandex.div.core.animation.reversed -import com.yandex.div.core.expression.variables.toVariable import com.yandex.div.core.view2.divs.dpToPx -import com.yandex.div.data.Variable import com.yandex.div.internal.core.buildItems import com.yandex.div.internal.core.nonNullItems import com.yandex.div.json.expressions.ExpressionResolver @@ -38,7 +33,6 @@ import com.yandex.div2.DivState import com.yandex.div2.DivSwitch import com.yandex.div2.DivTabs import com.yandex.div2.DivText -import com.yandex.div2.DivVariable import com.yandex.div2.DivVideo import java.util.Collections.min @@ -113,13 +107,6 @@ internal val DivAnimationDirection.isAlternated: Boolean } } -internal fun requestHierarchyLayout(v : View) { - v.requestLayout() - if (v is ViewGroup) { - v.children.forEach { requestHierarchyLayout(it) } - } -} - internal fun DivBorder.getCornerRadii( widthPx: Float, heightPx: Float, @@ -211,9 +198,3 @@ internal val Div.isBranch: Boolean internal val Div.isLeaf: Boolean get() = !isBranch - -internal fun List.toVariables(): List { - return map { - it.toVariable() - } -} diff --git a/client/android/div/src/test/java/com/yandex/div/core/expression/local/RuntimeStoreTest.kt b/client/android/div/src/test/java/com/yandex/div/core/expression/local/RuntimeStoreTest.kt index 5e3de53a0..0002da131 100644 --- a/client/android/div/src/test/java/com/yandex/div/core/expression/local/RuntimeStoreTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/core/expression/local/RuntimeStoreTest.kt @@ -13,6 +13,8 @@ import com.yandex.div.data.Variable import com.yandex.div.evaluable.EvaluationContext import com.yandex.div.evaluable.Evaluator import com.yandex.div.internal.Assert +import com.yandex.div.json.expressions.Expression +import com.yandex.div.json.expressions.ExpressionResolver import com.yandex.div2.Div import com.yandex.div2.DivBase import com.yandex.div2.DivVariable @@ -82,7 +84,7 @@ class RuntimeStoreTest { Assert.assertNotNull(underTest.getRuntimeWithOrNull(newResolver)) Assert.assertEquals( runtimeFromCallback, - underTest.getOrCreateRuntime(path.fullPath, div) + underTest.getOrCreateRuntime(path.fullPath, div, newResolver) ) } @@ -91,7 +93,7 @@ class RuntimeStoreTest { setVariable() underTest.resolveRuntimeWith(divView, path.fullPath, div, resolver, resolver) - val runtime = underTest.getOrCreateRuntime(path.fullPath, div) + val runtime = underTest.getOrCreateRuntime(path.fullPath, div, resolver) Assert.assertNotNull(underTest.getRuntimeWithOrNull(resolver)) Assert.assertNotNull(runtime) Assert.assertEquals( @@ -105,7 +107,7 @@ class RuntimeStoreTest { val runtime = ExpressionsRuntime(resolver, mock(), null, functionProvider, underTest) underTest.putRuntime(runtime, PATH, rootRuntime) - Assert.assertEquals(runtime, underTest.getOrCreateRuntime(path.fullPath, div)) + Assert.assertEquals(runtime, underTest.getOrCreateRuntime(path.fullPath, div, resolver)) Assert.assertNotSame(runtime, rootRuntime) Assert.assertNotNull(underTest.getRuntimeWithOrNull(resolver)) } @@ -148,7 +150,7 @@ class RuntimeStoreTest { @Test fun `getOrCreateRuntime returns root runtime if parent runtime is not found`() { - val runtime = underTest.getOrCreateRuntime(path.fullPath, div) + val runtime = underTest.getOrCreateRuntime(path.fullPath, div, mock()) Assert.assertEquals(rootRuntime, runtime) Assert.assertNotNull(underTest.getRuntimeWithOrNull(resolver)) } @@ -165,7 +167,7 @@ class RuntimeStoreTest { ) Assert.assertEquals( runtimeFromCallback, - underTest.getOrCreateRuntime(path.fullPath, div) + underTest.getOrCreateRuntime(path.fullPath, div, resolver) ) } @@ -180,7 +182,7 @@ class RuntimeStoreTest { ) underTest.resolveRuntimeWith(divView, path.fullPath, div, resolver, resolver) - val newRuntime = underTest.getOrCreateRuntime(path.fullPath, div) + val newRuntime = underTest.getOrCreateRuntime(path.fullPath, div, resolver) Assert.assertNotNull(newRuntime) Assert.assertEquals( @@ -194,7 +196,7 @@ class RuntimeStoreTest { } private fun setVariable() { - val variables = listOf(DivVariable.Integer(IntegerVariable(CHILD_VARIABLE, 123))) + val variables = listOf(DivVariable.Integer(IntegerVariable(CHILD_VARIABLE, Expression.constant(123)))) whenever(divBase.variables).doReturn(variables) } } diff --git a/client/android/div/src/test/java/com/yandex/div/core/view2/local/LocalVariablesTest.kt b/client/android/div/src/test/java/com/yandex/div/core/view2/local/LocalVariablesTest.kt index db99e0241..44183a260 100644 --- a/client/android/div/src/test/java/com/yandex/div/core/view2/local/LocalVariablesTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/core/view2/local/LocalVariablesTest.kt @@ -125,8 +125,8 @@ class LocalVariablesTest { } private fun setVariable(name: String, value: String, path: String) { - val variableController = div2View.expressionsRuntime - ?.runtimeStore?.getOrCreateRuntime(path, div)?.variableController + val runtime = div2View.expressionsRuntime + val variableController = runtime?.runtimeStore?.getOrCreateRuntime(path, div, runtime)?.variableController val variable = variableController?.getMutableVariable(name) ?: return variable.set(value) } diff --git a/client/android/div/src/test/java/com/yandex/div/interactive/IntegrationMultiplatformTest.kt b/client/android/div/src/test/java/com/yandex/div/interactive/IntegrationMultiplatformTest.kt index fbd60b280..21a75a6e4 100644 --- a/client/android/div/src/test/java/com/yandex/div/interactive/IntegrationMultiplatformTest.kt +++ b/client/android/div/src/test/java/com/yandex/div/interactive/IntegrationMultiplatformTest.kt @@ -9,6 +9,7 @@ import com.yandex.div.core.expression.ExpressionTestCaseUtils import com.yandex.div.core.expression.ExpressionTestCaseUtils.VALUE_TYPE_ARRAY import com.yandex.div.core.expression.ExpressionTestCaseUtils.VALUE_TYPE_DICT import com.yandex.div.core.expression.ExpressionTestCaseUtils.createVariable +import com.yandex.div.core.expression.variables.wrapVariableValue import com.yandex.div.core.images.DivImageDownloadCallback import com.yandex.div.core.images.DivImageLoader import com.yandex.div.core.images.LoadReference @@ -56,8 +57,8 @@ class IntegrationMultiplatformTest(testCase: TestCaseOrError { - val expectedValue = it.value - val actualValue = variableController.get(it.name)?.getValue() + val expectedValue = it.value.wrapVariableValue() + val actualValue = divView.expressionsRuntime?.variableController?.get(it.name) if (it.type == VALUE_TYPE_DICT || it.type == VALUE_TYPE_ARRAY) { Assert.assertEquals(expectedValue.toString(), actualValue.toString()) } else { diff --git a/schema/div-variable.json b/schema/div-variable.json index 89efe617c..4d3d66b3d 100644 --- a/schema/div-variable.json +++ b/schema/div-variable.json @@ -16,7 +16,6 @@ ] }, "value": { - "supports_expressions": false, "type": "string", "$description": "translations.json#/div_variable_value" } @@ -42,7 +41,6 @@ ] }, "value": { - "supports_expressions": false, "long_type": true, "type": "integer", "$description": "translations.json#/div_variable_value" @@ -69,7 +67,6 @@ ] }, "value": { - "supports_expressions": false, "type": "number", "$description": "translations.json#/div_variable_value" } @@ -96,7 +93,6 @@ ] }, "value": { - "supports_expressions": false, "$ref": "common.json#/boolean_int", "$description": "translations.json#/div_variable_value" } @@ -116,14 +112,12 @@ "$description": "translations.json#/div_variable_name" }, "type": { - "supports_expressions": false, "type": "string", "enum": [ "color" ] }, "value": { - "supports_expressions": false, "$ref": "common.json#/color", "$description": "translations.json#/div_variable_value" } @@ -149,7 +143,6 @@ ] }, "value": { - "supports_expressions": false, "$ref": "common.json#/url", "$description": "translations.json#/div_variable_value" } @@ -175,7 +168,6 @@ ] }, "value": { - "supports_expressions": false, "type": "dict", "$description": "translations.json#/div_variable_value" } @@ -202,7 +194,6 @@ }, "value": { "type": "array", - "supports_expressions": false, "$description": "translations.json#/div_variable_value" } }, diff --git a/test_data/integration_test_data/decl_extressions_nesting.json b/test_data/integration_test_data/decl_extressions_nesting.json index e1c415cbd..e0136d988 100644 --- a/test_data/integration_test_data/decl_extressions_nesting.json +++ b/test_data/integration_test_data/decl_extressions_nesting.json @@ -68,6 +68,7 @@ } ], "platforms": [ + "android", "web" ] } diff --git a/test_data/integration_test_data/decl_extressions_simple.json b/test_data/integration_test_data/decl_extressions_simple.json index d569f2b45..3cd81d35c 100644 --- a/test_data/integration_test_data/decl_extressions_simple.json +++ b/test_data/integration_test_data/decl_extressions_simple.json @@ -34,6 +34,7 @@ } ], "platforms": [ + "android", "web" ] } diff --git a/test_data/integration_test_data/decl_extressions_transitive.json b/test_data/integration_test_data/decl_extressions_transitive.json index 95ebed62d..f83500af9 100644 --- a/test_data/integration_test_data/decl_extressions_transitive.json +++ b/test_data/integration_test_data/decl_extressions_transitive.json @@ -39,6 +39,7 @@ } ], "platforms": [ + "android", "web" ] }