Skip to content

Commit

Permalink
add jsx-runtime and jsx-dev-runtime
Browse files Browse the repository at this point in the history
  • Loading branch information
lunaruan committed Mar 17, 2020
1 parent 0705b72 commit 2b03ad8
Show file tree
Hide file tree
Showing 15 changed files with 915 additions and 208 deletions.
10 changes: 10 additions & 0 deletions packages/react/jsx-dev-runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/

export {Fragment, jsxDEV} from './src/jsx/ReactJSX';
9 changes: 9 additions & 0 deletions packages/react/jsx-runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
*/
export {Fragment, jsx, jsxs} from './src/jsx/ReactJSX';
7 changes: 7 additions & 0 deletions packages/react/npm/jsx-dev-runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-jsx-dev-runtime.production.min.js');
} else {
module.exports = require('./cjs/react-jsx-dev-runtime.development.js');
}
7 changes: 7 additions & 0 deletions packages/react/npm/jsx-runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

if (process.env.NODE_ENV === 'production') {
module.exports = require('./cjs/react-jsx-runtime.production.min.js');
} else {
module.exports = require('./cjs/react-jsx-runtime.development.js');
}
4 changes: 3 additions & 1 deletion packages/react/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
"build-info.json",
"index.js",
"cjs/",
"umd/"
"umd/",
"jsx-runtime.js",
"jsx-dev-runtime.js"
],
"main": "index.js",
"repository": {
Expand Down
11 changes: 1 addition & 10 deletions packages/react/src/React.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
createFactory as createFactoryProd,
cloneElement as cloneElementProd,
isValidElement,
jsx as jsxProd,
} from './ReactElement';
import {createContext} from './ReactContext';
import {lazy} from './ReactLazy';
Expand Down Expand Up @@ -52,27 +51,19 @@ import {
createElementWithValidation,
createFactoryWithValidation,
cloneElementWithValidation,
jsxWithValidation,
jsxWithValidationStatic,
jsxWithValidationDynamic,
} from './ReactElementValidator';
import createMutableSource from './createMutableSource';
import ReactSharedInternals from './ReactSharedInternals';
import createFundamental from 'shared/createFundamentalComponent';
import createResponder from 'shared/createEventResponder';
import createScope from 'shared/createScope';
import {jsx, jsxs, jsxDEV} from './jsx/ReactJSX';

// TODO: Move this branching into the other module instead and just re-export.
const createElement = __DEV__ ? createElementWithValidation : createElementProd;
const cloneElement = __DEV__ ? cloneElementWithValidation : cloneElementProd;
const createFactory = __DEV__ ? createFactoryWithValidation : createFactoryProd;

const jsxDEV = __DEV__ ? jsxWithValidation : undefined;
const jsx = __DEV__ ? jsxWithValidationDynamic : jsxProd;
// we may want to special case jsxs internally to take advantage of static children.
// for now we can ship identical prod functions
const jsxs = __DEV__ ? jsxWithValidationStatic : jsxProd;

