Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide new jsx transform target for reactjs/rfcs#107 #15141

Merged
merged 3 commits into from
Apr 7, 2019
Merged
Show file tree
Hide file tree
Changes from 2 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
22 changes: 21 additions & 1 deletion packages/react/src/React.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
createFactory,
cloneElement,
isValidElement,
jsx,
} from './ReactElement';
import {createContext} from './ReactContext';
import {lazy} from './ReactLazy';
Expand All @@ -43,10 +44,16 @@ import {
createElementWithValidation,
createFactoryWithValidation,
cloneElementWithValidation,
jsxWithValidation,
jsxWithValidationStatic,
jsxWithValidationDynamic,
} from './ReactElementValidator';
import ReactSharedInternals from './ReactSharedInternals';
import {error, warn} from './withComponentStack';
import {enableStableConcurrentModeAPIs} from 'shared/ReactFeatureFlags';
import {
enableStableConcurrentModeAPIs,
enableJSXTransformAPI,
} from 'shared/ReactFeatureFlags';

const React = {
Children: {
Expand Down Expand Up @@ -107,4 +114,17 @@ if (enableStableConcurrentModeAPIs) {
React.unstable_ConcurrentMode = undefined;
}

if (enableJSXTransformAPI) {
if (__DEV__) {
React.jsxDEV = jsxWithValidation;
React.jsx = jsxWithValidationDynamic;
React.jsxs = jsxWithValidationStatic;
} else {
React.jsx = jsx;
// we may want to special case jsxs internally to take advantage of static children.
// for now we can ship identical prod functions
React.jsxs = jsx;
}
}

export default React;
141 changes: 133 additions & 8 deletions packages/react/src/ReactElement.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,20 +95,20 @@ function defineRefPropWarningGetter(props, displayName) {
* if something is a React Element.
*
* @param {*} type
* @param {*} props
* @param {*} key
* @param {string|object} ref
* @param {*} owner
* @param {*} self A *temporary* helper to detect places where `this` is
* different from the `owner` when React.createElement is called, so that we
* can warn. We want to get rid of owner and replace string `ref`s with arrow
* functions, and as long as `this` and owner are the same, there will be no
* change in behavior.
* @param {*} source An annotation object (added by a transpiler or otherwise)
* indicating filename, line number, and/or other information.
* @param {*} owner
* @param {*} props
* @internal
*/
const ReactElement = function(type, key, ref, self, source, owner, props) {
const ReactElement = function(type, props, key, ref, owner, self, source) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok, so I downloaded the artifacts. Somehow, this is not getting inlined anymore. That's why the file increases.

I'm not sure if it's called in more places and maybe it stops trying to inline it before it's able DCE the other paths.

It could also be the argument order. You could try restoring the argument order. It might have an effect on the compiler since the property reads of mutable values are not pure operations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hey looks like reordering fixes it! Wild. Now there is only a size regression on WWW prod which is to be expected since the feature is turned on there.

const element = {
// This tag allows us to uniquely identify this as a React Element
$$typeof: REACT_ELEMENT_TYPE,
Expand Down Expand Up @@ -164,6 +164,131 @@ const ReactElement = function(type, key, ref, self, source, owner, props) {
return element;
};

/**
* https://github.com/reactjs/rfcs/pull/107
* @param {*} type
* @param {object} props
* @param {string} key
*/
export function jsx(type, config, maybeKey) {
let propName;

// Reserved names are extracted
const props = {};

let key = null;
let ref = null;

if (hasValidRef(config)) {
ref = config.ref;
}

if (hasValidKey(config)) {
key = '' + config.key;
}

// Remaining properties are added to a new props object
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}

// intentionally not checking if key was set above
// this key is higher priority as it's static
if (maybeKey !== undefined) {
key = '' + maybeKey;
}

// Resolve default props
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}

return ReactElement(type, props, key, ref, ReactCurrentOwner.current);
}

/**
* https://github.com/reactjs/rfcs/pull/107
* @param {*} type
* @param {object} props
* @param {string} key
*/
export function jsxDEV(type, config, maybeKey, source, self) {
let propName;

// Reserved names are extracted
const props = {};

let key = null;
let ref = null;

if (hasValidRef(config)) {
ref = config.ref;
}

if (hasValidKey(config)) {
key = '' + config.key;
}

// Remaining properties are added to a new props object
for (propName in config) {
if (
hasOwnProperty.call(config, propName) &&
!RESERVED_PROPS.hasOwnProperty(propName)
) {
props[propName] = config[propName];
}
}

// intentionally not checking if key was set above
// this key is higher priority as it's static
if (maybeKey !== undefined) {
key = '' + maybeKey;
}

// Resolve default props
if (type && type.defaultProps) {
const defaultProps = type.defaultProps;
for (propName in defaultProps) {
if (props[propName] === undefined) {
props[propName] = defaultProps[propName];
}
}
}

if (key || ref) {
const displayName =
typeof type === 'function'
? type.displayName || type.name || 'Unknown'
: type;
if (key) {
defineKeyPropWarningGetter(props, displayName);
}
if (ref) {
defineRefPropWarningGetter(props, displayName);
}
}

return ReactElement(
type,
props,
key,
ref,
ReactCurrentOwner.current,
self,
source,
);
}

/**
* Create and return a new ReactElement of the given type.
* See https://reactjs.org/docs/react-api.html#createelement
Expand Down Expand Up @@ -243,12 +368,12 @@ export function createElement(type, config, children) {
}
return ReactElement(
type,
props,
key,
ref,
ReactCurrentOwner.current,
self,
source,
ReactCurrentOwner.current,
props,
);
}

Expand All @@ -270,12 +395,12 @@ export function createFactory(type) {
export function cloneAndReplaceKey(oldElement, newKey) {
const newElement = ReactElement(
oldElement.type,
oldElement.props,
newKey,
oldElement.ref,
oldElement._owner,
oldElement._self,
oldElement._source,
oldElement._owner,
oldElement.props,
);

return newElement;
Expand Down Expand Up @@ -353,7 +478,7 @@ export function cloneElement(element, config, children) {
props.children = childArray;
}

return ReactElement(element.type, key, ref, self, source, owner, props);
return ReactElement(element.type, props, key, ref, owner, self, source);
}

/**
Expand Down
Loading