From e3ed5b09577a13d0bf085abad1fe46e2eb6f4502 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 25 Nov 2020 15:36:17 +0800 Subject: [PATCH 1/3] Core: Detect arg inference for cyclic args and warn --- .../stories/addon-controls.stories.tsx | 8 +++++ lib/client-api/src/inferArgTypes.ts | 36 ++++++++++++++----- 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/examples/official-storybook/stories/addon-controls.stories.tsx b/examples/official-storybook/stories/addon-controls.stories.tsx index b6537a686ad4..f93c44db9a49 100644 --- a/examples/official-storybook/stories/addon-controls.stories.tsx +++ b/examples/official-storybook/stories/addon-controls.stories.tsx @@ -33,3 +33,11 @@ CustomControls.argTypes = { }; export const NoArgs = () => ; + +const hasCycle: any = {}; +hasCycle.cycle = hasCycle; + +export const CyclicArgs = Template.bind({}); +CyclicArgs.args = { + hasCycle, +}; diff --git a/lib/client-api/src/inferArgTypes.ts b/lib/client-api/src/inferArgTypes.ts index 6524b7eac1ad..da479d1a9e6d 100644 --- a/lib/client-api/src/inferArgTypes.ts +++ b/lib/client-api/src/inferArgTypes.ts @@ -1,8 +1,10 @@ import mapValues from 'lodash/mapValues'; +import dedent from 'ts-dedent'; +import { logger } from '@storybook/client-logger'; import { SBType, ArgTypesEnhancer } from './types'; import { combineParameters } from './parameters'; -const inferType = (value?: any): SBType => { +const inferType = (value: any, name: string, visited: Set): SBType => { const type = typeof value; switch (type) { case 'boolean': @@ -10,24 +12,40 @@ const inferType = (value?: any): SBType => { case 'number': case 'function': return { name: type }; + case 'symbol': + return { name: 'other', value: 'symbol' }; default: break; } - if (Array.isArray(value)) { - const childType: SBType = - value.length > 0 ? inferType(value[0]) : { name: 'other', value: 'unknown' }; - return { name: 'array', value: childType }; - } if (value) { - const fieldTypes = mapValues(value, (field) => inferType(field)); + if (visited.has(value)) { + logger.warn(dedent` + We've detected a cycle in arg '${name}'. Arg values should be JSON-serializable (ish, functions are ok). + + More info: https://storybook.js.org/docs/react/essentials/controls#fully-custom-args + `); + return { name: 'other', value: 'cyclic object' }; + } + visited.add(value); + if (Array.isArray(value)) { + const childType: SBType = + value.length > 0 + ? inferType(value[0], name, new Set(visited)) + : { name: 'other', value: 'unknown' }; + return { name: 'array', value: childType }; + } + const fieldTypes = mapValues(value, (field) => inferType(field, name, new Set(visited))); return { name: 'object', value: fieldTypes }; } return { name: 'object', value: {} }; }; export const inferArgTypes: ArgTypesEnhancer = (context) => { - const { argTypes: userArgTypes = {}, args = {} } = context.parameters; + const { id, parameters } = context; + const { argTypes: userArgTypes = {}, args = {} } = parameters; if (!args) return userArgTypes; - const argTypes = mapValues(args, (arg) => ({ type: inferType(arg) })); + const argTypes = mapValues(args, (arg, key) => ({ + type: inferType(arg, `${id}.${key}`, new Set()), + })); return combineParameters(argTypes, userArgTypes); }; From 41e4750b1f9c95c534d6c2ebfbfc7a1d07cda409 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 25 Nov 2020 15:51:53 +0800 Subject: [PATCH 2/3] Update inferArgTypes.ts --- lib/client-api/src/inferArgTypes.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/client-api/src/inferArgTypes.ts b/lib/client-api/src/inferArgTypes.ts index da479d1a9e6d..c3b1642760c6 100644 --- a/lib/client-api/src/inferArgTypes.ts +++ b/lib/client-api/src/inferArgTypes.ts @@ -20,7 +20,7 @@ const inferType = (value: any, name: string, visited: Set): SBType => { if (value) { if (visited.has(value)) { logger.warn(dedent` - We've detected a cycle in arg '${name}'. Arg values should be JSON-serializable (ish, functions are ok). + We've detected a cycle in arg '${name}'. Args should be JSON-serializable (-ish, functions are ok). More info: https://storybook.js.org/docs/react/essentials/controls#fully-custom-args `); From 01fd93e6794d0e238ab64a381de925a28b1ca900 Mon Sep 17 00:00:00 2001 From: Michael Shilman Date: Wed, 25 Nov 2020 22:20:58 +0800 Subject: [PATCH 3/3] Disable chromatic for broken story --- examples/official-storybook/stories/addon-controls.stories.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/official-storybook/stories/addon-controls.stories.tsx b/examples/official-storybook/stories/addon-controls.stories.tsx index f93c44db9a49..81a01ef70ab5 100644 --- a/examples/official-storybook/stories/addon-controls.stories.tsx +++ b/examples/official-storybook/stories/addon-controls.stories.tsx @@ -41,3 +41,6 @@ export const CyclicArgs = Template.bind({}); CyclicArgs.args = { hasCycle, }; +CyclicArgs.parameters = { + chromatic: { disable: true }, +};