Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Core: Fix race-condition relating to addons.setConfig #23802

Merged
merged 3 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
29 changes: 2 additions & 27 deletions code/lib/manager-api/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import * as version from './modules/versions';
import * as whatsnew from './modules/whatsnew';

import * as globals from './modules/globals';
import type { ModuleFn } from './lib/types';

export * from './lib/shortcut';

Expand All @@ -76,14 +77,6 @@ export { ActiveTabs };

export const ManagerContext = createContext({ api: undefined, state: getInitialState({}) });

export type ModuleArgs = RouterData &
API_ProviderData<API> & {
mode?: 'production' | 'development';
state: State;
fullAPI: API;
store: Store;
};

export type State = layout.SubState &
stories.SubState &
refs.SubState &
Expand Down Expand Up @@ -152,28 +145,10 @@ export const combineParameters = (...parameterSets: Parameters[]) =>
return undefined;
});

interface ModuleWithInit<APIType = unknown, StateType = unknown> {
init: () => void | Promise<void>;
api: APIType;
state: StateType;
}

type ModuleWithoutInit<APIType = unknown, StateType = unknown> = Omit<
ModuleWithInit<APIType, StateType>,
'init'
>;

export type ModuleFn<APIType = unknown, StateType = unknown, HasInit = false> = (
m: ModuleArgs,
options?: any
) => HasInit extends true
? ModuleWithInit<APIType, StateType>
: ModuleWithoutInit<APIType, StateType>;

