Compare commits

...

5 Commits

Author SHA1 Message Date
Nicolas Gallagher
65055028c6 0.0.98 2017-06-07 16:03:26 -07:00
Nicolas Gallagher
93f425e414 [fix] event normalization
Fix #508
2017-06-07 16:02:45 -07:00
Nicolas Gallagher
ce4cc8a946 Remove avoidable vendor code
Updates the 'StyleSheetValidation' and 'ColorPropType' implementations
with the latest from React Native.
2017-06-05 20:06:22 -07:00
Nicolas Gallagher
77fd867421 [fix] correct types
Fix #465
2017-06-05 19:51:34 -07:00
Nicolas Gallagher
22999d7e5b Run lint and test before releasing new versions 2017-06-02 15:29:11 -07:00
24 changed files with 296 additions and 214 deletions

View File

@@ -23,35 +23,47 @@ Install dependencies (requires [yarn](https://yarnpkg.com/en/docs/install):
yarn
```
## Unit tests
## Automated tests
To run flow:
```
npm run flow
```
To run the unit tests:
```
npm test
npm run jest
```
…in watch mode:
```
npm run test:watch
npm run jest:watch
```
To run all automated tests:
```
npm test
```
## Visual tests
Run the interactive storybook:
To run the interactive storybook:
```
npm run docs:start
```
Run generate a static build of the storybook:
To generate a static build of the storybook:
```
npm run docs:build
```
Run the performance benchmarks in a browser (opening `./performance/index.html`):
To run the performance benchmarks in a browser (opening `./benchmarks/index.html`):
```
npm run benchmarks
@@ -59,7 +71,7 @@ npm run benchmarks
## Compile and build
Compile the source code to `dist`:
To compile the source code to `dist`:
```
npm run compile
@@ -73,7 +85,7 @@ npm run build
### Pre-commit
Before creating a commit run:
To format and lint code before commit:
```
npm run precommit

View File

@@ -1,6 +1,6 @@
{
"name": "react-native-web",
"version": "0.0.97",
"version": "0.0.98",
"description": "React Native for Web",
"main": "dist/index.js",
"files": [
@@ -18,19 +18,25 @@
"flow": "flow",
"fmt": "find benchmarks docs src -name '*.js' | grep -v -E '(node_modules|dist)' | xargs npm run fmt:cmd",
"fmt:cmd": "prettier --print-width=100 --single-quote --write",
"jest": "jest",
"jest:watch": "npm run test -- --watch",
"lint": "npm run lint:cmd -- benchmarks docs src",
"lint:cmd": "eslint --fix --ignore-path .gitignore",
"precommit": "lint-staged",
"release": "npm run compile && npm run build && npm publish",
"test": "jest",
"test:watch": "npm run test -- --watch"
"release": "npm run lint && npm run test && npm run compile && npm run build && npm publish",
"test": "flow && jest"
},
"babel": {
"presets": [
"react-native"
],
"plugins": [
[ "transform-react-remove-prop-types", { "mode": "wrap" } ]
[
"transform-react-remove-prop-types",
{
"mode": "wrap"
}
]
]
},
"jest": {
@@ -77,7 +83,7 @@
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-react": "^6.10.3",
"file-loader": "^0.11.1",
"flow-bin": "^0.46.0",
"flow-bin": "^0.47.0",
"jest": "^19.0.2",
"lint-staged": "^3.4.2",
"node-libs-browser": "^0.5.3",

View File

@@ -0,0 +1,65 @@
/**
* @flow
*/
import StyleSheet from '../StyleSheet';
import View from '../../components/View';
import { any, node } from 'prop-types';
import React, { Component } from 'react';
type Context = {
rootTag: any
};
type Props = {
children?: React.Children,
rootTag: any
};
type State = {
mainKey: number
};
class AppContainer extends Component {
props: Props;
state: State = { mainKey: 1 };
static childContextTypes = {
rootTag: any
};
static propTypes = {
children: node,
rootTag: any.isRequired
};
getChildContext(): Context {
return {
rootTag: this.props.rootTag
};
}
render() {
return (
<View pointerEvents="box-none" style={styles.appContainer}>
<View
children={this.props.children}
key={this.state.mainKey}
pointerEvents="box-none"
style={styles.appContainer}
/>
</View>
);
}
}
const styles = StyleSheet.create({
/**
* Ensure that the application covers the whole screen.
*/
appContainer: {
flex: 1
}
});
module.exports = AppContainer;

View File

@@ -1,41 +0,0 @@
/**
* @flow
*/
import StyleSheet from '../StyleSheet';
import View from '../../components/View';
import { any, object } from 'prop-types';
import React, { Component } from 'react';
class ReactNativeApp extends Component {
static propTypes = {
initialProps: object,
rootComponent: any.isRequired,
rootTag: any
};
render() {
const { initialProps, rootComponent: RootComponent, rootTag } = this.props;
return (
<View style={styles.appContainer}>
<RootComponent {...initialProps} rootTag={rootTag} />
</View>
);
}
}
const styles = StyleSheet.create({
/**
* Ensure that the application covers the whole screen.
*/
appContainer: {
position: 'absolute',
left: 0,
top: 0,
right: 0,
bottom: 0
}
});
module.exports = ReactNativeApp;

View File

@@ -1,6 +1,14 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`apis/AppRegistry/renderApplication getApplication 1`] = `
<AppContainer
rootTag={Object {}}
>
<RootComponent />
</AppContainer>
`;
exports[`apis/AppRegistry/renderApplication getApplication 2`] = `
"<style id=\\"react-native-stylesheet-static\\">
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:rgba(0,0,0,0);}
body{margin:0;}
@@ -41,6 +49,7 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-boxSizing-deolkf{box-sizing:border-box}
.rn-display-6koalj{display:-webkit-box;display:-moz-box;display:-ms-flexbox;display:-webkit-flex;display:flex}
.rn-flexShrink-1qe8dj5{-webkit-flex-shrink:0;flex-shrink:0}
.rn-flexShrink-1wbh5a2{-webkit-flex-shrink:1;flex-shrink:1}
.rn-flexBasis-1mlwlqe{-webkit-flex-basis:auto;flex-basis:auto}
.rn-flexDirection-eqz5dr{-webkit-box-direction:normal;-webkit-box-orient:vertical;-webkit-flex-direction:column;flex-direction:column}
.rn-marginTop-1mnahxq{margin-top:0px}
@@ -55,5 +64,6 @@ input::-webkit-inner-spin-button,input::-webkit-outer-spin-button,input::-webkit
.rn-paddingLeft-gy4na3{padding-left:0px}
.rn-zIndex-1lgpqti{z-index:0}
.rn-zIndex-1wyyakw{z-index:-1}
.rn-flexGrow-16y2uox{-webkit-flex-grow:1;flex-grow:1}
</style>"
`;

View File

@@ -3,13 +3,13 @@
import { getApplication } from '../renderApplication';
import React from 'react';
const component = () => <div />;
const RootComponent = () => <div />;
describe('apis/AppRegistry/renderApplication', () => {
test('getApplication', () => {
const { element, stylesheet } = getApplication(component, {});
const { element, stylesheet } = getApplication(RootComponent, {});
expect(element).toBeTruthy();
expect(element).toMatchSnapshot();
expect(stylesheet).toMatchSnapshot();
});
});

View File

@@ -6,7 +6,6 @@
* @flow
*/
import { Component } from 'react';
import invariant from 'fbjs/lib/invariant';
import { unmountComponentAtNode } from 'react-dom';
import renderApplication, { getApplication } from './renderApplication';
@@ -14,9 +13,9 @@ import renderApplication, { getApplication } from './renderApplication';
const emptyObject = {};
const runnables = {};
type ComponentProvider = () => Component<any, any, any>;
export type ComponentProvider = () => ReactClass<any>;
type AppConfig = {
export type AppConfig = {
appKey: string,
component?: ComponentProvider,
run?: Function

View File

@@ -8,25 +8,31 @@
import invariant from 'fbjs/lib/invariant';
import { render } from 'react-dom';
import ReactNativeApp from './ReactNativeApp';
import AppContainer from './AppContainer';
import StyleSheet from '../../apis/StyleSheet';
import React, { Component } from 'react';
import React from 'react';
export default function renderApplication(
RootComponent: Component,
RootComponent: ReactClass<Object>,
initialProps: Object,
rootTag: any
) {
invariant(rootTag, 'Expect to have a valid rootTag, instead got ', rootTag);
const component = (
<ReactNativeApp initialProps={initialProps} rootComponent={RootComponent} rootTag={rootTag} />
render(
<AppContainer rootTag={rootTag}>
<RootComponent {...initialProps} />
</AppContainer>,
rootTag
);
render(component, rootTag);
}
export function getApplication(RootComponent: Component, initialProps: Object): Object {
const element = <ReactNativeApp initialProps={initialProps} rootComponent={RootComponent} />;
export function getApplication(RootComponent: ReactClass<Object>, initialProps: Object): Object {
const element = (
<AppContainer rootTag={{}}>
<RootComponent {...initialProps} />
</AppContainer>
);
const stylesheet = StyleSheet.renderToString();
return { element, stylesheet };
}

View File

@@ -16,30 +16,33 @@ class Clipboard {
static setString(text) {
let success = false;
const body = document.body;
// add the text to a hidden node
const node = document.createElement('span');
node.textContent = text;
node.style.position = 'absolute';
node.style.opacity = '0';
document.body.appendChild(node);
if (body) {
// add the text to a hidden node
const node = document.createElement('span');
node.textContent = text;
node.style.position = 'absolute';
node.style.opacity = '0';
body.appendChild(node);
// select the text
const selection = window.getSelection();
selection.removeAllRanges();
const range = document.createRange();
range.selectNodeContents(node);
selection.addRange(range);
// select the text
const selection = window.getSelection();
selection.removeAllRanges();
const range = document.createRange();
range.selectNodeContents(node);
selection.addRange(range);
// attempt to copy
try {
document.execCommand('copy');
success = true;
} catch (e) {}
// attempt to copy
try {
document.execCommand('copy');
success = true;
} catch (e) {}
// remove selection and node
selection.removeAllRanges();
document.body.removeChild(node);
// remove selection and node
selection.removeAllRanges();
body.removeChild(node);
}
return success;
}

View File

@@ -24,7 +24,9 @@ const isRTL = () => {
const onChange = () => {
if (ExecutionEnvironment.canUseDOM) {
document.documentElement.setAttribute('dir', isRTL() ? 'rtl' : 'ltr');
if (document.documentElement && document.documentElement.setAttribute) {
document.documentElement.setAttribute('dir', isRTL() ? 'rtl' : 'ltr');
}
}
};

View File

@@ -33,19 +33,25 @@ const Linking = {
*/
const iframeOpen = url => {
const noOpener = url.indexOf('mailto:') !== 0;
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
const body = document.body;
if (body) {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
body.appendChild(iframe);
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const script = iframeDoc.createElement('script');
const openerExpression = noOpener ? 'child.opener = null' : '';
script.text = `
window.parent = null; window.top = null; window.frameElement = null;
var child = window.open("${url}"); ${openerExpression};
`;
iframeDoc.body.appendChild(script);
document.body.removeChild(iframe);
const iframeDoc = iframe.contentDocument || iframe.contentWindow.document;
const iframeBody = iframeDoc.body;
if (iframeBody) {
const script = iframeDoc.createElement('script');
const openerExpression = noOpener ? 'child.opener = null' : '';
script.text = `
window.parent = null; window.top = null; window.frameElement = null;
var child = window.open("${url}"); ${openerExpression};
`;
iframeBody.appendChild(script);
}
body.removeChild(iframe);
}
};
module.exports = Linking;

View File

@@ -1,62 +1,68 @@
/* eslint-disable */
/**
* Copyright (c) 2016-present, Nicolas Gallagher.
* Copyright (c) 2015-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 StyleSheetValidation
* @flow
*/
import ImageStylePropTypes from '../../components/Image/ImageStylePropTypes';
import ReactPropTypeLocationNames from '../../vendor/ReactPropTypeLocationNames';
import ReactPropTypesSecret from '../../vendor/ReactPropTypesSecret';
import TextInputStylePropTypes from '../../components/TextInput/TextInputStylePropTypes';
import TextStylePropTypes from '../../components/Text/TextStylePropTypes';
import ViewStylePropTypes from '../../components/View/ViewStylePropTypes';
import warning from 'fbjs/lib/warning';
import { oneOf, string } from 'prop-types';
// Hardcoded because this is a legit case but we don't want to load it from
// a private API. We might likely want to unify style sheet creation with how it
// is done in the DOM so this might move into React. I know what I'm doing so
// plz don't fire me.
const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
class StyleSheetValidation {
static validateStyleProp(prop, style, caller) {
if (process.env.NODE_ENV !== 'production') {
if (allStylePropTypes[prop] === undefined) {
var message1 = '"' + prop + '" is not a valid style property.';
var message2 =
const message1 = '"' + prop + '" is not a valid style property.';
const message2 =
'\nValid style props: ' +
JSON.stringify(Object.keys(allStylePropTypes).sort(), null, ' ');
styleError(message1, style, caller, message2);
} else {
var error = allStylePropTypes[prop](
style,
prop,
caller,
ReactPropTypeLocationNames.prop,
null,
ReactPropTypesSecret
);
if (error) {
styleError(error.message, style, caller);
}
}
const error = allStylePropTypes[prop](
style,
prop,
caller,
'prop',
null,
ReactPropTypesSecret
);
if (error) {
styleError(error.message, style, caller);
}
}
}
static validateStyle(name, styles) {
if (process.env.NODE_ENV !== 'production') {
for (var prop in styles[name]) {
for (const prop in styles[name]) {
StyleSheetValidation.validateStyleProp(prop, styles[name], 'StyleSheet ' + name);
}
}
}
static addValidStylePropTypes(stylePropTypes) {
for (var key in stylePropTypes) {
for (const key in stylePropTypes) {
allStylePropTypes[key] = stylePropTypes[key];
}
}
}
var styleError = function(message1, style, caller?, message2?) {
const styleError = function(message1, style, caller?, message2?) {
warning(
false,
message1 +
@@ -68,7 +74,7 @@ var styleError = function(message1, style, caller?, message2?) {
);
};
var allStylePropTypes = {};
const allStylePropTypes = {};
StyleSheetValidation.addValidStylePropTypes(ImageStylePropTypes);
StyleSheetValidation.addValidStylePropTypes(TextStylePropTypes);

View File

@@ -23,7 +23,7 @@ function getStyle(style) {
}
function flattenStyle(style: ?StyleObj): ?Object {
if (!style) {
if (style == null || typeof style === 'boolean') {
return undefined;
}

View File

@@ -11,6 +11,8 @@ import React, { Component } from 'react';
import { bool, number } from 'prop-types';
class ProgressBar extends Component {
_progressElement = null;
static displayName = 'ProgressBar';
static propTypes = {
@@ -58,17 +60,19 @@ class ProgressBar extends Component {
);
}
_setProgressRef = component => {
this._progressRef = component;
_setProgressRef = element => {
this._progressElement = element;
};
_updateProgressWidth = () => {
const { indeterminate, progress } = this.props;
const percentageProgress = indeterminate ? 50 : progress * 100;
const width = indeterminate ? '25%' : `${percentageProgress}%`;
this._progressRef.setNativeProps({
style: { width }
});
if (this._progressElement) {
this._progressElement.setNativeProps({
style: { width }
});
}
};
}

View File

@@ -18,7 +18,8 @@ const thumbDefaultBoxShadow = '0px 1px 3px rgba(0,0,0,0.5)';
const thumbFocusedBoxShadow = `${thumbDefaultBoxShadow}, 0 0 0 10px rgba(0,0,0,0.1)`;
class Switch extends PureComponent {
_checkbox: HTMLInputElement;
_checkboxElement: HTMLInputElement;
_thumbElement = null;
static displayName = 'Switch';
@@ -44,11 +45,11 @@ class Switch extends PureComponent {
};
blur() {
UIManager.blur(this._checkbox);
UIManager.blur(this._checkboxElement);
}
focus() {
UIManager.focus(this._checkbox);
UIManager.focus(this._checkboxElement);
}
render() {
@@ -136,15 +137,17 @@ class Switch extends PureComponent {
_handleFocusState = (event: Object) => {
const isFocused = event.nativeEvent.type === 'focus';
const boxShadow = isFocused ? thumbFocusedBoxShadow : thumbDefaultBoxShadow;
this._thumb.setNativeProps({ style: { boxShadow } });
if (this._thumbElement) {
this._thumbElement.setNativeProps({ style: { boxShadow } });
}
};
_setCheckboxRef = component => {
this._checkbox = component;
_setCheckboxRef = element => {
this._checkboxElement = element;
};
_setThumbRef = component => {
this._thumb = component;
_setThumbRef = element => {
this._thumbElement = element;
};
}

View File

@@ -82,6 +82,7 @@ const TouchableWithoutFeedback = createReactClass({
* reactivated! Move it back and forth several times while the scroll view
* is disabled. Ensure you pass in a constant to reduce memory allocations.
*/
// $FlowFixMe
pressRetentionOffset: EdgeInsetsPropType,
/**
* This defines how far your touch can start away from the button. This is
@@ -91,6 +92,7 @@ const TouchableWithoutFeedback = createReactClass({
* of sibling views always takes precedence if a touch hits two overlapping
* views.
*/
// $FlowFixMe
hitSlop: EdgeInsetsPropType
},

View File

@@ -1,5 +1,20 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`modules/createDOMElement onClick 1`] = `
Object {
"_normalized": true,
"changedTouches": Array [],
"pageX": undefined,
"pageY": undefined,
"preventDefault": [Function],
"stopImmediatePropagation": [Function],
"stopPropagation": [Function],
"target": undefined,
"timestamp": 1496876171255,
"touches": Array [],
}
`;
exports[`modules/createDOMElement prop "accessibilityLabel" 1`] = `
<span
aria-label="accessibilityLabel"

View File

@@ -1,7 +1,7 @@
/* eslint-env jasmine, jest */
import createDOMElement from '..';
import { render } from 'enzyme';
import { shallow, render } from 'enzyme';
describe('modules/createDOMElement', () => {
test('renders correct DOM element', () => {
@@ -103,6 +103,22 @@ describe('modules/createDOMElement', () => {
expect(component).toMatchSnapshot();
});
test('onClick', done => {
const onClick = e => {
e.nativeEvent.timestamp = 1496876171255;
expect(e.nativeEvent).toMatchSnapshot();
done();
};
const component = shallow(createDOMElement('span', { onClick }));
component.find('span').simulate('click', {
nativeEvent: {
preventDefault() {},
stopImmediatePropagation() {},
stopPropagation() {}
}
});
});
test('prop "testID"', () => {
const component = render(createDOMElement('span', { testID: 'Example.testID' }));
expect(component).toMatchSnapshot();

View File

@@ -44,10 +44,11 @@ const createDOMElement = (component, props) => {
// normalize DOM events to match React Native events
// TODO: move this out of the render path
Object.keys(domProps).forEach(prop => {
const isEventHandler = typeof prop === 'function' && eventHandlerNames[prop];
Object.keys(domProps).forEach(propName => {
const prop = domProps[propName];
const isEventHandler = typeof prop === 'function' && eventHandlerNames[propName];
if (isEventHandler) {
domProps[prop] = wrapEventHandler(prop);
domProps[propName] = wrapEventHandler(prop);
}
});

View File

@@ -1,25 +1,23 @@
/* eslint-disable */
/**
* Copyright (c) 2015-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 ColorPropType
*/
* Copyright (c) 2015-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 ColorPropType
* @flow
*/
var colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
var normalizeColor = require('normalize-css-color');
var ReactPropTypeLocationNames = require('../vendor/ReactPropTypeLocationNames');
var color = props[propName];
const colorPropType = function(isRequired, props, propName, componentName, location, propFullName) {
const normalizeColor = require('normalize-css-color');
const color = props[propName];
if (color === undefined || color === null) {
if (isRequired) {
var locationName = ReactPropTypeLocationNames[location];
return new Error(
'Required ' +
locationName +
location +
' `' +
(propFullName || propName) +
'` was not specified in `' +
@@ -42,10 +40,9 @@ var colorPropType = function(isRequired, props, propName, componentName, locatio
}
if (normalizeColor(color) === null) {
var locationName = ReactPropTypeLocationNames[location];
return new Error(
'Invalid ' +
locationName +
location +
' `' +
(propFullName || propName) +
'` supplied to `' +
@@ -70,11 +67,13 @@ var colorPropType = function(isRequired, props, propName, componentName, locatio
}
};
let ColorPropType;
if (process.env.NODE_ENV !== 'production') {
var ColorPropType = colorPropType.bind(null, false /* isRequired */);
ColorPropType = colorPropType.bind(null, false /* isRequired */);
ColorPropType.isRequired = colorPropType.bind(null, true /* isRequired */);
} else {
var ColorPropType = function() {};
ColorPropType = function() {};
}
module.exports = ColorPropType;

View File

@@ -1,5 +1,3 @@
/* eslint-disable */
/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
@@ -8,29 +6,28 @@
* 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 createStrictShapeTypeChecker
* @flow
*/
import invariant from 'fbjs/lib/invariant';
import ReactPropTypeLocationNames from '../vendor/ReactPropTypeLocationNames';
import ReactPropTypesSecret from '../vendor/ReactPropTypesSecret';
function createStrictShapeTypeChecker(shapeTypes: {
[key: string]: ReactPropsCheckType
}): ReactPropsChainableTypeChecker {
function checkType(isRequired, props, propName, componentName, location?) {
function checkType(isRequired, props, propName, componentName, location?, ...rest) {
if (!props[propName]) {
if (isRequired) {
invariant(
false,
`Required object \`${propName}\` was not specified in ` + `\`${componentName}\`.`
`Required object \`${propName}\` was not specified in \`${componentName}\`.`
);
}
return;
}
var propValue = props[propName];
var propType = typeof propValue;
var locationName = (location && ReactPropTypeLocationNames[location]) || '(unknown)';
const propValue = props[propName];
const propType = typeof propValue;
const locationName = location || '(unknown)';
if (propType !== 'object') {
invariant(
false,
@@ -40,24 +37,24 @@ function createStrictShapeTypeChecker(shapeTypes: {
}
// We need to check all keys in case some are required but missing from
// props.
var allKeys = { ...props[propName], ...shapeTypes };
for (var key in allKeys) {
var checker = shapeTypes[key];
const allKeys = { ...props[propName], ...shapeTypes };
for (const key in allKeys) {
const checker = shapeTypes[key];
if (!checker) {
invariant(
false,
`Invalid props.${propName} key \`${key}\` supplied to \`${componentName}\`.` +
`\nBad object: ` +
'\nBad object: ' +
JSON.stringify(props[propName], null, ' ') +
`\nValid keys: ` +
'\nValid keys: ' +
JSON.stringify(Object.keys(shapeTypes), null, ' ')
);
}
var error = checker(propValue, key, componentName, location, null, ReactPropTypesSecret);
const error = checker(propValue, key, componentName, location, ...rest);
if (error) {
invariant(
false,
error.message + `\nBad object: ` + JSON.stringify(props[propName], null, ' ')
error.message + '\nBad object: ' + JSON.stringify(props[propName], null, ' ')
);
}
}
@@ -66,9 +63,10 @@ function createStrictShapeTypeChecker(shapeTypes: {
props: { [key: string]: any },
propName: string,
componentName: string,
location?: string
location?: string,
...rest
): ?Error {
return checkType(false, props, propName, componentName, location);
return checkType(false, props, propName, componentName, location, ...rest);
}
chainedCheckType.isRequired = checkType.bind(null, true);
return chainedCheckType;

View File

@@ -1,20 +0,0 @@
/**
* 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.
*/
let ReactPropTypeLocationNames = {};
if (process.env.NODE_ENV !== 'production') {
ReactPropTypeLocationNames = {
prop: 'prop',
context: 'context',
childContext: 'child context'
};
}
module.exports = ReactPropTypeLocationNames;

View File

@@ -1,10 +0,0 @@
/**
* 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.
*/
const ReactPropTypesSecret = 'SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED';
module.exports = ReactPropTypesSecret;

View File

@@ -2756,9 +2756,9 @@ flatten@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.2.tgz#dae46a9d78fbe25292258cc1e780a41d95c03782"
flow-bin@^0.46.0:
version "0.46.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.46.0.tgz#06ad7fe19dddb1042264438064a2a32fee12b872"
flow-bin@^0.47.0:
version "0.47.0"
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.47.0.tgz#a2a08ab3e0d1f1cb57d17e27b30b118b62fda367"
flow-parser@0.45.0:
version "0.45.0"