Skip to content

Commit decff26

Browse files
committed
Add a warning for adding some properties in the SyntheticEvent object if Proxy is supported
1 parent 6454bfb commit decff26

12 files changed

+78
-15
lines changed

src/renderers/dom/client/syntheticEvents/SyntheticClipboardEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ var ClipboardEventInterface = {
3434
* @extends {SyntheticUIEvent}
3535
*/
3636
function SyntheticClipboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
37-
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
37+
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
3838
}
3939

4040
SyntheticEvent.augmentClass(SyntheticClipboardEvent, ClipboardEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticCompositionEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ function SyntheticCompositionEvent(
3333
nativeEvent,
3434
nativeEventTarget
3535
) {
36-
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
36+
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
3737
}
3838

3939
SyntheticEvent.augmentClass(

src/renderers/dom/client/syntheticEvents/SyntheticDragEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var DragEventInterface = {
2828
* @extends {SyntheticUIEvent}
2929
*/
3030
function SyntheticDragEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
31-
SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
31+
return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
3232
}
3333

3434
SyntheticMouseEvent.augmentClass(SyntheticDragEvent, DragEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticEvent.js

+49-5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ var assign = require('Object.assign');
1717
var emptyFunction = require('emptyFunction');
1818
var warning = require('warning');
1919

20+
var didWarnForAddedNewProperty = false;
21+
var isProxySupported = typeof Proxy === 'function';
22+
23+
var shouldBeReleasedProperties = [
24+
'dispatchConfig',
25+
'_targetInst',
26+
'nativeEvent',
27+
'isDefaultPrevented',
28+
'isPropagationStopped',
29+
'_dispatchListeners',
30+
'_dispatchInstances',
31+
];
32+
2033
/**
2134
* @interface Event
2235
* @see http://www.w3.org/TR/DOM-Level-3-Events/
@@ -57,7 +70,7 @@ var EventInterface = {
5770
function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarget) {
5871
if (__DEV__) {
5972
// these have a getter/setter for warnings
60-
delete this.nativeEvent;
73+
delete this.nativeEvent;
6174
delete this.preventDefault;
6275
delete this.stopPropagation;
6376
}
@@ -95,6 +108,7 @@ function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarg
95108
this.isDefaultPrevented = emptyFunction.thatReturnsFalse;
96109
}
97110
this.isPropagationStopped = emptyFunction.thatReturnsFalse;
111+
return this;
98112
}
99113

100114
assign(SyntheticEvent.prototype, {
@@ -156,22 +170,52 @@ assign(SyntheticEvent.prototype, {
156170
this[propName] = null;
157171
}
158172
}
173+
for (var i = 0; i < shouldBeReleasedProperties.length; i++) {
174+
this[shouldBeReleasedProperties[i]] = null;
175+
}
159176
if (__DEV__) {
160177
var noop = require('emptyFunction');
161178
Object.defineProperty(this, 'nativeEvent', getPooledWarningPropertyDefinition('nativeEvent', null));
162179
Object.defineProperty(this, 'preventDefault', getPooledWarningPropertyDefinition('preventDefault', noop));
163180
Object.defineProperty(this, 'stopPropagation', getPooledWarningPropertyDefinition('stopPropagation', noop));
164-
} else {
165-
this.nativeEvent = null;
166181
}
167-
this.dispatchConfig = null;
168-
this._targetInst = null;
169182
},
170183

171184
});
172185

173186
SyntheticEvent.Interface = EventInterface;
174187

188+
if (__DEV__) {
189+
if (isProxySupported) {
190+
/*eslint-disable no-func-assign */
191+
SyntheticEvent = new Proxy(SyntheticEvent, {
192+
construct: function(target, args) {
193+
return this.apply(target, {}, args);
194+
},
195+
apply: function(constructor, that, args) {
196+
return new Proxy(constructor.apply(that, args), {
197+
set: function(target, prop, value) {
198+
if (prop !== 'isPersistent' &&
199+
!target.constructor.Interface.hasOwnProperty(prop) &&
200+
shouldBeReleasedProperties.indexOf(prop) === -1) {
201+
warning(
202+
didWarnForAddedNewProperty || target.isPersistent(),
203+
'This synthetic event is reused for performance reasons. If you\'re ' +
204+
'seeing this, you\'re adding a new property in the synthetic event object. ' +
205+
'The property is never released. See ' +
206+
'https://fb.me/react-event-pooling for more information.'
207+
);
208+
didWarnForAddedNewProperty = true;
209+
}
210+
target[prop] = value;
211+
return true;
212+
},
213+
});
214+
},
215+
});
216+
/*eslint-enable no-func-assign */
217+
}
218+
}
175219
/**
176220
* Helper to reduce boilerplate when creating subclasses.
177221
*

src/renderers/dom/client/syntheticEvents/SyntheticFocusEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ var FocusEventInterface = {
2828
* @extends {SyntheticUIEvent}
2929
*/
3030
function SyntheticFocusEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
31-
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
31+
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
3232
}
3333

