Revert Strict boolean int parse

bcb3145d32482f6890155d6f0ea135cc46b821f6
This commit is contained in:
4eb0da
2024-03-13 17:11:44 +03:00
parent 510cbde3e4
commit d690ca47da
18 changed files with 64 additions and 139 deletions
-2
View File
@@ -12106,7 +12106,6 @@
"client/web/divkit/src/utils/nonNegativeModulo.ts":"divkit/public/client/web/divkit/src/utils/nonNegativeModulo.ts",
"client/web/divkit/src/utils/padLeft.ts":"divkit/public/client/web/divkit/src/utils/padLeft.ts",
"client/web/divkit/src/utils/prepareBase64.ts":"divkit/public/client/web/divkit/src/utils/prepareBase64.ts",
"client/web/divkit/src/utils/previewValue.ts":"divkit/public/client/web/divkit/src/utils/previewValue.ts",
"client/web/divkit/src/utils/propToString.ts":"divkit/public/client/web/divkit/src/utils/propToString.ts",
"client/web/divkit/src/utils/pxToEm.ts":"divkit/public/client/web/divkit/src/utils/pxToEm.ts",
"client/web/divkit/src/utils/shadow.ts":"divkit/public/client/web/divkit/src/utils/shadow.ts",
@@ -14253,7 +14252,6 @@
"client/web/divkit/tests/templates/string_enum_property.test.ts":"divkit/public/client/web/divkit/tests/templates/string_enum_property.test.ts",
"client/web/divkit/tests/utils/__snapshots__/applyTemplate.test.ts.snap":"divkit/public/client/web/divkit/tests/utils/__snapshots__/applyTemplate.test.ts.snap",
"client/web/divkit/tests/utils/__snapshots__/background.test.ts.snap":"divkit/public/client/web/divkit/tests/utils/__snapshots__/background.test.ts.snap",
"client/web/divkit/tests/utils/__snapshots__/correctBooleanInt.test.ts.snap":"divkit/public/client/web/divkit/tests/utils/__snapshots__/correctBooleanInt.test.ts.snap",
"client/web/divkit/tests/utils/__snapshots__/filters.test.ts.snap":"divkit/public/client/web/divkit/tests/utils/__snapshots__/filters.test.ts.snap",
"client/web/divkit/tests/utils/__snapshots__/simpleCheckInput.test.ts.snap":"divkit/public/client/web/divkit/tests/utils/__snapshots__/simpleCheckInput.test.ts.snap",
"client/web/divkit/tests/utils/applyTemplate.test.ts":"divkit/public/client/web/divkit/tests/utils/applyTemplate.test.ts",
+3 -4
View File
@@ -77,7 +77,6 @@
import { arrayInsert, arrayRemove } from '../actions/array';
import { copyToClipboard } from '../actions/copyToClipboard';
import { filterEnabledActions } from '../utils/filterEnabledActions';
import { correctBooleanInt } from '../utils/correctBooleanInt';
export let id: string;
export let json: Partial<DivJson> = {};
@@ -719,7 +718,7 @@
const actionUrl = action.url ? String(action.url) : '';
const actionTyped = action.typed;
if (!filterEnabledActions(action, logError)) {
if (!filterEnabledActions(action)) {
return;
}
@@ -903,7 +902,7 @@
return;
}
const filtered = actions.filter(action => filterEnabledActions(action, logError));
const filtered = actions.filter(filterEnabledActions);
for (let i = 0; i < filtered.length; ++i) {
let action = filtered[i];
@@ -1530,7 +1529,7 @@
if (
// if condition is truthy
correctBooleanInt(conditionResult.value, false, logError) &&
conditionResult.value &&
// and trigger mode matches
(mode === 'on_variable' || mode === 'on_condition' && prevConditionResult === false)
) {
@@ -54,7 +54,6 @@
import { ContentAlignmentHorizontalMapped, correctContentAlignmentHorizontal } from '../../utils/correctContentAlignmentHorizontal';
import { Truthy } from '../../utils/truthy';
import { assignIfDifferent } from '../../utils/assignIfDifferent';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
export let componentContext: ComponentContext<DivContainerData>;
export let layoutParams: LayoutParams | undefined = undefined;
@@ -138,7 +137,7 @@
}
const selectorVal = componentContext.getJsonWithVars(prototype.selector, additionalVars);
if (correctBooleanInt(selectorVal, true, componentContext.logError)) {
if (selectorVal) {
div = prototype.div;
break;
}
@@ -210,12 +209,9 @@
if (style) {
separator = {
show_at_start:
correctBooleanInt($jsonSeparator.show_at_start, false, componentContext.logError),
show_at_end:
correctBooleanInt($jsonSeparator.show_at_end, false, componentContext.logError),
show_between:
correctBooleanInt($jsonSeparator.show_between, true, componentContext.logError),
show_at_start: Boolean($jsonSeparator.show_at_start ?? false),
show_at_end: Boolean($jsonSeparator.show_at_end ?? false),
show_between: Boolean($jsonSeparator.show_between ?? true),
style,
margins: prepareMargins($jsonSeparator.margins)
};
@@ -237,12 +233,9 @@
if (style) {
lineSeparator = {
show_at_start:
correctBooleanInt($jsonLineSeparator.show_at_start, false, componentContext.logError),
show_at_end:
correctBooleanInt($jsonLineSeparator.show_at_end, false, componentContext.logError),
show_between:
correctBooleanInt($jsonLineSeparator.show_between, true, componentContext.logError),
show_at_start: Boolean($jsonLineSeparator.show_at_start ?? false),
show_at_end: Boolean($jsonLineSeparator.show_at_end ?? false),
show_between: Boolean($jsonLineSeparator.show_between ?? true),
style,
margins: prepareMargins($jsonLineSeparator.margins)
};
@@ -315,7 +308,7 @@
valign: contentVAlign,
halign: contentHAlign,
wrap,
overflow: correctBooleanInt($jsonClipToBounds, true, componentContext.logError) ? undefined : 'visible'
overflow: ($jsonClipToBounds === false || $jsonClipToBounds === 0) ? 'visible' : undefined
};
$: style = {
@@ -31,7 +31,6 @@
import { debounce } from '../../utils/debounce';
import { Truthy } from '../../utils/truthy';
import { nonNegativeModulo } from '../../utils/nonNegativeModulo';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
export let componentContext: ComponentContext<DivGalleryData>;
export let layoutParams: LayoutParams | undefined = undefined;
@@ -229,8 +228,6 @@
[gridTemplate]: joinTemplateSizes(templateSizes)
};
$: restrictScroll = correctBooleanInt($jsonRestrictParentScroll, false, componentContext.logError);
$: mods = {
orientation,
'scroll-snap': scrollSnap,
@@ -505,7 +502,7 @@
{replaceItems}
>
<div
class="{css.gallery__scroller} {restrictScroll ? rootCss['root_restrict-scroll'] : ''}"
class="{css.gallery__scroller} {$jsonRestrictParentScroll ? rootCss['root_restrict-scroll'] : ''}"
bind:this={scroller}
on:scroll={shouldCheckArrows ? updateArrowsVisibility : null}
style={makeStyle(scrollerStyle)}
@@ -32,7 +32,6 @@
import { correctTintMode } from '../../utils/correctTintMode';
import { getCssFilter } from '../../utils/filters';
import { prepareBase64 } from '../../utils/prepareBase64';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
export let componentContext: ComponentContext<DivImageData>;
export let layoutParams: LayoutParams | undefined = undefined;
@@ -146,8 +145,6 @@
$: alt = $jsonA11y?.description || '';
$: preload = correctBooleanInt($jsonPreloadRequired, false, componentContext.logError);
$: {
const newRatio = $jsonAspect?.ratio;
if (newRatio && isPositiveNumber(newRatio)) {
@@ -252,7 +249,7 @@
bind:this={img}
class={css.image__image}
src={state === STATE_ERROR ? FALLBACK_IMAGE : imageUrl}
loading={preload ? 'eager' : 'lazy'}
loading={$jsonPreloadRequired ? 'eager' : 'lazy'}
decoding="async"
style={makeStyle(style)}
{alt}
@@ -266,7 +263,7 @@
bind:this={img}
class={css.image__image}
src={state === STATE_ERROR ? FALLBACK_IMAGE : imageUrl}
loading={preload ? 'eager' : 'lazy'}
loading={$jsonPreloadRequired ? 'eager' : 'lazy'}
decoding="async"
style={makeStyle(style)}
{alt}
@@ -48,7 +48,6 @@
import { correctAlignmentHorizontal } from '../../utils/correctAlignmentHorizontal';
import { AlignmentVerticalMapped, correctAlignmentVertical } from '../../utils/correctAlignmentVertical';
import { calcSelectionOffset, setSelectionOffset } from '../../utils/contenteditable';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
export let componentContext: ComponentContext<DivInputData>;
export let layoutParams: LayoutParams | undefined = undefined;
@@ -214,8 +213,6 @@
$: isMultiline = keyboardType === 'multi_line_text'/* && isPositiveNumber($jsonVisibleMaxLines) && $jsonVisibleMaxLines > 1*/;
$: selectAllOnFocus = correctBooleanInt($jsonSelectAll, false, componentContext.logError);
$: {
if (isPositiveNumber($jsonVisibleMaxLines)) {
maxHeight = `calc(${$jsonVisibleMaxLines * (lineHeight || 1.25) * (fontSize / 10) + 'em'} + ${pxToEmWithUnits(correctNonNegativeNumber($jsonPaddings?.top, 0) + correctNonNegativeNumber($jsonPaddings?.bottom, 0))})`;
@@ -453,8 +450,8 @@
bind:innerText={contentEditableValue}
on:input={onInput}
on:paste={onPaste}
on:mousedown={selectAllOnFocus ? onMousedown : undefined}
on:click={selectAllOnFocus ? onClick : undefined}
on:mousedown={$jsonSelectAll ? onMousedown : undefined}
on:click={$jsonSelectAll ? onClick : undefined}
on:focus={focusHandler}
on:blur={blurHandler}
>
@@ -473,8 +470,8 @@
{placeholder}
{value}
on:input={onInput}
on:mousedown={selectAllOnFocus ? onMousedown : undefined}
on:click={selectAllOnFocus ? onClick : undefined}
on:mousedown={$jsonSelectAll ? onMousedown : undefined}
on:click={$jsonSelectAll ? onClick : undefined}
on:focus={focusHandler}
on:blur={blurHandler}
>
@@ -27,7 +27,6 @@
import { debounce } from '../../utils/debounce';
import { Truthy } from '../../utils/truthy';
import { nonNegativeModulo } from '../../utils/nonNegativeModulo';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
export let componentContext: ComponentContext<DivPagerData>;
export let layoutParams: LayoutParams | undefined = undefined;
@@ -141,8 +140,6 @@
}
}
$: restrictScroll = correctBooleanInt($jsonRestrictParentScroll, false, componentContext.logError);
$: style = {
'grid-gap': itemSpacing,
padding,
@@ -321,7 +318,7 @@
{replaceItems}
>
<div
class="{css.pager__items} {restrictScroll ? rootCss['root_restrict-scroll'] : ''}"
class="{css.pager__items} {$jsonRestrictParentScroll ? rootCss['root_restrict-scroll'] : ''}"
style={makeStyle(style)}
bind:this={pagerItemsWrapper}
on:scroll={onScrollDebounced}
@@ -37,8 +37,7 @@
import { correctNonNegativeNumber } from '../../utils/correctNonNegativeNumber';
import { edgeInsertsToCss } from '../../utils/edgeInsertsToCss';
import { filterEnabledActions } from '../../utils/filterEnabledActions';
import { nonNegativeModulo } from '../../utils/nonNegativeModulo';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
import { nonNegativeModulo } from '../../utils/nonNegativeModulo';
export let componentContext: ComponentContext<DivTabsData>;
export let layoutParams: LayoutParams | undefined = undefined;
@@ -327,7 +326,7 @@
}
$: {
if (correctBooleanInt($jsonSeparator, false, componentContext.logError)) {
if ($jsonSeparator) {
if ($jsonSeparatorColor) {
separatorBackground = correctColor($jsonSeparatorColor, 1, separatorBackground);
}
@@ -341,14 +340,14 @@
margin: separatorMargins
};
$: isSwipeEnabled = correctBooleanInt($jsonSwipeEnabled, true, componentContext.logError);
$: isSwipeEnabled = typeof $jsonSwipeEnabled === 'undefined' ?
true :
Boolean($jsonSwipeEnabled);
$: {
titlePadding = correctEdgeInsertsObject($jsonTitlePaddings ? $jsonTitlePaddings : undefined, titlePadding);
}
$: restrictScroll = correctBooleanInt($jsonRestrictParentScroll, false, componentContext.logError);
function updateItems(items: MaybeMissing<TabItem>[]): void {
if (hasError) {
return;
@@ -665,7 +664,7 @@
<!-- svelte-ignore a11y-interactive-supports-focus -->
<div
bind:this={tabsElem}
class="{css.tabs__list} {restrictScroll ? rootCss['root_restrict-scroll'] : ''}"
class="{css.tabs__list} {$jsonRestrictParentScroll ? rootCss['root_restrict-scroll'] : ''}"
role="tablist"
style:--divkit-tabs-title-padding={titlePadding ? edgeInsertsToCss(titlePadding, $direction) : ''}
style:--divkit-tabs-font-size={pxToEm(tabFontSize)}
@@ -696,8 +695,7 @@
})}
actions={
item.title_click_action && !componentContext.fakeElement ?
[item.title_click_action]
.filter(action => filterEnabledActions(action, componentContext.logError)) :
[item.title_click_action].filter(filterEnabledActions) :
[]
}
attrs={{
@@ -719,7 +717,7 @@
></div>
{/if}
<div
class="{css.tabs__panels} {restrictScroll ? rootCss['root_restrict-scroll'] : ''}"
class="{css.tabs__panels} {$jsonRestrictParentScroll ? rootCss['root_restrict-scroll'] : ''}"
bind:this={panelsWrapper}
on:touchstart={isSwipeEnabled ? onTouchStart : undefined}
on:touchmove={isSwipeEnabled ? onTouchMove : undefined}
@@ -141,7 +141,7 @@
newMaxLines = lines;
newLineClamp = lines;
newMultiline = true;
} else if (correctBooleanInt($jsonAutoEllipsize, false, componentContext.logError) && $jsonMaxLines !== 1) {
} else if ($jsonAutoEllipsize && $jsonMaxLines !== 1) {
newMultiline = true;
}
@@ -205,7 +205,7 @@
}
$: {
selectable = correctBooleanInt($jsonSelectable, selectable, componentContext.logError);
selectable = correctBooleanInt($jsonSelectable, selectable);
}
function updateRenderList(
@@ -326,7 +326,7 @@
newRenderList.push({
text: content.substring(prevIndex, index),
textStyles,
actions: item.type === 'rangeEnd' && item.range?.actions?.filter(action => filterEnabledActions(action, componentContext.logError)) || undefined
actions: item.type === 'rangeEnd' && item.range?.actions?.filter(filterEnabledActions) || undefined
});
}
@@ -362,7 +362,7 @@
height: imageHeight,
wrapperStyle,
svgFilterId,
preloadRequired: correctBooleanInt(item.image.preload_required, false, componentContext.logError)
preloadRequired: Boolean(item.image.preload_required)
}
});
}
@@ -71,7 +71,6 @@
import { isDeepEqual } from '../../utils/isDeepEqual';
import { filterEnabledActions } from '../../utils/filterEnabledActions';
import { isPrefersReducedMotion } from '../../utils/isPrefersReducedMotion';
import { correctBooleanInt } from '../../utils/correctBooleanInt';
import Actionable from './Actionable.svelte';
import OuterBackground from './OuterBackground.svelte';
@@ -263,7 +262,7 @@
let newBackgroundRadius = '';
if (border) {
if (correctBooleanInt(border.has_shadow, false, componentContext.logError)) {
if (border.has_shadow) {
const shadow = border.shadow;
if (shadow) {
newBorderStyle['box-shadow'] = shadowToCssBoxShadow(shadow);
@@ -359,8 +358,7 @@
) {
widthType = 'content';
if (
type === 'wrap_content' &&
correctBooleanInt($jsonWidth?.constrained, false, componentContext.logError) ||
type === 'wrap_content' && $jsonWidth?.constrained ||
(type === 'match_parent' || !type) && layoutParams.parentHorizontalWrapContent
) {
newWidthMods['width-constrained'] = true;
@@ -469,8 +467,7 @@
} else {
heightType = 'content';
if (
type === 'wrap_content' &&
correctBooleanInt($jsonHeight?.constrained, false, componentContext.logError) ||
type === 'wrap_content' && $jsonHeight?.constrained ||
type === 'match_parent' && layoutParams.parentVerticalWrapContent
) {
newHeightMods['height-constrained'] = true;
@@ -628,14 +625,12 @@
componentContext.logError(wrapError(new Error(`Cannot use action on component "${customActions}"`)));
}
const filterFn = (action: MaybeMissing<Action>) => filterEnabledActions(action, componentContext.logError);
// todo check parent actions with customActions
actions = newActions.filter(filterFn);
doubleTapActions = newDoubleTapActions.filter(filterFn);
longTapActions = newLongTapActions.filter(filterFn);
focusActions = newFocusActions.filter(filterFn);
blurActions = newBlurActions.filter(filterFn);
actions = newActions.filter(filterEnabledActions);
doubleTapActions = newDoubleTapActions.filter(filterEnabledActions);
longTapActions = newLongTapActions.filter(filterEnabledActions);
focusActions = newFocusActions.filter(filterEnabledActions);
blurActions = newBlurActions.filter(filterEnabledActions);
}
$: {
@@ -84,11 +84,11 @@
}
}
$: loop = correctBooleanInt($jsonRepeatable, loop, componentContext.logError);
$: loop = correctBooleanInt($jsonRepeatable, loop);
$: autoplay = correctBooleanInt($jsonAutostart, autoplay, componentContext.logError);
$: autoplay = correctBooleanInt($jsonAutostart, autoplay);
$: muted = correctBooleanInt($jsonMuted, muted, componentContext.logError);
$: muted = correctBooleanInt($jsonMuted, muted);
$: poster = typeof $jsonPreview === 'string' ? prepareBase64($jsonPreview) : poster;
@@ -5,7 +5,6 @@ import type { MaybeMissing } from '../expressions/json';
import type { ComponentContext } from '../types/componentContext';
import { getUrlSchema, isBuiltinSchema } from '../utils/url';
import { correctNonNegativeNumber } from '../utils/correctNonNegativeNumber';
import { correctBooleanInt } from '../utils/correctBooleanInt';
interface CalcedAction {
index: number | undefined;
@@ -31,6 +30,10 @@ function checkPercentage(isVisibility: boolean, val: number | undefined, default
return defaultVal;
}
function filterActions(it: CalcedAction): it is IndexedCalcedAction {
return it.is_enabled !== 0 && it.is_enabled !== false && it.index !== undefined;
}
export function visibilityAction(node: HTMLElement, {
visibilityActions,
disappearActions,
@@ -40,7 +43,7 @@ export function visibilityAction(node: HTMLElement, {
visibilityActions?: MaybeMissing<VisibilityAction>[];
disappearActions?: MaybeMissing<DisappearAction>[];
rootCtx: RootCtxValue;
componentContext: ComponentContext
componentContext: ComponentContext;
}) {
const visibilityStatus: {
type: 'visibility' | 'disappear';
@@ -107,12 +110,8 @@ export function visibilityAction(node: HTMLElement, {
const totalStore = derived(calcedList, values => values);
const filterActions = (it: CalcedAction): it is IndexedCalcedAction => {
return correctBooleanInt(it.is_enabled, true, componentContext.logError);
};
const unsubscribe = totalStore.subscribe(values => {
const filtered = values.filter<IndexedCalcedAction>(filterActions);
const filtered = values.filter(filterActions);
const map: Record<number, IndexedCalcedAction> = {};
filtered.forEach(it => {
@@ -1,16 +1,6 @@
import { previewValue } from './previewValue';
import { LogError, wrapError } from './wrapError';
export function correctBooleanInt(
val: unknown,
defaultVal: boolean,
logError: LogError
): boolean {
export function correctBooleanInt(val: number | boolean | undefined, defaultVal: boolean): boolean {
if (val === 1 || val === 0 || val === false || val === true) {
return Boolean(val);
}
if (val !== undefined) {
logError(wrapError(new Error(`Invalid value: ${previewValue(val)}. Expression<Bool> expected.`)));
}
return defaultVal;
}
@@ -1,11 +1,6 @@
import type { Action, DisappearAction, VisibilityAction } from '../../typings/common';
import type { MaybeMissing } from '../expressions/json';
import { correctBooleanInt } from './correctBooleanInt';
import { LogError } from './wrapError';
export function filterEnabledActions(
action: MaybeMissing<Action | VisibilityAction | DisappearAction>,
logError: LogError
): boolean {
return correctBooleanInt(action.is_enabled, true, logError);
export function filterEnabledActions(action: MaybeMissing<Action | VisibilityAction | DisappearAction>): boolean {
return action.is_enabled !== 0 && action.is_enabled !== false;
}
@@ -1,13 +0,0 @@
export function previewValue(value: unknown): string {
if (typeof value === 'object' && value) {
if (Array.isArray(value)) {
return 'array';
}
return 'object';
} else if (value === null) {
return 'null';
} else if (value === undefined) {
return 'undefined';
}
return JSON.stringify(value);
}
@@ -3,7 +3,6 @@ import type { MaskData } from './mask/baseInputMask';
import { FixedLengthInputMask } from './mask/fixedLengthInputMask';
import { MaybeMissing } from '../expressions/json';
import { FixedLengthInputMask as FixedLengthInputMaskType } from '../types/input';
import { correctBooleanInt } from './correctBooleanInt';
export function updateFixedMask(
mask: MaybeMissing<FixedLengthInputMaskType>,
@@ -16,7 +15,7 @@ export function updateFixedMask(
) {
const maskData: MaskData = {
pattern: mask.pattern,
alwaysVisible: correctBooleanInt(mask.always_visible, false, logError),
alwaysVisible: Boolean(mask.always_visible),
decoding: mask.pattern_elements.map(it => ({
key: it.key as string,
filter: it.regex && typeof it.regex === 'string' ? it.regex : undefined,
@@ -1,12 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`correctBooleanInt simple 1`] = `
[
[
[Error: Invalid value: 2. Expression<Bool> expected.],
],
[
[Error: Invalid value: 2. Expression<Bool> expected.],
],
]
`;
@@ -2,21 +2,17 @@ import { correctBooleanInt } from '../../src/utils/correctBooleanInt';
describe('correctBooleanInt', () => {
test('simple', () => {
const logError = jest.fn();
expect(correctBooleanInt(2, false, logError)).toBe(false);
expect(correctBooleanInt(2, true, logError)).toBe(true);
expect(correctBooleanInt(1, false, logError)).toBe(true);
expect(correctBooleanInt(1, true, logError)).toBe(true);
expect(correctBooleanInt(0, false, logError)).toBe(false);
expect(correctBooleanInt(0, true, logError)).toBe(false);
expect(correctBooleanInt(true, false, logError)).toBe(true);
expect(correctBooleanInt(true, true, logError)).toBe(true);
expect(correctBooleanInt(false, false, logError)).toBe(false);
expect(correctBooleanInt(false, true, logError)).toBe(false);
expect(correctBooleanInt(undefined, false, logError)).toBe(false);
expect(correctBooleanInt(undefined, true, logError)).toBe(true);
expect(logError.mock.calls).toMatchSnapshot();
expect(correctBooleanInt(2, false)).toBe(false);
expect(correctBooleanInt(2, true)).toBe(true);
expect(correctBooleanInt(1, false)).toBe(true);
expect(correctBooleanInt(1, true)).toBe(true);
expect(correctBooleanInt(0, false)).toBe(false);
expect(correctBooleanInt(0, true)).toBe(false);
expect(correctBooleanInt(true, false)).toBe(true);
expect(correctBooleanInt(true, true)).toBe(true);
expect(correctBooleanInt(false, false)).toBe(false);
expect(correctBooleanInt(false, true)).toBe(false);
expect(correctBooleanInt(undefined, false)).toBe(false);
expect(correctBooleanInt(undefined, true)).toBe(true);
});
});