@samitouri / QOS-React-2 / commits / e1535fbd71
Fork 0

The library for web and native user interfaces.

Create `EventPluginRegistry`

The `EventPluginHub` module was getting huge and scary. This pulls out all of the logic required to inject plugins and publish their event registration names into a new `EventPluginRegistry` module. Functionally, nothing should have changed. I added many error checks to cover edge cases that we were not yet running into, but they are all in `EventPluginRegistry` and unit tested.

CommitSyncScript committed Jun 13, 2013 at 16:33 UTC e1535fbd71d8c89c82cd9d9073c1ee97ee6a3b00
11 files changed +667 -347
src/core/ReactEventEmitter.js
+11 -20
@@ -31,26 +31,17 @@ var isEventSupported = require('isEventSupported');
31 /**
32 * Summary of `ReactEventEmitter` event handling:
33 *
34 - * - We trap low level 'top-level' events.
34 + * - Top-level delegation is used to trap native browser events. We normalize
35 + * and de-duplicate events to account for browser quirks.
36 *
36 - * - We dedupe cross-browser event names into these 'top-level types' (e.g. so
37 - * that `wheel`, `mousewheel`, and `DOMMouseScroll` fire one event).
37 + * - Forward these native events (with the associated top-level type used to
38 + * trap it) to `EventPluginHub`, which in turn will ask plugins if they want
39 + * to extract any synthetic events.
40 *
39 - * - At this point we have native browser events with the top-level type that
40 - * was used to catch it at the top-level.
41 + * - The `EventPluginHub` will then process each event by annotating them with
42 + * "dispatches", a sequence of listeners and IDs that care about that event.
43 *
42 - * - We continuously stream these native events (and their respective top-level
43 - * types) to the event plugin system `EventPluginHub` and ask the plugin
44 - * system if it was able to extract `AbstractEvent` objects. `AbstractEvent`
45 - * objects are the events that applications actually deal with - they are not
46 - * native browser events but cross-browser wrappers.
47 - *
48 - * - When returning the `AbstractEvent` objects, `EventPluginHub` will make
49 - * sure each abstract event is annotated with "dispatches", which are the
50 - * sequence of listeners (and IDs) that care about the event.
51 - *
52 - * - These `AbstractEvent` objects are fed back into the event plugin system,
53 - * which in turn executes these dispatches.
44 + * - The `EventPluginHub` then dispatches the events.
45 *
46 * Overview of React and the event system:
47 *
@@ -321,7 +312,7 @@ var ReactEventEmitter = {
312 topLevelTarget,
313 topLevelTargetID,
314 nativeEvent) {
324 - var abstractEvents = EventPluginHub.extractAbstractEvents(
315 + var events = EventPluginHub.extractEvents(
316 topLevelType,
317 topLevelTarget,
318 topLevelTargetID,
@@ -329,8 +320,8 @@ var ReactEventEmitter = {
320 );
321
322 // Event queue being processed in the same cycle allows `preventDefault`.
332 - EventPluginHub.enqueueAbstractEvents(abstractEvents);
333 - EventPluginHub.processAbstractEventQueue();
323 + EventPluginHub.enqueueEvents(events);
324 + EventPluginHub.processEventQueue();
325 },
326
327 registrationNames: EventPluginHub.registrationNames,
src/event/EventPluginHub.js
+139 -267
@@ -18,309 +18,181 @@
18
19 "use strict";
20
21 -var AbstractEvent = require('AbstractEvent');
21 var CallbackRegistry = require('CallbackRegistry');
22 +var EventPluginRegistry = require('EventPluginRegistry');
23 var EventPluginUtils = require('EventPluginUtils');
24 var EventPropagators = require('EventPropagators');
25 var ExecutionEnvironment = require('ExecutionEnvironment');
26
27 var accumulate = require('accumulate');
28 var forEachAccumulated = require('forEachAccumulated');
29 -var keyMirror = require('keyMirror');
30 -var merge = require('merge');
31 -var throwIf = require('throwIf');
32 -
33 -var deleteListener = CallbackRegistry.deleteListener;
34 -
35 -var ERRORS = keyMirror({
36 - DOUBLE_REGISTER: null,
37 - DOUBLE_ENQUEUE: null,
38 - DEPENDENCY_ERROR: null
39 -});
40 -
41 -if (__DEV__) {
42 - ERRORS.DOUBLE_REGISTER =
43 - 'You\'ve included an event plugin that extracts an ' +
44 - 'event type with the exact same or identity as an event that ' +
45 - 'had previously been injected - or, one of the registration names ' +
46 - 'used by an plugin has already been used.';
47 - ERRORS.DOUBLE_ENQUEUE =
48 - 'During the processing of events, more events were enqueued. This ' +
49 - 'is strange and should not happen. Please report immediately. ';
50 - ERRORS.DEPENDENCY_ERROR =
51 - 'You have either attempted to load an event plugin that has no ' +
52 - 'entry in EventPluginOrder, or have attempted to extract events ' +
53 - 'when some critical dependencies have not yet been injected.';
54 -}
29 +var invariant = require('invariant');
30
31 +/**
32 + * Internal queue of events that have accumulated their dispatches and are
33 + * waiting to have their dispatches executed.
34 + */
35 +var eventQueue = null;
36
37 /**
58 - * EventPluginHub: To see a diagram and explanation of the overall architecture
59 - * of the plugin hub system, @see ReactEvents.js
38 + * Dispatches an event and releases it back into the pool, unless persistent.
39 + *
40 + * @param {?object} event Synthetic event to be dispatched.
41 + * @private
42 */
43 +var executeDispatchesAndRelease = function(event) {
44 + if (event) {
45 + var executeDispatch = EventPluginUtils.executeDispatch;
46 + // Plugins can provide custom behavior when dispatching events.
47 + var PluginModule = EventPluginRegistry.getPluginModuleForEvent(event);
48 + if (PluginModule && PluginModule.executeDispatch) {
49 + executeDispatch = PluginModule.executeDispatch;
50 + }
51 + EventPluginUtils.executeDispatchesInOrder(event, executeDispatch);
52 +
53 + if (!event.isPersistent()) {
54 + event.constructor.release(event);
55 + }
56 + }
57 +};
58
59 /**
63 - * Injected Dependencies:
60 + * This is a unified interface for event plugins to be installed and configured.
61 + *
62 + * Event plugins can implement the following properties:
63 + *
64 + * `extractEvents` {function(string, DOMEventTarget, string, object): *}
65 + * Required. When a top-level event is fired, this method is expected to
66 + * extract synthetic events that will in turn be queued and dispatched.
67 + *
68 + * `abstractEventTypes` {object}
69 + * Optional, plugins that fire events must publish a mapping of registration
70 + * names that are used to register listeners. Values of this mapping must
71 + * be objects that contain `registrationName` or `phasedRegistrationNames`.
72 + *
73 + * `executeDispatch` {function(object, function, string)}
74 + * Optional, allows plugins to override how an event gets dispatched. By
75 + * default, the listener is simply invoked.
76 + *
77 + * Each plugin that is injected into `EventsPluginHub` is immediately operable.
78 + *
79 + * @public
80 */
65 -var injection = {
66 - /**
67 - * [required] Dependency of `EventPropagators`.
68 - */
69 - injectInstanceHandle: function(InjectedInstanceHandle) {
70 - EventPropagators.injection.injectInstanceHandle(InjectedInstanceHandle);
71 - },
81 +var EventPluginHub = {
82
83 /**
74 - * `EventPluginOrder`: [optional] Provides deterministic ordering of
75 - * `EventPlugin`s. Ordering decoupled from the injection of actual
76 - * plugins so that there is always a deterministic and permanent ordering
77 - * regardless of the plugins that happen to become packaged, or applications
78 - * that happen to inject on-the-fly event plugins.
84 + * Methods for injecting dependencies.
85 */
80 - EventPluginOrder: null,
81 - injectEventPluginOrder: function(InjectedEventPluginOrder) {
82 - injection.EventPluginOrder = InjectedEventPluginOrder;
83 - injection._recomputePluginsList();
84 - },
86 + injection: {
87
86 - /**
87 - * `EventPlugins`: [optional][lazy-loadable] Plugins that must be listed in
88 - * the `EventPluginOrder` injected dependency. The list of plugins may grow as
89 - * custom plugins are injected into the system at page as part of the
90 - * initialization process, or even after the initialization process (on-the-
91 - * fly). Plugins injected into the hub have an opportunity to infer abstract
92 - * events when top level events are streamed through the `EventPluginHub`.
93 - */
94 - plugins: [],
95 - injectEventPluginsByName: function(pluginsByName) {
96 - injection.pluginsByName = merge(injection.pluginsByName, pluginsByName);
97 - injection._recomputePluginsList();
98 - },
88 + /**
89 + * @param {object} InjectedInstanceHandle
90 + * @public
91 + */
92 + injectInstanceHandle: EventPropagators.injection.injectInstanceHandle,
93
100 - /**
101 - * A reference of all injected plugins by their name. Both plugins and
102 - * `EventPluginOrder` can be injected on-the-fly. Any time either dependency
103 - * is (re)injected, the resulting list of plugins in correct order is
104 - * recomputed.
105 - */
106 - pluginsByName: {},
107 - _recomputePluginsList: function() {
108 - var injectPluginByName = function(name, PluginModule) {
109 - var pluginIndex = injection.EventPluginOrder.indexOf(name);
110 - throwIf(pluginIndex === -1, ERRORS.DEPENDENCY_ERROR + name);
111 - if (!injection.plugins[pluginIndex]) {
112 - injection.plugins[pluginIndex] = PluginModule;
113 - for (var eventName in PluginModule.abstractEventTypes) {
114 - var eventType = PluginModule.abstractEventTypes[eventName];
115 - recordAllRegistrationNames(eventType, PluginModule);
116 - }
117 - }
118 - };
119 - if (injection.EventPluginOrder) { // Else, do when plugin order injected
120 - var injectedPluginsByName = injection.pluginsByName;
121 - for (var name in injectedPluginsByName) {
122 - injectPluginByName(name, injectedPluginsByName[name]);
123 - }
124 - }
125 - }
126 -};
94 + /**
95 + * @param {array} InjectedEventPluginOrder
96 + * @public
97 + */
98 + injectEventPluginOrder: EventPluginRegistry.injectEventPluginOrder,
99
100 + /**
101 + * @param {object} injectedNamesToPlugins Map from names to plugin modules.
102 + */
103 + injectEventPluginsByName: EventPluginRegistry.injectEventPluginsByName
104
129 -/**
130 - * `renderedTarget`: We'll refer to the concept of a "rendered target". Any
131 - * framework code that uses the `EventPluginHub` will stream events to the
132 - * `EventPluginHub`. In order for registered plugins to make sense of the native
133 - * events, it helps to allow plugins to not only have access to the native
134 - * `Event` object but also the notion of a "rendered target", which is the
135 - * conceptual target `Element` of the `Event` that the framework (user of
136 - * `EventPluginHub`) deems as being the "important" target.
137 - */
138 -/**
139 - * Keeps track of all valid "registration names" (`onClick` etc). We expose
140 - * these structures to other modules, who will always see updates that we apply
141 - * to these structures. They should never have a desire to mutate these.
142 - */
143 -var registrationNames = {};
105 + },
106
145 -/**
146 - * This prevents the need for clients to call `Object.keys(registrationNames)`
147 - * every time they want to loop through the possible registration names.
148 - */
149 -var registrationNamesArr = [];
107 + registrationNames: EventPluginRegistry.registrationNames,
108
151 -/**
152 - * Internal queue of events that have accumulated their dispatches and are
153 - * waiting to have their dispatches executed.
154 - */
155 -var abstractEventQueue = [];
109 + putListener: CallbackRegistry.putListener,
110
157 -/**
158 - * Records all the registration names that the event plugin makes available
159 - * to the general event system. These are things like
160 - * `onClick`/`onClickCapture`.
161 - */
162 -function recordAllRegistrationNames(eventType, PluginModule) {
163 - var phaseName;
164 - var phasedRegistrationNames = eventType.phasedRegistrationNames;
165 - if (phasedRegistrationNames) {
166 - for (phaseName in phasedRegistrationNames) {
167 - if (!phasedRegistrationNames.hasOwnProperty(phaseName)) {
168 - continue;
169 - }
170 - if (__DEV__) {
171 - throwIf(
172 - registrationNames[phasedRegistrationNames[phaseName]],
173 - ERRORS.DOUBLE_REGISTER
174 - );
175 - }
176 - registrationNames[phasedRegistrationNames[phaseName]] = PluginModule;
177 - registrationNamesArr.push(phasedRegistrationNames[phaseName]);
178 - }
179 - } else if (eventType.registrationName) {
180 - if (__DEV__) {
181 - throwIf(
182 - registrationNames[eventType.registrationName],
183 - ERRORS.DOUBLE_REGISTER
184 - );
185 - }
186 - registrationNames[eventType.registrationName] = PluginModule;
187 - registrationNamesArr.push(eventType.registrationName);
188 - }
189 -}
111 + getListener: CallbackRegistry.getListener,
112
191 -/**
192 - * A hacky way to reverse engineer which event plugin module created an
193 - * AbstractEvent.
194 - * @param {AbstractEvent} abstractEvent to look at
195 - */
196 -function getPluginModuleForAbstractEvent(abstractEvent) {
197 - var reactEventType = abstractEvent.reactEventType;
198 - if (reactEventType.registrationName) {
199 - return registrationNames[reactEventType.registrationName];
200 - } else {
201 - for (var phase in reactEventType.phasedRegistrationNames) {
202 - if (!reactEventType.phasedRegistrationNames.hasOwnProperty(phase)) {
203 - continue;
204 - }
205 - var PluginModule = registrationNames[
206 - reactEventType.phasedRegistrationNames[phase]
207 - ];
208 - if (PluginModule) {
209 - return PluginModule;
210 - }
211 - }
212 - }
213 - return null;
214 -}
113 + deleteListener: CallbackRegistry.deleteListener,
114
216 -var deleteAllListeners = function(domID) {
217 - var ii;
218 - for (ii = 0; ii < registrationNamesArr.length; ii++) {
219 - deleteListener(domID, registrationNamesArr[ii]);
220 - }
221 -};
115 + /**
116 + * Deletes all listeners for the DOM element with the supplied ID.
117 + *
118 + * @param {string} domID ID of a DOM element.
119 + */
120 + deleteAllListeners: function(domID) {
121 + var registrationNamesKeys = EventPluginRegistry.registrationNamesKeys;
122 + for (var ii = 0; ii < registrationNamesKeys.length; ii++) {
123 + CallbackRegistry.deleteListener(domID, registrationNamesKeys[ii]);
124 + }
125 + },
126
223 -/**
224 - * Accepts the stream of top level native events, and gives every registered
225 - * plugin an opportunity to extract `AbstractEvent`s with annotated dispatches.
226 - *
227 - * @param {string} topLevelType Record from `EventConstants`.
228 - * @param {DOMEventTarget} topLevelTarget The listening component root node.
229 - * @param {string} topLevelTargetID ID of `topLevelTarget`.
230 - * @param {object} nativeEvent Native browser event.
231 - * @return {*} An accumulation of `AbstractEvent`s.
232 - */
233 -var extractAbstractEvents = function(
234 - topLevelType,
235 - topLevelTarget,
236 - topLevelTargetID,
237 - nativeEvent) {
238 - var abstractEvents;
239 - var plugins = injection.plugins;
240 - for (var i = 0, l = plugins.length; i < l; i++) {
241 - // Not every plugin in the ordering may be loaded at runtime.
242 - var possiblePlugin = plugins[i];
243 - if (possiblePlugin) {
244 - var extractedAbstractEvents = possiblePlugin.extractAbstractEvents(
245 - topLevelType,
246 - topLevelTarget,
247 - topLevelTargetID,
248 - nativeEvent
249 - );
250 - if (extractedAbstractEvents) {
251 - abstractEvents = accumulate(abstractEvents, extractedAbstractEvents);
127 + /**
128 + * Allows registered plugins an opportunity to extract events from top-level
129 + * native browser events.
130 + *
131 + * @param {string} topLevelType Record from `EventConstants`.
132 + * @param {DOMEventTarget} topLevelTarget The listening component root node.
133 + * @param {string} topLevelTargetID ID of `topLevelTarget`.
134 + * @param {object} nativeEvent Native browser event.
135 + * @return {*} An accumulation of synthetic events.
136 + * @internal
137 + */
138 + extractEvents: function(
139 + topLevelType,
140 + topLevelTarget,
141 + topLevelTargetID,
142 + nativeEvent) {
143 + var events;
144 + var plugins = EventPluginRegistry.plugins;
145 + for (var i = 0, l = plugins.length; i < l; i++) {
146 + // Not every plugin in the ordering may be loaded at runtime.
147 + var possiblePlugin = plugins[i];
148 + if (possiblePlugin) {
149 + var extractedEvents = possiblePlugin.extractEvents(
150 + topLevelType,
151 + topLevelTarget,
152 + topLevelTargetID,
153 + nativeEvent
154 + );
155 + if (extractedEvents) {
156 + events = accumulate(events, extractedEvents);
157 + }
158 }
159 }
254 - }
255 - return abstractEvents;
256 -};
257 -
258 -var enqueueAbstractEvents = function(abstractEvents) {
259 - if (abstractEvents) {
260 - abstractEventQueue = accumulate(abstractEventQueue, abstractEvents);
261 - }
262 -};
160 + return events;
161 + },
162
264 -/**
265 - * Executes a single abstract event dispatch. Returns a value, but this return
266 - * value doesn't make much sense when executing dispatches for a list of a
267 - * events. However, if a plugin executes a single dispatch, mostly bypassing
268 - * `EventPluginHub`, it can execute dispatches directly and assign special
269 - * meaning to the return value. So this will return the result of executing the
270 - * dispatch, though for most use cases, it gets dropped.
271 - */
272 -var executeDispatchesAndRelease = function(abstractEvent) {
273 - if (abstractEvent) {
274 - var PluginModule = getPluginModuleForAbstractEvent(abstractEvent);
275 - var pluginExecuteDispatch = PluginModule && PluginModule.executeDispatch;
276 - EventPluginUtils.executeDispatchesInOrder(
277 - abstractEvent,
278 - pluginExecuteDispatch || EventPluginUtils.executeDispatch
279 - );
280 - if (!abstractEvent.isPersistent()) {
281 - AbstractEvent.release(abstractEvent);
163 + /**
164 + * Enqueues a synthetic event that should be dispatched when
165 + * `processEventQueue` is invoked.
166 + *
167 + * @param {*} events An accumulation of synthetic events.
168 + * @internal
169 + */
170 + enqueueEvents: function(events) {
171 + if (events) {
172 + eventQueue = accumulate(eventQueue, events);
173 }
283 - }
284 -};
174 + },
175
286 -/**
287 - * Sets `abstractEventQueue` to null before processing it, so that we can tell
288 - * if in the process of processing events, more were enqueued. We throw if we
289 - * find that any were enqueued though this use case could be supported in the
290 - * future. For now, throwing an error as it's something we don't expect to
291 - * occur.
292 - */
293 -var processAbstractEventQueue = function() {
294 - var processingAbstractEventQueue = abstractEventQueue;
295 - abstractEventQueue = null;
296 - forEachAccumulated(processingAbstractEventQueue, executeDispatchesAndRelease);
297 - if (__DEV__) {
298 - throwIf(abstractEventQueue, ERRORS.DOUBLE_ENQUEUE);
176 + /**
177 + * Dispatches all synthetic events on the event queue.
178 + *
179 + * @internal
180 + */
181 + processEventQueue: function() {
182 + // Set `eventQueue` to null before processing it so that we can tell if more
183 + // events get enqueued while processing.
184 + var processingEventQueue = eventQueue;
185 + eventQueue = null;
186 + forEachAccumulated(processingEventQueue, executeDispatchesAndRelease);
187 + invariant(
188 + !eventQueue,
189 + 'processEventQueue(): Additional events were enqueued while processing ' +
190 + 'an event queue. Support for this has not yet been implemented.'
191 + );
192 }
300 -};
193
302 -/**
303 - * Provides a unified interface for an arbitrary and dynamic set of event
304 - * plugins. Loosely, a hub, where several "event plugins" may act as a single
305 - * event plugin behind the facade of `EventPluginHub`. Each event plugin injects
306 - * themselves into the HUB, and will immediately become operable upon injection.
307 - *
308 - * @constructor EventPluginHub
309 - */
310 -var EventPluginHub = {
311 - registrationNames: registrationNames,
312 - registrationNamesArr: registrationNamesArr,
313 - putListener: CallbackRegistry.putListener,
314 - getListener: CallbackRegistry.getListener,
315 - deleteListener: CallbackRegistry.deleteListener,
316 - deleteAllListeners: deleteAllListeners,
317 - extractAbstractEvents: extractAbstractEvents,
318 - enqueueAbstractEvents: enqueueAbstractEvents,
319 - processAbstractEventQueue: processAbstractEventQueue,
320 - injection: injection
194 };
195
323 -
196 if (ExecutionEnvironment.canUseDOM) {
197 window.EventPluginHub = EventPluginHub;
198 }
src/event/EventPluginRegistry.js new
+207
@@ -0,0 +1,207 @@
1 +/**
2 + * @providesModule EventPluginRegistry
3 + * @typechecks
4 + */
5 +
6 +var invariant = require('invariant');
7 +
8 +/**
9 + * Injectable ordering of event plugins.
10 + */
11 +var EventPluginOrder = null;
12 +
13 +/**
14 + * Injectable mapping from names to event plugin modules.
15 + */
16 +var namesToPlugins = {};
17 +
18 +/**
19 + * Recomputes the plugin list using the injected plugins and plugin ordering.
20 + *
21 + * @private
22 + */
23 +function recomputePluginOrdering() {
24 + if (!EventPluginOrder) {
25 + // Wait until an `EventPluginOrder` is injected.
26 + return;
27 + }
28 + for (var pluginName in namesToPlugins) {
29 + var PluginModule = namesToPlugins[pluginName];
30 + var pluginIndex = EventPluginOrder.indexOf(pluginName);
31 + invariant(
32 + pluginIndex > -1,
33 + 'EventPluginRegistry: Cannot inject event plugins that do not exist in ' +
34 + 'the plugin ordering, `%s`.',
35 + pluginName
36 + );
37 + if (EventPluginRegistry.plugins[pluginIndex]) {
38 + continue;
39 + }
40 + invariant(
41 + PluginModule.extractEvents,
42 + 'EventPluginRegistry: Event plugins must implement an `extractEvents` ' +
43 + 'method, but `%s` does not.',
44 + pluginName
45 + );
46 + EventPluginRegistry.plugins[pluginIndex] = PluginModule;
47 + var publishedEvents = PluginModule.abstractEventTypes;
48 + for (var eventName in publishedEvents) {
49 + invariant(
50 + publishEventForPlugin(publishedEvents[eventName], PluginModule),
51 + 'EventPluginRegistry: Failed to publish event `%s` for plugin `%s`.',
52 + eventName,
53 + pluginName
54 + );
55 + }
56 + }
57 +}
58 +
59 +/**
60 + * Publishes an event so that it can be dispatched by the supplied plugin.
61 + *
62 + * @param {object} dispatchConfig Dispatch configuration for the event.
63 + * @param {object} PluginModule Plugin publishing the event.
64 + * @return {boolean} True if the event was successfully published.
65 + * @private
66 + */
67 +function publishEventForPlugin(dispatchConfig, PluginModule) {
68 + var phasedRegistrationNames = dispatchConfig.phasedRegistrationNames;
69 + if (phasedRegistrationNames) {
70 + for (var phaseName in phasedRegistrationNames) {
71 + if (phasedRegistrationNames.hasOwnProperty(phaseName)) {
72 + var phasedRegistrationName = phasedRegistrationNames[phaseName];
73 + publishRegistrationName(phasedRegistrationName, PluginModule);
74 + }
75 + }
76 + return true;
77 + } else if (dispatchConfig.registrationName) {
78 + publishRegistrationName(dispatchConfig.registrationName, PluginModule);
79 + return true;
80 + }
81 + return false;
82 +}
83 +
84 +/**
85 + * Publishes a registration name that is used to identify dispatched events and
86 + * can be used with `EventPluginHub.putListener` to register listeners.
87 + *
88 + * @param {string} registrationName Registration name to add.
89 + * @param {object} PluginModule Plugin publishing the event.
90 + * @private
91 + */
92 +function publishRegistrationName(registrationName, PluginModule) {
93 + invariant(
94 + !EventPluginRegistry.registrationNames[registrationName],
95 + 'EventPluginHub: More than one plugin attempted to publish the same ' +
96 + 'registration name, `%s`.',
97 + registrationName
98 + );
99 + EventPluginRegistry.registrationNames[registrationName] = PluginModule;
100 + EventPluginRegistry.registrationNamesKeys.push(registrationName);
101 +}
102 +
103 +/**
104 + * Registers plugins so that they can extract and dispatch events.
105 + *
106 + * @see {EventPluginHub}
107 + */
108 +var EventPluginRegistry = {
109 +
110 + /**
111 + * Ordered list of injected plugins.
112 + */
113 + plugins: [],
114 +
115 + /**
116 + * Mapping from registration names to plugin modules.
117 + */
118 + registrationNames: {},
119 +
120 + /**
121 + * The keys of `registrationNames`.
122 + */
123 + registrationNamesKeys: [],
124 +
125 + /**
126 + * Injects an ordering of plugins (by plugin name). This allows the ordering
127 + * to be decoupled from injection of the actual plugins so that ordering is
128 + * always deterministic regardless of packaging, on-the-fly injection, etc.
129 + *
130 + * @param {array} InjectedEventPluginOrder
131 + * @internal
132 + * @see {EventPluginHub.injection.injectEventPluginOrder}
133 + */
134 + injectEventPluginOrder: function(InjectedEventPluginOrder) {
135 + invariant(
136 + !EventPluginOrder,
137 + 'EventPluginRegistry: Cannot inject event plugin ordering more than once.'
138 + );
139 + // Clone the ordering so it cannot be dynamically mutated.
140 + EventPluginOrder = Array.prototype.slice.call(InjectedEventPluginOrder);
141 + recomputePluginOrdering();
142 + },
143 +
144 + /**
145 + * Injects plugins to be used by `EventPluginHub`. The plugin names must be
146 + * in the ordering injected by `injectEventPluginOrder`.
147 + *
148 + * Plugins can be injected as part of page initialization or on-the-fly.
149 + *
150 + * @param {object} injectedNamesToPlugins Map from names to plugin modules.
151 + * @internal
152 + * @see {EventPluginHub.injection.injectEventPluginsByName}
153 + */
154 + injectEventPluginsByName: function(injectedNamesToPlugins) {
155 + var isOrderingDirty = false;
156 + for (var pluginName in injectedNamesToPlugins) {
157 + if (!injectedNamesToPlugins.hasOwnProperty(pluginName)) {
158 + continue;
159 + }
160 + var PluginModule = injectedNamesToPlugins[pluginName];
161 + if (namesToPlugins[pluginName] !== PluginModule) {
162 + invariant(
163 + !namesToPlugins[pluginName],
164 + 'EventPluginRegistry: Cannot inject two different event plugins ' +
165 + 'using the same name, `%s`.',
166 + pluginName
167 + );
168 + namesToPlugins[pluginName] = PluginModule;
169 + isOrderingDirty = true;
170 + }
171 + }
172 + if (isOrderingDirty) {
173 + recomputePluginOrdering();
174 + }
175 + },
176 +
177 + /**
178 + * Looks up the plugin for the supplied event.
179 + *
180 + * @param {object} event A synthetic event.
181 + * @return {?object} The plugin that created the supplied event.
182 + * @internal
183 + */
184 + getPluginModuleForEvent: function(event) {
185 + var dispatchConfig = event.reactEventType;
186 + if (dispatchConfig.registrationName) {
187 + return EventPluginRegistry.registrationNames[
188 + dispatchConfig.registrationName
189 + ] || null;
190 + }
191 + for (var phase in dispatchConfig.phasedRegistrationNames) {
192 + if (!dispatchConfig.phasedRegistrationNames.hasOwnProperty(phase)) {
193 + continue;
194 + }
195 + var PluginModule = EventPluginRegistry.registrationNames[
196 + dispatchConfig.phasedRegistrationNames[phase]
197 + ];
198 + if (PluginModule) {
199 + return PluginModule;
200 + }
201 + }
202 + return null;
203 + }
204 +
205 +};
206 +
207 +module.exports = EventPluginRegistry;
src/event/__tests__/EventPluginRegistry-test.js new
+258
@@ -0,0 +1,258 @@
1 +/**
2 + * @emails react-core
3 + */
4 +
5 +"use strict";
6 +
7 +var merge = require('merge');
8 +
9 +describe('EventPluginRegistry', function() {
10 + var EventPluginRegistry;
11 + var createPlugin;
12 +
13 + beforeEach(function() {
14 + require('mock-modules').dumpCache();
15 + EventPluginRegistry = require('EventPluginRegistry');
16 +
17 + createPlugin = function(properties) {
18 + return merge({extractEvents: function() {}}, properties);
19 + };
20 + });
21 +
22 + it('should be able to inject ordering before plugins', function() {
23 + var OnePlugin = createPlugin();
24 + var TwoPlugin = createPlugin();
25 + var ThreePlugin = createPlugin();
26 +
27 + EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);
28 + EventPluginRegistry.injectEventPluginsByName({
29 + one: OnePlugin,
30 + two: TwoPlugin
31 + });
32 + EventPluginRegistry.injectEventPluginsByName({
33 + three: ThreePlugin
34 + });
35 +
36 + expect(EventPluginRegistry.plugins.length).toBe(3);
37 + expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);
38 + expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);
39 + expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);
40 + });
41 +
42 + it('should be able to inject plugins before and after ordering', function() {
43 + var OnePlugin = createPlugin();
44 + var TwoPlugin = createPlugin();
45 + var ThreePlugin = createPlugin();
46 +
47 + EventPluginRegistry.injectEventPluginsByName({
48 + one: OnePlugin,
49 + two: TwoPlugin
50 + });
51 + EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);
52 + EventPluginRegistry.injectEventPluginsByName({
53 + three: ThreePlugin
54 + });
55 +
56 + expect(EventPluginRegistry.plugins.length).toBe(3);
57 + expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);
58 + expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);
59 + expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);
60 + });
61 +
62 + it('should be able to inject repeated plugins and out-of-order', function() {
63 + var OnePlugin = createPlugin();
64 + var TwoPlugin = createPlugin();
65 + var ThreePlugin = createPlugin();
66 +
67 + EventPluginRegistry.injectEventPluginsByName({
68 + one: OnePlugin,
69 + three: ThreePlugin
70 + });
71 + EventPluginRegistry.injectEventPluginOrder(['one', 'two', 'three']);
72 + EventPluginRegistry.injectEventPluginsByName({
73 + two: TwoPlugin,
74 + three: ThreePlugin
75 + });
76 +
77 + expect(EventPluginRegistry.plugins.length).toBe(3);
78 + expect(EventPluginRegistry.plugins[0]).toBe(OnePlugin);
79 + expect(EventPluginRegistry.plugins[1]).toBe(TwoPlugin);
80 + expect(EventPluginRegistry.plugins[2]).toBe(ThreePlugin);
81 + });
82 +
83 + it('should throw if plugin does not implement `extractEvents`', function() {
84 + var BadPlugin = {};
85 +
86 + EventPluginRegistry.injectEventPluginOrder(['bad']);
87 +
88 + expect(function() {
89 + EventPluginRegistry.injectEventPluginsByName({
90 + bad: BadPlugin
91 + });
92 + }).toThrow(
93 + 'Invariant Violation: EventPluginRegistry: Event plugins must ' +
94 + 'implement an `extractEvents` method, but `bad` does not.'
95 + );
96 + });
97 +
98 + it('should throw if plugin does not exist in ordering', function() {
99 + var OnePlugin = createPlugin();
100 + var RandomPlugin = createPlugin();
101 +
102 + EventPluginRegistry.injectEventPluginOrder(['one']);
103 +
104 + expect(function() {
105 + EventPluginRegistry.injectEventPluginsByName({
106 + one: OnePlugin,
107 + random: RandomPlugin
108 + });
109 + }).toThrow(
110 + 'Invariant Violation: EventPluginRegistry: Cannot inject event plugins ' +
111 + 'that do not exist in the plugin ordering, `random`.'
112 + );
113 + });
114 +
115 + it('should throw if ordering is injected more than once', function() {
116 + var pluginOrdering = [];
117 +
118 + EventPluginRegistry.injectEventPluginOrder(pluginOrdering);
119 +
120 + expect(function() {
121 + EventPluginRegistry.injectEventPluginOrder(pluginOrdering);
122 + }).toThrow(
123 + 'Invariant Violation: EventPluginRegistry: Cannot inject event plugin ' +
124 + 'ordering more than once.'
125 + );
126 + });
127 +
128 + it('should throw if different plugins injected using same name', function() {
129 + var OnePlugin = createPlugin();
130 + var TwoPlugin = createPlugin();
131 +
132 + EventPluginRegistry.injectEventPluginsByName({same: OnePlugin});
133 +
134 + expect(function() {
135 + EventPluginRegistry.injectEventPluginsByName({same: TwoPlugin});
136 + }).toThrow(
137 + 'Invariant Violation: EventPluginRegistry: Cannot inject two different ' +
138 + 'event plugins using the same name, `same`.'
139 + );
140 + });
141 +
142 + it('should publish registration names of injected plugins', function() {
143 + var OnePlugin = createPlugin({
144 + abstractEventTypes: {
145 + click: {registrationName: 'onClick'},
146 + focus: {registrationName: 'onFocus'}
147 + }
148 + });
149 + var TwoPlugin = createPlugin({
150 + abstractEventTypes: {
151 + magic: {
152 + phasedRegistrationNames: {
153 + bubbled: 'onMagicBubble',
154 + captured: 'onMagicCapture'
155 + }
156 + }
157 + }
158 + });
159 +
160 + EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});
161 + EventPluginRegistry.injectEventPluginOrder(['one', 'two']);
162 +
163 + expect(EventPluginRegistry.registrationNamesKeys.length).toBe(2);
164 + expect(EventPluginRegistry.registrationNames.onClick).toBe(OnePlugin);
165 + expect(EventPluginRegistry.registrationNames.onFocus).toBe(OnePlugin);
166 +
167 + EventPluginRegistry.injectEventPluginsByName({two: TwoPlugin});
168 +
169 + expect(EventPluginRegistry.registrationNamesKeys.length).toBe(4);
170 + expect(EventPluginRegistry.registrationNames.onMagicBubble).toBe(TwoPlugin);
171 + expect(
172 + EventPluginRegistry.registrationNames.onMagicCapture
173 + ).toBe(TwoPlugin);
174 + });
175 +
176 + it('should throw if multiple registration names collide', function() {
177 + var OnePlugin = createPlugin({
178 + abstractEventTypes: {
179 + photoCapture: {registrationName: 'onPhotoCapture'}
180 + }
181 + });
182 + var TwoPlugin = createPlugin({
183 + abstractEventTypes: {
184 + photo: {
185 + phasedRegistrationNames: {
186 + bubbled: 'onPhotoBubble',
187 + captured: 'onPhotoCapture'
188 + }
189 + }
190 + }
191 + });
192 +
193 + EventPluginRegistry.injectEventPluginsByName({
194 + one: OnePlugin,
195 + two: TwoPlugin
196 + });
197 +
198 + expect(function() {
199 + EventPluginRegistry.injectEventPluginOrder(['one', 'two']);
200 + }).toThrow(
201 + 'Invariant Violation: EventPluginHub: More than one plugin attempted ' +
202 + 'to publish the same registration name, `onPhotoCapture`.'
203 + );
204 + });
205 +
206 + it('should throw if an invalid event is published', function() {
207 + var OnePlugin = createPlugin({
208 + abstractEventTypes: {
209 + badEvent: {/* missing configuration */}
210 + }
211 + });
212 +
213 + EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});
214 +
215 + expect(function() {
216 + EventPluginRegistry.injectEventPluginOrder(['one']);
217 + }).toThrow(
218 + 'Invariant Violation: EventPluginRegistry: Failed to publish event ' +
219 + '`badEvent` for plugin `one`.'
220 + );
221 + });
222 +
223 + it('should be able to get the plugin from synthetic events', function() {
224 + var clickDispatchConfig = {
225 + registrationName: 'onClick'
226 + };
227 + var magicDispatchConfig = {
228 + phasedRegistrationNames: {
229 + bubbled: 'onMagicBubble',
230 + captured: 'onMagicCapture'
231 + }
232 + };
233 +
234 + var OnePlugin = createPlugin({
235 + abstractEventTypes: {
236 + click: clickDispatchConfig,
237 + magic: magicDispatchConfig
238 + }
239 + });
240 +
241 + var clickEvent = {reactEventType: clickDispatchConfig};
242 + var magicEvent = {reactEventType: magicDispatchConfig};
243 +
244 + expect(EventPluginRegistry.getPluginModuleForEvent(clickEvent)).toBe(null);
245 + expect(EventPluginRegistry.getPluginModuleForEvent(magicEvent)).toBe(null);
246 +
247 + EventPluginRegistry.injectEventPluginsByName({one: OnePlugin});
248 + EventPluginRegistry.injectEventPluginOrder(['one']);
249 +
250 + expect(
251 + EventPluginRegistry.getPluginModuleForEvent(clickEvent)
252 + ).toBe(OnePlugin);
253 + expect(
254 + EventPluginRegistry.getPluginModuleForEvent(magicEvent)
255 + ).toBe(OnePlugin);
256 + });
257 +
258 +});
src/eventPlugins/AnalyticsEventPluginFactory.js
+3 -3
@@ -141,9 +141,9 @@ if (__DEV__) {
141 * @param {string} topLevelTargetID ID of `topLevelTarget`.
142 * @param {object} nativeEvent Native browser event.
143 * @return {*} An accumulation of `AbstractEvent`s.
144 - * @see {EventPluginHub.extractAbstractEvents}
144 + * @see {EventPluginHub.extractEvents}
145 */
146 -function extractAbstractEvents(
146 +function extractEvents(
147 topLevelType,
148 topLevelTarget,
149 topLevelTargetID,
@@ -220,7 +220,7 @@ var createAnalyticsPlugin = function(cb, interval) {
220 interval > DEFAULT_INTERVAL_MS ? interval : DEFAULT_INTERVAL_MS
221 );
222
223 - return {extractAbstractEvents: extractAbstractEvents};
223 + return {extractEvents: extractEvents};
224 };
225
226 var AnalyticsEventPluginFactory = {
src/eventPlugins/EnterLeaveEventPlugin.js
+3 -3
@@ -50,9 +50,9 @@ var abstractEventTypes = {
50 * @param {string} topLevelTargetID ID of `topLevelTarget`.
51 * @param {object} nativeEvent Native browser event.
52 * @return {*} An accumulation of `AbstractEvent`s.
53 - * @see {EventPluginHub.extractAbstractEvents}
53 + * @see {EventPluginHub.extractEvents}
54 */
55 -var extractAbstractEvents = function(
55 +var extractEvents = function(
56 topLevelType,
57 topLevelTarget,
58 topLevelTargetID,
@@ -102,7 +102,7 @@ var extractAbstractEvents = function(
102
103 var EnterLeaveEventPlugin = {
104 abstractEventTypes: abstractEventTypes,
105 - extractAbstractEvents: extractAbstractEvents
105 + extractEvents: extractEvents
106 };
107
108 module.exports = EnterLeaveEventPlugin;
src/eventPlugins/ResponderEventPlugin.js
+9 -9
@@ -113,10 +113,10 @@ var abstractEventTypes = {
113 *
114 * - The current event plugin system will traverse the list of injected plugins,
115 * in order, and extract events by collecting the plugin's return value of
116 - * `extractAbstractEvents()`.
117 - * - These events that are returned from `extractAbstractEvents` are "deferred
116 + * `extractEvents()`.
117 + * - These events that are returned from `extractEvents` are "deferred
118 * dispatched events".
119 - * - When returned from `extractAbstractEvents`, deferred dispatched events
119 + * - When returned from `extractEvents`, deferred dispatched events
120 * contain an "accumulation" of deferred dispatches.
121 * -- These deferred dispatches are accumulated/collected before they are
122 * returned, but processed at a later time by the `EventPluginHub` (hence the
@@ -124,13 +124,13 @@ var abstractEventTypes = {
124 *
125 * In the process of returning their deferred dispatched events, event plugins
126 * themselves can dispatch events on-demand without returning them from
127 - * `extractAbstractEvents`. Plugins might want to do this, so that they can use
127 + * `extractEvents`. Plugins might want to do this, so that they can use
128 * event dispatching as a tool that helps them decide which events should be
129 * extracted in the first place.
130 *
131 * "On-Demand-Dispatched Events":
132 *
133 - * - On-demand dispatched are not returned from `extractAbstractEvents`.
133 + * - On-demand dispatched are not returned from `extractEvents`.
134 * - On-demand dispatched events are dispatched during the process of returning
135 * the deferred-dispatched events.
136 * - They should not have side effects.
@@ -150,7 +150,7 @@ var abstractEventTypes = {
150 * In the case of `ResponderEventPlugin`: If the `startShouldSetResponder`
151 * on-demand dispatch returns `true` (and some other details are satisfied) the
152 * `onResponderGrant` deferred dispatched event is returned from
153 - * `extractAbstractEvents`. The sequence of dispatch executions in this case
153 + * `extractEvents`. The sequence of dispatch executions in this case
154 * will appear as follows:
155 *
156 * - `startShouldSetResponder` (`ResponderEventPlugin` dispatches on-demand)
@@ -257,9 +257,9 @@ function canTriggerTransfer(topLevelType) {
257 * @param {string} topLevelTargetID ID of `topLevelTarget`.
258 * @param {object} nativeEvent Native browser event.
259 * @return {*} An accumulation of `AbstractEvent`s.
260 - * @see {EventPluginHub.extractAbstractEvents}
260 + * @see {EventPluginHub.extractEvents}
261 */
262 -var extractAbstractEvents = function(
262 +var extractEvents = function(
263 topLevelType,
264 topLevelTarget,
265 topLevelTargetID,
@@ -312,7 +312,7 @@ var extractAbstractEvents = function(
312 */
313 var ResponderEventPlugin = {
314 abstractEventTypes: abstractEventTypes,
315 - extractAbstractEvents: extractAbstractEvents,
315 + extractEvents: extractEvents,
316 getResponderID: getResponderID
317 };
318
src/eventPlugins/SimpleEventPlugin.js
+2 -2
@@ -222,9 +222,9 @@ var SimpleEventPlugin = {
222 * @param {string} topLevelTargetID ID of `topLevelTarget`.
223 * @param {object} nativeEvent Native browser event.
224 * @return {*} An accumulation of `AbstractEvent`s.
225 - * @see {EventPluginHub.extractAbstractEvents}
225 + * @see {EventPluginHub.extractEvents}
226 */
227 - extractAbstractEvents: function(
227 + extractEvents: function(
228 topLevelType,
229 topLevelTarget,
230 topLevelTargetID,
src/eventPlugins/TapEventPlugin.js
+3 -3
@@ -52,9 +52,9 @@ var abstractEventTypes = {
52 * @param {string} topLevelTargetID ID of `topLevelTarget`.
53 * @param {object} nativeEvent Native browser event.
54 * @return {*} An accumulation of `AbstractEvent`s.
55 - * @see {EventPluginHub.extractAbstractEvents}
55 + * @see {EventPluginHub.extractEvents}
56 */
57 -var extractAbstractEvents = function(
57 +var extractEvents = function(
58 topLevelType,
59 topLevelTarget,
60 topLevelTargetID,
@@ -85,7 +85,7 @@ var TapEventPlugin = {
85 tapMoveThreshold: tapMoveThreshold,
86 startCoords: startCoords,
87 abstractEventTypes: abstractEventTypes,
88 - extractAbstractEvents: extractAbstractEvents
88 + extractEvents: extractEvents
89 };
90
91 module.exports = TapEventPlugin;
src/eventPlugins/__tests__/AnalyticsEventPlugin-test.js
+25 -33
@@ -19,26 +19,29 @@
19
20 "use strict";
21
22 -require('mock-modules')
23 - .dontMock('AnalyticsEventPluginFactory')
24 - .dontMock('EventPluginHub')
25 - .dontMock('React')
26 - .dontMock('ReactEventEmitter')
27 - .dontMock('ReactEventTopLevelCallback')
28 - .dontMock('ReactInstanceHandles')
29 - .dontMock('ReactTestUtils');
30 -
31 -var AnalyticsEventPluginFactory = require('AnalyticsEventPluginFactory');
32 -var EventPluginHub = require('EventPluginHub');
22 var mocks = require('mocks');
34 -var React = require('React');
35 -var ReactEventEmitter = require('ReactEventEmitter');
36 -var ReactEventTopLevelCallback = require('ReactEventTopLevelCallback');
37 -var ReactTestUtils = require('ReactTestUtils');
38 -
39 -ReactEventEmitter.ensureListening(false, ReactEventTopLevelCallback);
23
24 describe('AnalyticsEventPlugin', function() {
25 + var AnalyticsEventPluginFactory;
26 + var EventPluginHub;
27 + var React;
28 + var ReactEventEmitter;
29 + var ReactEventTopLevelCallback;
30 + var ReactTestUtils;
31 +
32 + beforeEach(function() {
33 + require('mock-modules').dumpCache();
34 +
35 + AnalyticsEventPluginFactory = require('AnalyticsEventPluginFactory');
36 + EventPluginHub = require('EventPluginHub');
37 + React = require('React');
38 + ReactEventEmitter = require('ReactEventEmitter');
39 + ReactEventTopLevelCallback = require('ReactEventTopLevelCallback');
40 + ReactTestUtils = require('ReactTestUtils');
41 +
42 + ReactEventEmitter.ensureListening(false, ReactEventTopLevelCallback);
43 + });
44 +
45 it('should count events correctly', function() {
46 var numClickEvents = 5;
47 var numDoubleClickEvents = 7;
@@ -69,9 +72,8 @@ describe('AnalyticsEventPlugin', function() {
72 );
73
74 EventPluginHub.injection.injectEventPluginsByName({
72 - AnalyticsEventPlugin: AnalyticsEventPluginFactory.createAnalyticsPlugin(
73 - cb
74 - )
75 + AnalyticsEventPlugin:
76 + AnalyticsEventPluginFactory.createAnalyticsPlugin(cb)
77 });
78
79 // Simulate some clicks
@@ -87,22 +89,12 @@ describe('AnalyticsEventPlugin', function() {
89
90 window.mockRunTimersOnce();
91 expect(cb).toBeCalled();
90 -
92 });
93
94 it('error non no callback', function() {
94 - var error = false;
95 - try {
96 - EventPluginHub.injection.injectEventPluginsByName({
97 - AnalyticsEventPlugin: AnalyticsEventPluginFactory.createAnalyticsPlugin(
98 - null
99 - )
100 - });
101 - } catch(e) {
102 - error = true;
103 - }
104 -
105 - expect(error).toBe(true);
95 + expect(function() {
96 + AnalyticsEventPluginFactory.createAnalyticsPlugin(null);
97 + }).toThrow();
98 });
99
100 it('error on invalid analytics events', function() {
src/eventPlugins/__tests__/ResponderEventPlugin-test.js
+7 -7
@@ -79,7 +79,7 @@ var onResponderGrant = function(id, cb) {
79 };
80
81 var extractForTouchStart = function(renderedTargetID) {
82 - return ResponderEventPlugin.extractAbstractEvents(
82 + return ResponderEventPlugin.extractEvents(
83 topLevelTypes.topTouchStart,
84 DUMMY_NATIVE_EVENT,
85 renderedTargetID,
@@ -88,7 +88,7 @@ var extractForTouchStart = function(renderedTargetID) {
88 };
89
90 var extractForTouchMove = function(renderedTargetID) {
91 - return ResponderEventPlugin.extractAbstractEvents(
91 + return ResponderEventPlugin.extractEvents(
92 topLevelTypes.topTouchMove,
93 DUMMY_NATIVE_EVENT,
94 renderedTargetID,
@@ -97,7 +97,7 @@ var extractForTouchMove = function(renderedTargetID) {
97 };
98
99 var extractForTouchEnd = function(renderedTargetID) {
100 - return ResponderEventPlugin.extractAbstractEvents(
100 + return ResponderEventPlugin.extractEvents(
101 topLevelTypes.topTouchEnd,
102 DUMMY_NATIVE_EVENT,
103 renderedTargetID,
@@ -106,7 +106,7 @@ var extractForTouchEnd = function(renderedTargetID) {
106 };
107
108 var extractForMouseDown = function(renderedTargetID) {
109 - return ResponderEventPlugin.extractAbstractEvents(
109 + return ResponderEventPlugin.extractEvents(
110 topLevelTypes.topMouseDown,
111 DUMMY_NATIVE_EVENT,
112 renderedTargetID,
@@ -115,7 +115,7 @@ var extractForMouseDown = function(renderedTargetID) {
115 };
116
117 var extractForMouseMove = function(renderedTargetID) {
118 - return ResponderEventPlugin.extractAbstractEvents(
118 + return ResponderEventPlugin.extractEvents(
119 topLevelTypes.topMouseMove,
120 DUMMY_NATIVE_EVENT,
121 renderedTargetID,
@@ -125,7 +125,7 @@ var extractForMouseMove = function(renderedTargetID) {
125
126
127 var extractForMouseUp = function(renderedTargetID) {
128 - return ResponderEventPlugin.extractAbstractEvents(
128 + return ResponderEventPlugin.extractEvents(
129 topLevelTypes.topMouseUp,
130 DUMMY_NATIVE_EVENT,
131 renderedTargetID,
@@ -134,7 +134,7 @@ var extractForMouseUp = function(renderedTargetID) {
134 };
135
136 var extractForScroll = function(renderedTargetID) {
137 - return ResponderEventPlugin.extractAbstractEvents(
137 + return ResponderEventPlugin.extractEvents(
138 topLevelTypes.topScroll,
139 DUMMY_NATIVE_EVENT,
140 renderedTargetID,