class ManagerProvider extends Component<ManagerProviderProps, State> {
api: API = {} as API;

modules: (ModuleWithInit | ModuleWithoutInit)[];
modules: ReturnType<ModuleFn>[];

static displayName = 'Manager';

Expand Down
22 changes: 22 additions & 0 deletions code/lib/manager-api/src/lib/types.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { API_ProviderData } from '@storybook/types';
import type { RouterData } from '@storybook/router';

import type { API, State } from '../index';
import type Store from '../store';

export type ModuleFn<APIType = unknown, StateType = unknown> = (
m: ModuleArgs,
options?: any
) => {
init?: () => void | Promise<void>;
api: APIType;
state: StateType;
};

export type ModuleArgs = RouterData &
API_ProviderData<API> & {
mode?: 'production' | 'development';
state: State;
fullAPI: API;
store: Store;
};
2 changes: 1 addition & 1 deletion code/lib/manager-api/src/modules/addons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type {
API_StateMerger,
} from '@storybook/types';
import { Addon_TypesEnum } from '@storybook/types';
import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';
import type { Options } from '../store';

export interface SubState {
Expand Down
3 changes: 2 additions & 1 deletion code/lib/manager-api/src/modules/channel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import { STORIES_COLLAPSE_ALL, STORIES_EXPAND_ALL } from '@storybook/core-events
import type { Listener } from '@storybook/channels';

import type { API_Provider } from '@storybook/types';
import type { API, ModuleFn } from '../index';
import type { API } from '../index';
import type { ModuleFn } from '../lib/types';

export interface SubAPI {
/**
Expand Down
25 changes: 14 additions & 11 deletions code/lib/manager-api/src/modules/globals.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { logger } from '@storybook/client-logger';
import { dequal as deepEqual } from 'dequal';
import type { SetGlobalsPayload, Globals, GlobalTypes } from '@storybook/types';

import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';

// eslint-disable-next-line import/no-cycle
import { getEventMetadata } from '../lib/events';
Expand Down Expand Up @@ -32,7 +32,7 @@ export interface SubAPI {
updateGlobals: (newGlobals: Globals) => void;
}

export const init: ModuleFn<SubAPI, SubState, true> = ({ store, fullAPI }) => {
export const init: ModuleFn<SubAPI, SubState> = ({ store, fullAPI, provider }) => {
const api: SubAPI = {
getGlobals() {
return store.getState().globals;
Expand All @@ -42,7 +42,7 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({ store, fullAPI }) => {
},
updateGlobals(newGlobals) {
// Only emit the message to the local ref
fullAPI.emit(UPDATE_GLOBALS, {
provider.channel.emit(UPDATE_GLOBALS, {
globals: newGlobals,
options: {
target: 'storybook-preview-iframe',
Expand All @@ -62,8 +62,9 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({ store, fullAPI }) => {
}
};

const initModule = () => {
fullAPI.on(GLOBALS_UPDATED, function handleGlobalsUpdated({ globals }: { globals: Globals }) {
provider.channel.on(
GLOBALS_UPDATED,
function handleGlobalsUpdated({ globals }: { globals: Globals }) {
const { ref } = getEventMetadata(this, fullAPI);

if (!ref) {
Expand All @@ -73,10 +74,13 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({ store, fullAPI }) => {
'received a GLOBALS_UPDATED from a non-local ref. This is not currently supported.'
);
}
});
}
);

// Emitted by the preview on initialization
fullAPI.on(SET_GLOBALS, function handleSetStories({ globals, globalTypes }: SetGlobalsPayload) {
// Emitted by the preview on initialization
provider.channel.on(
SET_GLOBALS,
function handleSetStories({ globals, globalTypes }: SetGlobalsPayload) {
const { ref } = getEventMetadata(this, fullAPI);
const currentGlobals = store.getState()?.globals;

Expand All @@ -93,12 +97,11 @@ export const init: ModuleFn<SubAPI, SubState, true> = ({ store, fullAPI }) => {
) {
api.updateGlobals(currentGlobals);
}
});
};
}
);

return {
api,
state,
init: initModule,
};
};
5 changes: 3 additions & 2 deletions code/lib/manager-api/src/modules/layout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import type { ThemeVars } from '@storybook/theming';

import type { API_Layout, API_PanelPositions, API_UI } from '@storybook/types';
import merge from '../lib/merge';
import type { State, ModuleFn } from '../index';
import type { State } from '../index';
import type { ModuleFn } from '../lib/types';

const { document } = global;

Expand Down Expand Up @@ -284,7 +285,7 @@ export const init: ModuleFn = ({ store, provider, singleStory, fullAPI }) => {
state: merge(api.getInitialOptions(), persisted),
init: () => {
api.setOptions(merge(api.getInitialOptions(), persisted));
fullAPI.on(SET_CONFIG, () => {
provider.channel.on(SET_CONFIG, () => {
api.setOptions(merge(api.getInitialOptions(), persisted));
});
},
Expand Down
2 changes: 1 addition & 1 deletion code/lib/manager-api/src/modules/notifications.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { API_Notification } from '@storybook/types';
import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';

export interface SubState {
notifications: API_Notification[];
Expand Down
4 changes: 2 additions & 2 deletions code/lib/manager-api/src/modules/provider.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import type { API_IframeRenderer } from '@storybook/types';
import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';

export interface SubAPI {
renderPreview?: API_IframeRenderer;
}

export const init: ModuleFn<SubAPI, {}, true> = ({ provider, fullAPI }) => {
export const init: ModuleFn<SubAPI, {}> = ({ provider, fullAPI }) => {
return {
api: provider.renderPreview ? { renderPreview: provider.renderPreview } : {},
state: {},
Expand Down
4 changes: 2 additions & 2 deletions code/lib/manager-api/src/modules/refs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
transformStoryIndexToStoriesHash,
} from '../lib/stories';

import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';

const { location, fetch } = global;

Expand Down Expand Up @@ -154,7 +154,7 @@ const map = (
return input;
};

export const init: ModuleFn<SubAPI, SubState, void> = (
export const init: ModuleFn<SubAPI, SubState> = (
{ store, provider, singleStory, docsOptions = {} },
{ runCheck = true } = {}
) => {
Expand Down
7 changes: 5 additions & 2 deletions code/lib/manager-api/src/modules/settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { API_Settings, StoryId } from '@storybook/types';
import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';

export interface SubAPI {
storeSelection: () => void;
Expand Down Expand Up @@ -78,5 +78,8 @@ export const init: ModuleFn<SubAPI, SubState> = ({ store, navigate, fullAPI }) =
},
};

return { state: { settings: { lastTrackedStoryId: null } }, api };
return {
state: { settings: { lastTrackedStoryId: null } },
api,
};
};
10 changes: 5 additions & 5 deletions code/lib/manager-api/src/modules/shortcuts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { global } from '@storybook/global';
import { FORCE_REMOUNT, PREVIEW_KEYDOWN } from '@storybook/core-events';

import type { ModuleFn } from '../index';
import type { ModuleFn } from '../lib/types';

import type { KeyboardEventLike } from '../lib/shortcut';
import { shortcutMatchesShortcut, eventToShortcut } from '../lib/shortcut';
Expand Down Expand Up @@ -152,7 +152,7 @@ function focusInInput(event: KeyboardEvent) {
return /input|textarea/i.test(target.tagName) || target.getAttribute('contenteditable') !== null;
}

export const init: ModuleFn = ({ store, fullAPI }) => {
export const init: ModuleFn = ({ store, fullAPI, provider }) => {
const api: SubAPI = {
// Getting and setting shortcuts
getShortcutKeys(): API_Shortcuts {
Expand Down Expand Up @@ -397,13 +397,13 @@ export const init: ModuleFn = ({ store, fullAPI }) => {
// Listen for keydown events in the manager
document.addEventListener('keydown', (event: KeyboardEvent) => {
if (!focusInInput(event)) {
fullAPI.handleKeydownEvent(event);
api.handleKeydownEvent(event);
}
});

// Also listen to keydown events sent over the channel
fullAPI.on(PREVIEW_KEYDOWN, (data: { event: KeyboardEventLike }) => {
fullAPI.handleKeydownEvent(data.event);
provider.channel.on(PREVIEW_KEYDOWN, (data: { event: KeyboardEventLike }) => {
api.handleKeydownEvent(data.event);
});
};

Expand Down