fix(amis-core): guard tpl formatDate and date filter against unparseable input#21414
Open
calebcgates wants to merge 1 commit into
Open
fix(amis-core): guard tpl formatDate and date filter against unparseable input#21414calebcgates wants to merge 1 commit into
calebcgates wants to merge 1 commit into
Conversation
|
👍 Thanks for this! Please review the labels and make any necessary changes. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
packages/amis-core/exposes two adjacent helpers that wrapmoment(input, inputFormat).format(format)without anisValid()check:formatDateintpl-lodash.ts:24— the lodash-template helper used as<%= formatDate(data.someField, 'YYYY-MM-DD') %>.dateinfilter.ts:148-149— registered as an amis-formula filter (reachable as${value | date}in formula expressions) AND re-exported in the lodash template engine asformatTimeStamp: filters.date(seetpl-lodash.ts:50).The unguarded
moment(input, inputFormat).format(format)shape produces two silent failure modes for end users of amis dashboards:"Invalid date"rendered to the page. Whenvalueis a string that doesn't matchinputFormat(typo in a schema, broken upstream API response, etc.),moment(...).format(...)silently returns the literal string"Invalid date"(or"无效日期"under zh-CN locale).null/undefinedvalue → today's date rendered to the page (onlyformatDate). This is the moment-undefined foot-gun:moment(undefined)is moment's documented sentinel for "now", and.isValid()returns true. So a typo'd field name (e.g.formatDate(data.creatAt)when the actual field isdata.createdAt) silently renders today's date — the user sees what looks like fresh data and never realizes the field is missing. (Thedatefilter defaultsinputFormat = 'X', which puts moment in strict-parse mode whereundefinedis invalid — so this mode only affectsformatDate. Bundled the fix anyway for consistency.)This PR adds the same guard pattern to both helpers:
Why
String(value)for unparseable input lets the calling template see the actual offending input instead of a hardcoded"Invalid date"string — easier to debug and to wrap in a downstream conditional if needed.packages/amis-core/src/utils/filter.ts:119-122(toDate: (input, inputFormat = '') => { const date = moment(input, inputFormat); return date.isValid() ? date.toDate() : undefined; }) —toDateis directly adjacent in the sameextendsFilters({ ... })block to the unguardeddatefilter.packages/amis-core/src/utils/date.ts:122,142(both usem.isValid()before formatting).tpl.test.ts. No public API change. No new dependencies. Existing tests for the formula-syntax happy-path (${value| date}against a valid Unix timestamp, intpl-builtin.test.ts:103-111) continue to pass.How
formatDateand thedatefilter both now short-circuit onvalue == null || value === ''(returns'') and on!moment(value, inputFormat).isValid()(returnsString(value)). The valid path is unchanged for both.packages/amis/__tests__/utils/tpl.test.tsexercising the helpers through the existingfilter()entry point — two coverformatDate(new guards + unchanged valid path), one coversformatTimeStamp(the lodash alias forfilters.date, with assertions across thenull/undefined/''/ unparseable / valid-Unix-timestamp axes).'not-a-real-date'no longer surfaces"Invalid date"in either helper's rendered output.Verification
npx jest packages/amis/__tests__/utils/tpl.test.ts— 4/4 passed (1 pre-existing + 3 new).npx jest packages/amis/__tests__/utils/tpl-builtin.test.ts— 46/46 passed, including the existing${value| date}formula-syntax happy-path test.npx jest packages/amis/__tests__/utils/filter.test.ts— 1/1 passed.npm test --workspace amis-core— 150/150 passed across 14 suites.npm test --workspace amis— 926/927 passed; the single failure (Renderer:inputDate with utcininputDate.test.tsx) is a pre-existing timezone-sensitive flake that reproduces onmaster(verified bygit stash+ rebuild + rerun). It computesmoment('2022-08-22 00:00:00').add(moment().utcOffset(), 'm').add(-1, 's').format(...), which is sensitive to the test runner's clock and timezone.NODE_OPTIONS='--max-old-space-size=8192' npm run typecheck— clean.amis-formula→amis-core→amis-ui→amis→amis-editor-core→amis-editor) — clean.