@samitouri / QOS-React-2 / commits / 119294dcae

Validate that update callback is a function (#8639)

Dan Abramov committed Dec 27, 2016 at 08:38 UTC 119294dcae46edd0d19ff7e7d6d25062ea68001a
3 files changed +37 -3
scripts/fiber/tests-failing.txt
-3
@@ -86,9 +86,6 @@ src/renderers/shared/shared/__tests__/ReactStatelessComponent-test.js
86
87 src/renderers/shared/shared/__tests__/ReactUpdates-test.js
88 * marks top-level updates
89 -* throws in setState if the update callback is not a function
90 -* throws in replaceState if the update callback is not a function
91 -* throws in forceUpdate if the update callback is not a function
89
90 src/renderers/shared/shared/__tests__/refs-test.js
91 * Should increase refs with an increase in divs
scripts/fiber/tests-passing.txt
+3
@@ -1564,6 +1564,9 @@ src/renderers/shared/shared/__tests__/ReactUpdates-test.js
1564 * should queue updates from during mount
1565 * calls componentWillReceiveProps setState callback properly
1566 * does not call render after a component as been deleted
1567 +* throws in setState if the update callback is not a function
1568 +* throws in replaceState if the update callback is not a function
1569 +* throws in forceUpdate if the update callback is not a function
1570 * does not update one component twice in a batch (#2410)
1571 * does not update one component twice in a batch (#6371)
1572 * unstable_batchedUpdates should return value from a callback
src/renderers/shared/fiber/ReactFiberClassComponent.js
+34
@@ -33,6 +33,31 @@ var invariant = require('invariant');
33
34 const isArray = Array.isArray;
35
36 +function formatUnexpectedArgument(arg) {
37 + var type = typeof arg;
38 + if (type !== 'object') {
39 + return type;
40 + }
41 + var displayName = arg.constructor && arg.constructor.name || type;
42 + var keys = Object.keys(arg);
43 + if (keys.length > 0 && keys.length < 20) {
44 + return `${displayName} (keys: ${keys.join(', ')})`;
45 + }
46 + return displayName;
47 +}
48 +
49 +function validateCallback(callback, callerName) {
50 + if (typeof callback !== 'function') {
51 + invariant(
52 + false,
53 + '%s(...): Expected the last optional `callback` argument to be a ' +
54 + 'function. Instead received: %s.',
55 + callerName,
56 + formatUnexpectedArgument(callback)
57 + );
58 + }
59 +}
60 +
61 module.exports = function(
62 scheduleUpdate : (fiber : Fiber, priorityLevel : PriorityLevel) => void,
63 getPriorityContext : () => PriorityLevel,
@@ -42,18 +67,27 @@ module.exports = function(
67 const updater = {
68 isMounted,
69 enqueueSetState(instance, partialState, callback) {
70 + if (callback) {
71 + validateCallback(callback, 'setState');
72 + }
73 const fiber = ReactInstanceMap.get(instance);
74 const priorityLevel = getPriorityContext();
75 addUpdate(fiber, partialState, callback || null, priorityLevel);
76 scheduleUpdate(fiber, priorityLevel);
77 },
78 enqueueReplaceState(instance, state, callback) {
79 + if (callback) {
80 + validateCallback(callback, 'replaceState');
81 + }
82 const fiber = ReactInstanceMap.get(instance);
83 const priorityLevel = getPriorityContext();
84 addReplaceUpdate(fiber, state, callback || null, priorityLevel);
85 scheduleUpdate(fiber, priorityLevel);
86 },
87 enqueueForceUpdate(instance, callback) {
88 + if (callback) {
89 + validateCallback(callback, 'forceUpdate');
90 + }
91 const fiber = ReactInstanceMap.get(instance);
92 const priorityLevel = getPriorityContext();
93 addForceUpdate(fiber, callback || null, priorityLevel);