Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81152 views
1
/**
2
* Copyright 2013-2014, Facebook, Inc.
3
* All rights reserved.
4
*
5
* This source code is licensed under the BSD-style license found in the
6
* LICENSE file in the root directory of this source tree. An additional grant
7
* of patent rights can be found in the PATENTS file in the same directory.
8
*
9
* @providesModule EventPluginRegistry
10
* @typechecks static-only
11
*/
12
13
"use strict";
14
15
var invariant = require('invariant');
16
17
/**
18
* Injectable ordering of event plugins.
19
*/
20
var EventPluginOrder = null;
21
22
/**
23
* Injectable mapping from names to event plugin modules.
24
*/
25
var namesToPlugins = {};
26
27
/**
28
* Recomputes the plugin list using the injected plugins and plugin ordering.
29
*
30
* @private
31
*/
32
function recomputePluginOrdering() {
33
if (!EventPluginOrder) {
34
// Wait until an `EventPluginOrder` is injected.
35
return;
36
}
37
for (var pluginName in namesToPlugins) {
38
var PluginModule = namesToPlugins[pluginName];
39
var pluginIndex = EventPluginOrder.indexOf(pluginName);
40
invariant(
41
pluginIndex > -1,
42
'EventPluginRegistry: Cannot inject event plugins that do not exist in ' +
43
'the plugin ordering, `%s`.',
44
pluginName
45
);
46
if (EventPluginRegistry.plugins[pluginIndex]) {
47
continue;
48
}
49
invariant(
50
PluginModule.extractEvents,
51
'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +
52
'method, but `%s` does not.',
53
pluginName
54
);
55
EventPluginRegistry.plugins[pluginIndex] = PluginModule;
56
var publishedEvents = PluginModule.eventTypes;
57
for (var eventName in publishedEvents) {
58
invariant(
59
publishEventForPlugin(
60
publishedEvents[eventName],
61
PluginModule,
62
eventName
63
),
64
'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.',
65
eventName,
66
pluginName
67
);
68
}
69
}
70
}
71
72
/**
73
* Publishes an event so that it can be dispatched by the supplied plugin.
74
*
75
* @param {object} dispatchConfig Dispatch configuration for the event.
76
* @param {object} PluginModule Plugin publishing the event.
77
* @return {boolean} True if the event was successfully published.
78
* @private
79
*/
80
function publishEventForPlugin(dispatchConfig, PluginModule, eventName) {
81
invariant(
82
!EventPluginRegistry.eventNameDispatchConfigs.hasOwnProperty(eventName),
83
'EventPluginHub: More than one plugin attempted to publish the same ' +
84
'event name, `%s`.',
85
eventName
86
);
87
EventPluginRegistry.eventNameDispatchConfigs[eventName] = dispatchConfig;
88
89
var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
90
if (phasedRegistrationNames) {
91
for (var phaseName in phasedRegistrationNames) {
92
if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
93
var phasedRegistrationName = phasedRegistrationNames[phaseName];
94
publishRegistrationName(
95
phasedRegistrationName,
96
PluginModule,
97
eventName
98
);
99
}
100
}
101
return true;
102
} else if (dispatchConfig.registrationName) {
103
publishRegistrationName(
104
dispatchConfig.registrationName,
105
PluginModule,
106
eventName
107
);
108
return true;
109
}
110
return false;
111
}
112
113
/**
114
* Publishes a registration name that is used to identify dispatched events and
115
* can be used with `EventPluginHub.putListener` to register listeners.
116
*
117
* @param {string} registrationName Registration name to add.
118
* @param {object} PluginModule Plugin publishing the event.
119
* @private
120
*/
121
function publishRegistrationName(registrationName, PluginModule, eventName) {
122
invariant(
123
!EventPluginRegistry.registrationNameModules[registrationName],
124
'EventPluginHub: More than one plugin attempted to publish the same ' +
125
'registration name, `%s`.',
126
registrationName
127
);
128
EventPluginRegistry.registrationNameModules[registrationName] = PluginModule;
129
EventPluginRegistry.registrationNameDependencies[registrationName] =
130
PluginModule.eventTypes[eventName].dependencies;
131
}
132
133
/**
134
* Registers plugins so that they can extract and dispatch events.
135
*
136
* @see {EventPluginHub}
137
*/
138
var EventPluginRegistry = {
139
140
/**
141
* Ordered list of injected plugins.
142
*/
143
plugins: [],
144
145
/**
146
* Mapping from event name to dispatch config
147
*/
148
eventNameDispatchConfigs: {},
149
150
/**
151
* Mapping from registration name to plugin module
152
*/
153
registrationNameModules: {},
154
155
/**
156
* Mapping from registration name to event name
157
*/
158
registrationNameDependencies: {},
159
160
/**
161
* Injects an ordering of plugins (by plugin name). This allows the ordering
162
* to be decoupled from injection of the actual plugins so that ordering is
163
* always deterministic regardless of packaging, on-the-fly injection, etc.
164
*
165
* @param {array} InjectedEventPluginOrder
166
* @internal
167
* @see {EventPluginHub.injection.injectEventPluginOrder}
168
*/
169
injectEventPluginOrder: function(InjectedEventPluginOrder) {
170
invariant(
171
!EventPluginOrder,
172
'EventPluginRegistry: Cannot inject event plugin ordering more than ' +
173
'once. You are likely trying to load more than one copy of React.'
174
);
175
// Clone the ordering so it cannot be dynamically mutated.
176
EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);
177
recomputePluginOrdering();
178
},
179
180
/**
181
* Injects plugins to be used by `EventPluginHub`. The plugin names must be
182
* in the ordering injected by `injectEventPluginOrder`.
183
*
184
* Plugins can be injected as part of page initialization or on-the-fly.
185
*
186
* @param {object} injectedNamesToPlugins Map from names to plugin modules.
187
* @internal
188
* @see {EventPluginHub.injection.injectEventPluginsByName}
189
*/
190
injectEventPluginsByName: function(injectedNamesToPlugins) {
191
var isOrderingDirty = false;
192
for (var pluginName in injectedNamesToPlugins) {
193
if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
194
continue;
195
}
196
var PluginModule = injectedNamesToPlugins[pluginName];
197
if (!namesToPlugins.hasOwnProperty(pluginName) ||
198
namesToPlugins[pluginName] !== PluginModule) {
199
invariant(
200
!namesToPlugins[pluginName],
201
'EventPluginRegistry: Cannot inject two different event plugins ' +
202
'using the same name, `%s`.',
203
pluginName
204
);
205
namesToPlugins[pluginName] = PluginModule;
206
isOrderingDirty = true;
207
}
208
}
209
if (isOrderingDirty) {
210
recomputePluginOrdering();
211
}
212
},
213
214
/**
215
* Looks up the plugin for the supplied event.
216
*
217
* @param {object} event A synthetic event.
218
* @return {?object} The plugin that created the supplied event.
219
* @internal
220
*/
221
getPluginModuleForEvent: function(event) {
222
var dispatchConfig = event.dispatchConfig;
223
if (dispatchConfig.registrationName) {
224
return EventPluginRegistry.registrationNameModules[
225
dispatchConfig.registrationName
226
] || null;
227
}
228
for (var phase in dispatchConfig.phasedRegistrationNames) {
229
if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {
230
continue;
231
}
232
var PluginModule = EventPluginRegistry.registrationNameModules[
233
dispatchConfig.phasedRegistrationNames[phase]
234
];
235
if (PluginModule) {
236
return PluginModule;
237
}
238
}
239
return null;
240
},
241
242
/**
243
* Exposed for unit testing.
244
* @private
245
*/
246
_resetEventPlugins: function() {
247
EventPluginOrder = null;
248
for (var pluginName in namesToPlugins) {
249
if (namesToPlugins.hasOwnProperty(pluginName)) {
250
delete namesToPlugins[pluginName];
251
}
252
}
253
EventPluginRegistry.plugins.length = 0;
254
255
var eventNameDispatchConfigs = EventPluginRegistry.eventNameDispatchConfigs;
256
for (var eventName in eventNameDispatchConfigs) {
257
if (eventNameDispatchConfigs.hasOwnProperty(eventName)) {
258
delete eventNameDispatchConfigs[eventName];
259
}
260
}
261
262
var registrationNameModules = EventPluginRegistry.registrationNameModules;
263
for (var registrationName in registrationNameModules) {
264
if (registrationNameModules.hasOwnProperty(registrationName)) {
265
delete registrationNameModules[registrationName];
266
}
267
}
268
}
269
270
};
271
272
module.exports = EventPluginRegistry;
273
274