diff --git a/client/web/divkit/src/actions/array.ts b/client/web/divkit/src/actions/array.ts index fd227eec2..a7892a99c 100644 --- a/client/web/divkit/src/actions/array.ts +++ b/client/web/divkit/src/actions/array.ts @@ -1,6 +1,7 @@ import type { ActionArrayInsertValue, ActionArrayRemoveValue, ActionArraySetValue, WrappedError } from '../../typings/common'; import type { ArrayVariable, Variable } from '../../typings/variables'; import type { MaybeMissing } from '../expressions/json'; +import { convertTypedValue } from '../expressions/utils'; import type { ComponentContext } from '../types/componentContext'; import { wrapError } from '../utils/wrapError'; @@ -31,12 +32,19 @@ export function arrayInsert( length: list.length } })); + } else if (!value.type) { + logError(wrapError(new Error('Incorrect value type'), { + additional: { + name + } + })); } else { const newList = list.slice(); + const val = convertTypedValue(value); if (typeof index === 'number') { - newList.splice(index, 0, value.value); + newList.splice(index, 0, val); } else { - newList.push(value.value); + newList.push(val); } variableInstance.setValue(newList); } @@ -105,9 +113,15 @@ export function arraySet( length: list.length } })); + } else if (!value.type) { + logError(wrapError(new Error('Incorrect value type'), { + additional: { + name + } + })); } else { const newList = list.slice(); - newList[index] = value.value; + newList[index] = convertTypedValue(value); variableInstance.setValue(newList); } }); diff --git a/client/web/divkit/src/actions/dict.ts b/client/web/divkit/src/actions/dict.ts index b1f6ea316..7bfdd18be 100644 --- a/client/web/divkit/src/actions/dict.ts +++ b/client/web/divkit/src/actions/dict.ts @@ -1,6 +1,7 @@ import type { ActionDictSetValue, WrappedError } from '../../typings/common'; import type { Variable } from '../../typings/variables'; import type { MaybeMissing } from '../expressions/json'; +import { convertTypedValue } from '../expressions/utils'; import type { ComponentContext } from '../types/componentContext'; import { wrapError } from '../utils/wrapError'; @@ -30,6 +31,14 @@ export function dictSetValue( return; } + if (value && !value.type) { + logError(wrapError(new Error('Incorrect value type'), { + additional: { + name + } + })); + } + const variableInstance = componentContext?.getVariable(name) || variables.get(name); if (!variableInstance) { @@ -46,7 +55,7 @@ export function dictSetValue( const dict = variableInstance.getValue() as Record; const newDict = { ...dict }; if (value) { - newDict[key] = value.value; + newDict[key] = convertTypedValue(value); } else { delete newDict[key]; } diff --git a/client/web/divkit/src/actions/updateStructure.ts b/client/web/divkit/src/actions/updateStructure.ts index d3029309f..5ec502073 100644 --- a/client/web/divkit/src/actions/updateStructure.ts +++ b/client/web/divkit/src/actions/updateStructure.ts @@ -1,6 +1,7 @@ import type { ActionUpdateStructure, WrappedError } from '../../typings/common'; import type { Variable } from '../../typings/variables'; import type { MaybeMissing } from '../expressions/json'; +import { convertTypedValue } from '../expressions/utils'; import type { ComponentContext } from '../types/componentContext'; import { wrapError } from '../utils/wrapError'; @@ -120,7 +121,7 @@ export function updateStructure( } } - temp[parts[parts.length - 1]] = value.value; + temp[parts[parts.length - 1]] = convertTypedValue(value); variableInstance.setValue(newObj); } else { logError(wrapError(new Error('Action requires array or dictionary variable'), { diff --git a/client/web/divkit/src/expressions/utils.ts b/client/web/divkit/src/expressions/utils.ts index 9283149fe..89293fe0a 100644 --- a/client/web/divkit/src/expressions/utils.ts +++ b/client/web/divkit/src/expressions/utils.ts @@ -6,6 +6,8 @@ import { parseColor, type ParsedColor } from '../utils/correctColor'; import { padLeft } from '../utils/padLeft'; import { MAX_INT, MIN_INT, toBigInt } from './bigint'; import { BOOLEAN, NUMBER } from './const'; +import type { TypedValue } from '../../typings/common'; +import type { MaybeMissing } from './json'; export function valToInternal(val: EvalValue): EvalValue { if (val.type === 'url' || val.type === 'color') { @@ -179,7 +181,11 @@ const EVAL_TYPE_TO_JS_TYPE = { array: 'array', dict: 'object' }; -export function convertJsValueToDivKit(ctx: EvalContext, val: unknown, evalType: EvalTypesWithoutDatetime): EvalValue { +export function convertJsValueToDivKit( + ctx: EvalContext | undefined, + val: unknown, + evalType: EvalTypesWithoutDatetime +): EvalValue { const jsType = EVAL_TYPE_TO_JS_TYPE[evalType]; let type: string = typeof val; @@ -200,7 +206,9 @@ export function convertJsValueToDivKit(ctx: EvalContext, val: unknown, evalType: throw new Error(`Incorrect value type: expected ${typeToString(evalType)}, got ${typeToString(type)}.`); } if (jsType === 'number' && evalType === 'integer') { - checkIntegerOverflow(ctx, val as number); + if (ctx) { + checkIntegerOverflow(ctx, val as number); + } try { val = toBigInt(val as number); } catch (_err) { @@ -222,3 +230,19 @@ export function convertJsValueToDivKit(ctx: EvalContext, val: unknown, evalType: value: val } as EvalValue; } + +export function convertDivKitValueToJson(value: EvalValue) { + if (value.type === 'number' || value.type === 'integer') { + return Number(value.value); + } else if (value.type === 'boolean') { + return Boolean(value.value); + } + + return value.value; +} + +export function convertTypedValue(value: MaybeMissing) { + return convertDivKitValueToJson( + convertJsValueToDivKit(undefined, value.value, value.type as EvalTypesWithoutDatetime) + ); +} diff --git a/client/web/divkit/src/expressions/variable.ts b/client/web/divkit/src/expressions/variable.ts index efe6ebbc7..a49f9c594 100644 --- a/client/web/divkit/src/expressions/variable.ts +++ b/client/web/divkit/src/expressions/variable.ts @@ -3,7 +3,7 @@ import { writable } from 'svelte/store'; import type { EvalValue } from './eval'; import { parseColor } from '../utils/correctColor'; import { bigIntZero, toBigInt } from './bigint'; -import { checkUrl } from './utils'; +import { checkUrl, transformColorValue } from './utils'; import { BOOLEAN } from './const'; export type VariableType = 'string' | 'number' | 'integer' | 'boolean' | 'color' | 'url' | 'dict' | 'array'; @@ -161,8 +161,7 @@ export class ColorVariable extends Variable { throw new Error('Incorrect variable value'); } - // save input value, some expression tests rely on that - return value; + return transformColorValue(value); } protected fromString(val: string) { diff --git a/client/web/divkit/tests/expressions/expressions.test.ts b/client/web/divkit/tests/expressions/expressions.test.ts index c6977cc8b..981f24af8 100644 --- a/client/web/divkit/tests/expressions/expressions.test.ts +++ b/client/web/divkit/tests/expressions/expressions.test.ts @@ -6,7 +6,7 @@ import { } from 'vitest'; import { evalExpression, type EvalResult } from '../../src/expressions/eval'; -import { valToString } from '../../src/expressions/utils'; +import { transformColorValue, valToString } from '../../src/expressions/utils'; import { parse } from '../../src/expressions/expressions'; import { createVariable } from '../../src/expressions/variable'; @@ -34,6 +34,11 @@ function convertVals(val: EvalResult) { type: 'datetime', value: valToString(val, false) }; + } else if (val.type === 'color') { + return { + type: 'color', + value: transformColorValue(val.value) + }; } return val; diff --git a/test_data/integration_test_data/set_variable/set_color_variable.json b/test_data/integration_test_data/set_variable/set_color_variable.json index a47d77e3c..c43b59392 100644 --- a/test_data/integration_test_data/set_variable/set_color_variable.json +++ b/test_data/integration_test_data/set_variable/set_color_variable.json @@ -40,7 +40,8 @@ ], "platforms": [ "android", - "ios" + "ios", + "web" ] }, { @@ -92,7 +93,8 @@ ], "platforms": [ "android", - "ios" + "ios", + "web" ] } ] diff --git a/test_data/integration_test_data/structure_variable_changes/array_variable_mutation.json b/test_data/integration_test_data/structure_variable_changes/array_variable_mutation.json index 142efac79..bab9e9483 100644 --- a/test_data/integration_test_data/structure_variable_changes/array_variable_mutation.json +++ b/test_data/integration_test_data/structure_variable_changes/array_variable_mutation.json @@ -317,7 +317,8 @@ } ], "platforms": [ - "android" + "android", + "web" ] }, { @@ -662,7 +663,8 @@ } ], "platforms": [ - "android" + "android", + "web" ] }, { diff --git a/test_data/integration_test_data/structure_variable_changes/dict_set_value.json b/test_data/integration_test_data/structure_variable_changes/dict_set_value.json index bccc5ee8a..33eda6d30 100644 --- a/test_data/integration_test_data/structure_variable_changes/dict_set_value.json +++ b/test_data/integration_test_data/structure_variable_changes/dict_set_value.json @@ -317,7 +317,8 @@ } ], "platforms": [ - "android" + "android", + "web" ] }, { @@ -662,7 +663,8 @@ } ], "platforms": [ - "android" + "android", + "web" ] }, { diff --git a/test_data/integration_test_data/structure_variable_changes/update_structure.json b/test_data/integration_test_data/structure_variable_changes/update_structure.json index 97cedd24b..a550e54ac 100644 --- a/test_data/integration_test_data/structure_variable_changes/update_structure.json +++ b/test_data/integration_test_data/structure_variable_changes/update_structure.json @@ -1740,7 +1740,8 @@ } ], "platforms": [ - "android" + "android", + "web" ] }, { @@ -2017,7 +2018,8 @@ } ], "platforms": [ - "android" + "android", + "web" ] }, {