import type {DispatchConfig} from './ReactSyntheticEventType';
import type {
AnyNativeEvent,
PluginName,
LegacyPluginModule,
} from './PluginModuleType';
import type {TopLevelType} from './TopLevelEventTypes';
type NamesToPlugins = {
[key: PluginName]: LegacyPluginModule<AnyNativeEvent>,
};
type EventPluginOrder = null | Array<PluginName>;
let eventPluginOrder: EventPluginOrder = null;
const namesToPlugins: NamesToPlugins = {};
function recomputePluginOrdering(): void {
if (!eventPluginOrder) {
return;
}
for (const pluginName in namesToPlugins) {
const pluginModule = namesToPlugins[pluginName];
const pluginIndex = eventPluginOrder.indexOf(pluginName);
if (pluginIndex <= -1) {
throw new Error(
'EventPluginRegistry: Cannot inject event plugins that do not exist in ' +
`the plugin ordering, \`${pluginName}\`.`,
);
}
if (plugins[pluginIndex]) {
continue;
}
if (!pluginModule.extractEvents) {
throw new Error(
'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +
`method, but \`${pluginName}\` does not.`,
);
}
plugins[pluginIndex] = pluginModule;
const publishedEvents = pluginModule.eventTypes;
for (const eventName in publishedEvents) {
if (
!publishEventForPlugin(
publishedEvents[eventName],
pluginModule,
eventName,
)
) {
throw new Error(
`EventPluginRegistry: Failed to publish event \`${eventName}\` for plugin \`${pluginName}\`.`,
);
}
}
}
}
function publishEventForPlugin(
dispatchConfig: DispatchConfig,
pluginModule: LegacyPluginModule<AnyNativeEvent>,
eventName: string,
): boolean {
if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {
throw new Error(
'EventPluginRegistry: More than one plugin attempted to publish the same ' +
`event name, \`${eventName}\`.`,
);
}
eventNameDispatchConfigs[eventName] = dispatchConfig;
const phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
if (phasedRegistrationNames) {
for (const phaseName in phasedRegistrationNames) {
if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
const phasedRegistrationName = phasedRegistrationNames[phaseName];
publishRegistrationName(
phasedRegistrationName,
pluginModule,
eventName,
);
}
}
return true;
} else if (dispatchConfig.registrationName) {
publishRegistrationName(
dispatchConfig.registrationName,
pluginModule,
eventName,
);
return true;
}
return false;
}
function publishRegistrationName(
registrationName: string,
pluginModule: LegacyPluginModule<AnyNativeEvent>,
eventName: string,
): void {
if (registrationNameModules[registrationName]) {
throw new Error(
'EventPluginRegistry: More than one plugin attempted to publish the same ' +
`registration name, \`${registrationName}\`.`,
);
}
registrationNameModules[registrationName] = pluginModule;
registrationNameDependencies[registrationName] =
pluginModule.eventTypes[eventName].dependencies;
if (__DEV__) {
const lowerCasedName = registrationName.toLowerCase();
possibleRegistrationNames[lowerCasedName] = registrationName;
if (registrationName === 'onDoubleClick') {
possibleRegistrationNames.ondblclick = registrationName;
}
}
}
export const plugins: Array<LegacyPluginModule<AnyNativeEvent>> = [];
export const eventNameDispatchConfigs: {
[eventName: string]: DispatchConfig,
} = {};
export const registrationNameModules: {
[registrationName: string]: LegacyPluginModule<AnyNativeEvent>,
} = {};
export const registrationNameDependencies: {
[registrationName: string]: Array<TopLevelType> | void,
} = {};
export const possibleRegistrationNames: {
[lowerCasedName: string]: string,
} = __DEV__ ? {} : (null: any);
export function injectEventPluginOrder(
injectedEventPluginOrder: EventPluginOrder,
): void {
if (eventPluginOrder) {
throw new Error(
'EventPluginRegistry: Cannot inject event plugin ordering more than ' +
'once. You are likely trying to load more than one copy of React.',
);
}
eventPluginOrder = Array.prototype.slice.call(injectedEventPluginOrder);
recomputePluginOrdering();
}
export function injectEventPluginsByName(
injectedNamesToPlugins: NamesToPlugins,
): void {
let isOrderingDirty = false;
for (const pluginName in injectedNamesToPlugins) {
if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
continue;
}
const pluginModule = injectedNamesToPlugins[pluginName];
if (
!namesToPlugins.hasOwnProperty(pluginName) ||
namesToPlugins[pluginName] !== pluginModule
) {
if (namesToPlugins[pluginName]) {
throw new Error(
'EventPluginRegistry: Cannot inject two different event plugins ' +
`using the same name, \`${pluginName}\`.`,
);
}
namesToPlugins[pluginName] = pluginModule;
isOrderingDirty = true;
}
}
if (isOrderingDirty) {
recomputePluginOrdering();
}
}