3434
SyntheticUIEvent.augmentClass(SyntheticFocusEvent, FocusEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticInputEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function SyntheticInputEvent(
3434
nativeEvent,
3535
nativeEventTarget
3636
) {
37-
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
37+
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
3838
}
3939

4040
SyntheticEvent.augmentClass(

src/renderers/dom/client/syntheticEvents/SyntheticKeyboardEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ var KeyboardEventInterface = {
7676
* @extends {SyntheticUIEvent}
7777
*/
7878
function SyntheticKeyboardEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
79-
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
79+
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
8080
}
8181

8282
SyntheticUIEvent.augmentClass(SyntheticKeyboardEvent, KeyboardEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticMouseEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ var MouseEventInterface = {
7272
* @extends {SyntheticUIEvent}
7373
*/
7474
function SyntheticMouseEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
75-
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
75+
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
7676
}
7777

7878
SyntheticUIEvent.augmentClass(SyntheticMouseEvent, MouseEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticTouchEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ var TouchEventInterface = {
3737
* @extends {SyntheticUIEvent}
3838
*/
3939
function SyntheticTouchEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
40-
SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
40+
return SyntheticUIEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
4141
}
4242

4343
SyntheticUIEvent.augmentClass(SyntheticTouchEvent, TouchEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticUIEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ var UIEventInterface = {
5151
* @extends {SyntheticEvent}
5252
*/
5353
function SyntheticUIEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
54-
SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
54+
return SyntheticEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
5555
}
5656

5757
SyntheticEvent.augmentClass(SyntheticUIEvent, UIEventInterface);

src/renderers/dom/client/syntheticEvents/SyntheticWheelEvent.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ var WheelEventInterface = {
5050
* @extends {SyntheticMouseEvent}
5151
*/
5252
function SyntheticWheelEvent(dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget) {
53-
SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
53+
return SyntheticMouseEvent.call(this, dispatchConfig, dispatchMarker, nativeEvent, nativeEventTarget);
5454
}
5555

5656
SyntheticMouseEvent.augmentClass(SyntheticWheelEvent, WheelEventInterface);

src/renderers/dom/client/syntheticEvents/__tests__/SyntheticEvent-test.js

+19
Original file line numberDiff line numberDiff line change
@@ -160,4 +160,23 @@ describe('SyntheticEvent', function() {
160160
'See https://fb.me/react-event-pooling for more information.'
161161
);
162162
});
163+
164+
it('should warn if Proxy is supported and the synthetic event is added a property', function() {
165+
spyOn(console, 'error');
166+
var syntheticEvent = createEvent({});
167+
syntheticEvent.foo = 'bar';
168+
SyntheticEvent.release(syntheticEvent);
169+
expect(syntheticEvent.foo).toBe('bar');
170+
if (typeof Proxy === 'function') {
171+
expect(console.error.calls.length).toBe(1);
172+
expect(console.error.argsForCall[0][0]).toBe(
173+
'Warning: This synthetic event is reused for performance reasons. If you\'re ' +
174+
'seeing this, you\'re adding a new property in the synthetic event object. ' +
175+
'The property is never released. See ' +
176+
'https://fb.me/react-event-pooling for more information.'
177+
);
178+
} else {
179+
expect(console.error.calls.length).toBe(0);
180+
}
181+
});
163182
});

0 commit comments

Comments
 (0)