const Children = {
map,
forEach,
Expand Down
7 changes: 7 additions & 0 deletions packages/react/src/ReactDebugCurrentFrame.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ export function setCurrentlyValidatingElement(element: null | ReactElement) {
}

if (__DEV__) {
ReactDebugCurrentFrame.setCurrentlyValidatingElement = function(
element: null | ReactElement,
) {
if (__DEV__) {
currentlyValidatingElement = element;
}
};
// Stack implementation injected by the current renderer.
ReactDebugCurrentFrame.getCurrentStack = (null: null | (() => string));

Expand Down
141 changes: 1 addition & 140 deletions packages/react/src/ReactElementValidator.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,10 @@ import {
REACT_FRAGMENT_TYPE,
REACT_ELEMENT_TYPE,
} from 'shared/ReactSymbols';
import {warnAboutSpreadingKeyToJSX} from 'shared/ReactFeatureFlags';
import checkPropTypes from 'shared/checkPropTypes';

import ReactCurrentOwner from './ReactCurrentOwner';
import {
isValidElement,
createElement,
cloneElement,
jsxDEV,
} from './ReactElement';
import {isValidElement, createElement, cloneElement} from './ReactElement';
import {setCurrentlyValidatingElement} from './ReactDebugCurrentFrame';

let propTypesMisspellWarningShown;
Expand All @@ -39,8 +33,6 @@ if (__DEV__) {
propTypesMisspellWarningShown = false;
}

const hasOwnProperty = Object.prototype.hasOwnProperty;

function getDeclarationErrorAddendum() {
if (ReactCurrentOwner.current) {
const name = getComponentName(ReactCurrentOwner.current.type);
Expand Down Expand Up @@ -261,137 +253,6 @@ function validateFragmentProps(fragment) {
}
}

export function jsxWithValidation(
type,
props,
key,
isStaticChildren,
source,
self,
) {
const validType = isValidElementType(type);

// We warn in this case but don't throw. We expect the element creation to
// succeed and there will likely be errors in render.
if (!validType) {
let info = '';
if (
type === undefined ||
(typeof type === 'object' &&
type !== null &&
Object.keys(type).length === 0)
) {
info +=
' You likely forgot to export your component from the file ' +
"it's defined in, or you might have mixed up default and named imports.";
}

const sourceInfo = getSourceInfoErrorAddendum(source);
if (sourceInfo) {
info += sourceInfo;
} else {
info += getDeclarationErrorAddendum();
}

let typeString;
if (type === null) {
typeString = 'null';
} else if (Array.isArray(type)) {
typeString = 'array';
} else if (type !== undefined && type.$$typeof === REACT_ELEMENT_TYPE) {
typeString = `<${getComponentName(type.type) || 'Unknown'} />`;
info =
' Did you accidentally export a JSX literal instead of a component?';
} else {
typeString = typeof type;
}

if (__DEV__) {
console.error(
'React.jsx: type is invalid -- expected a string (for ' +
'built-in components) or a class/function (for composite ' +
'components) but got: %s.%s',
typeString,
info,
);
}
}

const element = jsxDEV(type, props, key, source, self);

// The result can be nullish if a mock or a custom function is used.
// TODO: Drop this when these are no longer allowed as the type argument.
if (element == null) {
return 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.
// (Rendering will throw with a helpful message and as soon as the type is
// fixed, the key warnings will appear.)

if (validType) {
const children = props.children;
if (children !== undefined) {
if (isStaticChildren) {
if (Array.isArray(children)) {
for (let i = 0; i < children.length; i++) {
validateChildKeys(children[i], type);
}

if (Object.freeze) {
Object.freeze(children);
}
} else {
if (__DEV__) {
console.error(
'React.jsx: Static children should always be an array. ' +
'You are likely explicitly calling React.jsxs or React.jsxDEV. ' +
'Use the Babel transform instead.',
);
}
}
} else {
validateChildKeys(children, type);
}
}
}

if (__DEV__) {
if (warnAboutSpreadingKeyToJSX) {
if (hasOwnProperty.call(props, 'key')) {
console.error(
'React.jsx: Spreading a key to JSX is a deprecated pattern. ' +
'Explicitly pass a key after spreading props in your JSX call. ' +
'E.g. <%s {...props} key={key} />',
getComponentName(type) || 'ComponentName',
);
}
}
}

if (type === REACT_FRAGMENT_TYPE) {
validateFragmentProps(element);
} else {
validatePropTypes(element);
}

return element;
}

// These two functions exist to still get child warnings in dev
// even with the prod transform. This means that jsxDEV is purely
// opt-in behavior for better messages but that we won't stop
// giving you warnings if you use production apis.
export function jsxWithValidationStatic(type, props, key) {
return jsxWithValidation(type, props, key, true);
}

export function jsxWithValidationDynamic(type, props, key) {
return jsxWithValidation(type, props, key, false);
}

export function createElementWithValidation(type, props, children) {
const validType = isValidElementType(type);

Expand Down
Loading

0 comments on commit 2b03ad8

Please sign in to comment.