Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,9 @@ var rendererSharedState = {
React: 'react/lib/React',
// Shared state
ReactCurrentOwner: 'react/lib/ReactCurrentOwner',
checkPropTypes: 'react/lib/checkPropTypes',
ReactComponentTreeHook: 'react/lib/ReactComponentTreeHook',
ReactDebugCurrentFrame: 'react/lib/ReactDebugCurrentFrame',
};

var moduleMapReactDOM = Object.assign(
Expand Down
2 changes: 2 additions & 0 deletions scripts/fiber/tests-passing.txt
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,8 @@ src/isomorphic/classic/element/__tests__/ReactElementValidator-test.js
* does not blow up on key warning with undefined type

src/isomorphic/classic/types/__tests__/ReactPropTypes-test.js
* does not return a value from a validator
* does not throw if validator throws
* should warn for invalid strings
* should fail date and regexp correctly
* should not warn for valid values
Expand Down
3 changes: 3 additions & 0 deletions src/isomorphic/React.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var ReactVersion = require('ReactVersion');

var onlyChild = require('onlyChild');
var warning = require('warning');
var checkPropTypes = require('checkPropTypes');

var createElement = ReactElement.createElement;
var createFactory = ReactElement.createFactory;
Expand Down Expand Up @@ -71,6 +72,8 @@ var React = {
cloneElement: cloneElement,
isValidElement: ReactElement.isValidElement,

checkPropTypes: checkPropTypes,

// Classic

PropTypes: ReactPropTypes,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ describe('ReactContextValidator', () => {
ReactTestUtils.renderIntoDocument(<Component testContext={{bar: 123}} />);
expectDev(console.error.calls.count()).toBe(1);
expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(0)[0])).toBe(
'Warning: Failed childContext type: ' +
'Warning: Failed child context type: ' +
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is released in 15.x, it would potentially break CIs on libraries that assert about this warning in tests.

We have some tests like this about prop types in React Redux so I wouldn't be surprised if somebody tested a similar thing about context types.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this needs to be released until 16. Could be mistaken.

'The child context `foo` is marked as required in `Component`, but its ' +
'value is `undefined`.\n' +
' in Component (at **)'
Expand All @@ -271,7 +271,7 @@ describe('ReactContextValidator', () => {

expectDev(console.error.calls.count()).toBe(2);
expectDev(normalizeCodeLocInfo(console.error.calls.argsFor(1)[0])).toBe(
'Warning: Failed childContext type: ' +
'Warning: Failed child context type: ' +
'Invalid child context `foo` of type `number` ' +
'supplied to `Component`, expected `string`.\n' +
' in Component (at **)'
Expand Down
9 changes: 3 additions & 6 deletions src/isomorphic/classic/class/ReactClass.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

var ReactBaseClasses = require('ReactBaseClasses');
var ReactElement = require('ReactElement');
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue');

var emptyObject = require('emptyObject');
Expand All @@ -22,8 +21,6 @@ var warning = require('warning');

var ReactComponent = ReactBaseClasses.Component;

import type { ReactPropTypeLocations } from 'ReactPropTypeLocations';

var MIXINS_KEY = 'mixins';

// Helper function to allow the creation of anonymous functions which do not
Expand Down Expand Up @@ -330,7 +327,7 @@ var RESERVED_SPEC_KEYS = {
validateTypeDef(
Constructor,
childContextTypes,
'childContext'
'child context'
);
}
Constructor.childContextTypes = Object.assign(
Expand Down Expand Up @@ -390,7 +387,7 @@ var RESERVED_SPEC_KEYS = {
function validateTypeDef(
Constructor,
typeDef,
location: ReactPropTypeLocations,
location: string,
) {
for (var propName in typeDef) {
if (typeDef.hasOwnProperty(propName)) {
Expand All @@ -401,7 +398,7 @@ function validateTypeDef(
'%s: %s type `%s` is invalid; it must be a function, usually from ' +
'React.PropTypes.',
Constructor.displayName || 'ReactClass',
ReactPropTypeLocationNames[location],
location,
propName
);
}
Expand Down
56 changes: 56 additions & 0 deletions src/isomorphic/classic/element/ReactDebugCurrentFrame.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Copyright 2013-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
* @providesModule ReactDebugCurrentFrame
* @flow
*/

'use strict';

import type { Fiber } from 'ReactFiber';
import type { DebugID } from 'ReactInstanceType';

const ReactDebugCurrentFrame = {};

if (__DEV__) {
var {
getStackAddendumByID,
getStackAddendumByWorkInProgressFiber,
getCurrentStackAddendum,
} = require('ReactComponentTreeHook');

// Component that is being worked on
ReactDebugCurrentFrame.current = (null : Fiber | DebugID | null);

// Element that is being cloned or created
ReactDebugCurrentFrame.element = (null : *);

ReactDebugCurrentFrame.getStackAddendum = function() : string | null {
let stack = null;
const current = ReactDebugCurrentFrame.current;
const element = ReactDebugCurrentFrame.element;
if (current !== null) {
if (typeof current === 'number') {
// DebugID from Stack.
const debugID = current;
stack = getStackAddendumByID(debugID);
} else if (typeof current.tag === 'number') {
// This is a Fiber.
// The stack will only be correct if this is a work in progress
// version and we're calling it during reconciliation.
const workInProgress = current;
stack = getStackAddendumByWorkInProgressFiber(workInProgress);
}
} else if (element !== null) {
stack = getCurrentStackAddendum(element);
}
return stack;
};
}

module.exports = ReactDebugCurrentFrame;
24 changes: 20 additions & 4 deletions src/isomorphic/classic/element/ReactElementValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,11 @@ var checkReactTypeSpec = require('checkReactTypeSpec');
var canDefineProperty = require('canDefineProperty');
var getComponentName = require('getComponentName');
var getIteratorFn = require('getIteratorFn');
var warning = require('warning');

if (__DEV__) {
var warning = require('warning');
var ReactDebugCurrentFrame = require('ReactDebugCurrentFrame');
}

function getDeclarationErrorAddendum() {
if (ReactCurrentOwner.current) {
Expand Down Expand Up @@ -181,9 +185,7 @@ function validatePropTypes(element) {
componentClass.propTypes,
element.props,
'prop',
name,
element,
null
name
);
}
if (typeof componentClass.getDefaultProps === 'function') {
Expand Down Expand Up @@ -248,6 +250,10 @@ var ReactElementValidator = {
return element;
}

if (__DEV__) {
ReactDebugCurrentFrame.element = element;
}

// Skip key warning if the type isn't valid since our key validation logic
// doesn't expect a non-string/function type and can throw confusing errors.
// We don't want exception behavior to differ between dev and prod.
Expand All @@ -261,6 +267,10 @@ var ReactElementValidator = {

validatePropTypes(element);

if (__DEV__) {
ReactDebugCurrentFrame.element = null;
}

return element;
},

Expand Down Expand Up @@ -301,10 +311,16 @@ var ReactElementValidator = {

cloneElement: function(element, props, children) {
var newElement = ReactElement.cloneElement.apply(this, arguments);
if (__DEV__) {
ReactDebugCurrentFrame.element = newElement;
}
for (var i = 2; i < arguments.length; i++) {
validateChildKeys(arguments[i], newElement.type);
}
validatePropTypes(newElement);
if (__DEV__) {
ReactDebugCurrentFrame.element = null;
}
return newElement;
},

Expand Down
34 changes: 12 additions & 22 deletions src/isomorphic/classic/types/ReactPropTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
'use strict';

var ReactElement = require('ReactElement');
var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames');
var ReactPropTypesSecret = require('ReactPropTypesSecret');

var emptyFunction = require('emptyFunction');
Expand Down Expand Up @@ -123,6 +122,7 @@ if (__DEV__) {
};
}


/**
* inlined Object.is polyfill to avoid requiring consumers ship their own
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/is
Expand Down Expand Up @@ -192,16 +192,15 @@ function createChainableTypeChecker(validate) {
}
}
if (props[propName] == null) {
var locationName = ReactPropTypeLocationNames[location];
if (isRequired) {
if (props[propName] === null) {
return new PropTypeError(
`The ${locationName} \`${propFullName}\` is marked as required ` +
`The ${location} \`${propFullName}\` is marked as required ` +
`in \`${componentName}\`, but its value is \`null\`.`
);
}
return new PropTypeError(
`The ${locationName} \`${propFullName}\` is marked as required in ` +
`The ${location} \`${propFullName}\` is marked as required in ` +
`\`${componentName}\`, but its value is \`undefined\`.`
);
}
Expand Down Expand Up @@ -235,14 +234,13 @@ function createPrimitiveTypeChecker(expectedType) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== expectedType) {
var locationName = ReactPropTypeLocationNames[location];
// `propValue` being instance of, say, date/regexp, pass the 'object'
// check, but we can offer a more precise error message here rather than
// 'of type `object`'.
var preciseType = getPreciseType(propValue);

return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of type ` +
`Invalid ${location} \`${propFullName}\` of type ` +
`\`${preciseType}\` supplied to \`${componentName}\`, expected ` +
`\`${expectedType}\`.`
);
Expand All @@ -265,10 +263,9 @@ function createArrayOfTypeChecker(typeChecker) {
}
var propValue = props[propName];
if (!Array.isArray(propValue)) {
var locationName = ReactPropTypeLocationNames[location];
var propType = getPropType(propValue);
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of type ` +
`Invalid ${location} \`${propFullName}\` of type ` +
`\`${propType}\` supplied to \`${componentName}\`, expected an array.`
);
}
Expand All @@ -294,10 +291,9 @@ function createElementTypeChecker() {
function validate(props, propName, componentName, location, propFullName) {
var propValue = props[propName];
if (!ReactElement.isValidElement(propValue)) {
var locationName = ReactPropTypeLocationNames[location];
var propType = getPropType(propValue);
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of type ` +
`Invalid ${location} \`${propFullName}\` of type ` +
`\`${propType}\` supplied to \`${componentName}\`, expected a single ReactElement.`
);
}
Expand All @@ -309,11 +305,10 @@ function createElementTypeChecker() {
function createInstanceTypeChecker(expectedClass) {
function validate(props, propName, componentName, location, propFullName) {
if (!(props[propName] instanceof expectedClass)) {
var locationName = ReactPropTypeLocationNames[location];
var expectedClassName = expectedClass.name || ANONYMOUS;
var actualClassName = getClassName(props[propName]);
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of type ` +
`Invalid ${location} \`${propFullName}\` of type ` +
`\`${actualClassName}\` supplied to \`${componentName}\`, expected ` +
`instance of \`${expectedClassName}\`.`
);
Expand All @@ -337,10 +332,9 @@ function createEnumTypeChecker(expectedValues) {
}
}

var locationName = ReactPropTypeLocationNames[location];
var valuesString = JSON.stringify(expectedValues);
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of value \`${propValue}\` ` +
`Invalid ${location} \`${propFullName}\` of value \`${propValue}\` ` +
`supplied to \`${componentName}\`, expected one of ${valuesString}.`
);
}
Expand All @@ -357,9 +351,8 @@ function createObjectOfTypeChecker(typeChecker) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
var locationName = ReactPropTypeLocationNames[location];
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of type ` +
`Invalid ${location} \`${propFullName}\` of type ` +
`\`${propType}\` supplied to \`${componentName}\`, expected an object.`
);
}
Expand Down Expand Up @@ -406,9 +399,8 @@ function createUnionTypeChecker(arrayOfTypeCheckers) {
}
}

var locationName = ReactPropTypeLocationNames[location];
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` supplied to ` +
`Invalid ${location} \`${propFullName}\` supplied to ` +
`\`${componentName}\`.`
);
}
Expand All @@ -418,9 +410,8 @@ function createUnionTypeChecker(arrayOfTypeCheckers) {
function createNodeChecker() {
function validate(props, propName, componentName, location, propFullName) {
if (!isNode(props[propName])) {
var locationName = ReactPropTypeLocationNames[location];
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` supplied to ` +
`Invalid ${location} \`${propFullName}\` supplied to ` +
`\`${componentName}\`, expected a ReactNode.`
);
}
Expand All @@ -434,9 +425,8 @@ function createShapeTypeChecker(shapeTypes) {
var propValue = props[propName];
var propType = getPropType(propValue);
if (propType !== 'object') {
var locationName = ReactPropTypeLocationNames[location];
return new PropTypeError(
`Invalid ${locationName} \`${propFullName}\` of type \`${propType}\` ` +
`Invalid ${location} \`${propFullName}\` of type \`${propType}\` ` +
`supplied to \`${componentName}\`, expected \`object\`.`
);
}
Expand Down
Loading