From c4e657ff430bdadb5caa43c9d4603fe410c93da4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Paul=20O=E2=80=99Shannessy?= Date: Fri, 1 Apr 2016 16:33:42 -0700 Subject: [PATCH] Use Object.assign directly and inject object-assign at compile --- .babelrc | 3 +- gulpfile.js | 2 +- .../babel/transform-object-assign-require.js | 40 +++++++++++++++++++ scripts/jest/preprocessor.js | 2 +- .../transitions/ReactCSSTransitionGroup.js | 4 +- .../transitions/ReactTransitionGroup.js | 3 +- src/addons/update.js | 5 +-- src/isomorphic/React.js | 3 +- src/isomorphic/classic/class/ReactClass.js | 9 ++--- .../classic/element/ReactElement.js | 3 +- src/isomorphic/deprecated/OrderedMap.js | 3 +- .../deprecated/ReactPropTransferer.js | 5 +-- .../dom/client/ReactBrowserEventEmitter.js | 3 +- .../dom/client/ReactEventListener.js | 3 +- .../dom/client/ReactReconcileTransaction.js | 3 +- .../eventPlugins/FallbackCompositionState.js | 3 +- .../client/syntheticEvents/SyntheticEvent.js | 7 ++-- .../dom/client/validateDOMNesting.js | 3 +- .../dom/client/wrappers/ReactDOMInput.js | 3 +- .../dom/client/wrappers/ReactDOMOption.js | 3 +- .../dom/client/wrappers/ReactDOMSelect.js | 3 +- .../dom/client/wrappers/ReactDOMTextarea.js | 3 +- .../server/ReactServerRenderingTransaction.js | 3 +- src/renderers/dom/shared/ReactDOMComponent.js | 9 ++--- .../dom/shared/ReactDOMEmptyComponent.js | 3 +- .../dom/shared/ReactDOMTextComponent.js | 3 +- .../__tests__/ReactDOMComponent-test.js | 5 +-- .../__tests__/EventPluginRegistry-test.js | 3 +- .../reconciler/ReactCompositeComponent.js | 7 ++-- .../ReactDefaultBatchingStrategy.js | 3 +- .../shared/reconciler/ReactNativeComponent.js | 3 +- .../reconciler/ReactSimpleEmptyComponent.js | 3 +- .../shared/reconciler/ReactUpdates.js | 3 +- .../reconciler/instantiateReactComponent.js | 3 +- src/shared/utils/CallbackQueue.js | 3 +- .../utils/__tests__/Transaction-test.js | 13 +++--- src/shared/utils/deprecated.js | 3 +- src/test/ReactDefaultPerfAnalysis.js | 7 ++-- src/test/ReactTestUtils.js | 7 ++-- src/test/reactComponentExpect.js | 3 +- src/umd/ReactUMDEntry.js | 3 +- src/umd/ReactWithAddonsUMDEntry.js | 3 +- 42 files changed, 104 insertions(+), 102 deletions(-) create mode 100644 scripts/babel/transform-object-assign-require.js diff --git a/.babelrc b/.babelrc index 8eb255a729f00..73803b050c24c 100644 --- a/.babelrc +++ b/.babelrc @@ -20,6 +20,7 @@ "transform-es2015-block-scoping", "transform-es2015-modules-commonjs", "transform-es3-member-expression-literals", - "transform-es3-property-literals" + "transform-es3-property-literals", + "./scripts/babel/transform-object-assign-require" ] } diff --git a/gulpfile.js b/gulpfile.js index 21bd6c5d11c1b..f885ea349a670 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -35,7 +35,7 @@ var babelOpts = { {}, require('fbjs/module-map'), { - 'Object.assign': 'object-assign', + 'object-assign': 'object-assign', } ), }], diff --git a/scripts/babel/transform-object-assign-require.js b/scripts/babel/transform-object-assign-require.js new file mode 100644 index 0000000000000..dc1dfebd2dd86 --- /dev/null +++ b/scripts/babel/transform-object-assign-require.js @@ -0,0 +1,40 @@ +/** + * 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. + */ + +'use strict'; + +module.exports = function autoImporter(babel) { + const t = babel.types; + + return { + pre: function() { + // map from module to generated identifier + this.id = null; + }, + + visitor: { + CallExpression: function (path, file) { + if (path.get("callee").matchesPattern("Object.assign")) { + // generate identifier and require if it hasn't been already + if (!this.id) { + this.id = path.scope.generateUidIdentifier('assign'); + path.scope.getProgramParent().push({ + id: this.id, + init: t.callExpression( + t.identifier('require'), + [t.stringLiteral('object-assign')] + ), + }); + } + path.node.callee = this.id; + } + }, + }, + }; +}; diff --git a/scripts/jest/preprocessor.js b/scripts/jest/preprocessor.js index ab2141e8eaed2..29f0d03b06979 100644 --- a/scripts/jest/preprocessor.js +++ b/scripts/jest/preprocessor.js @@ -32,7 +32,7 @@ var babelOptions = { {}, moduleMap, { - 'Object.assign': 'object-assign', + 'object-assign': 'object-assign', } ), }], diff --git a/src/addons/transitions/ReactCSSTransitionGroup.js b/src/addons/transitions/ReactCSSTransitionGroup.js index 532018847aaf1..4177ec790b2e8 100644 --- a/src/addons/transitions/ReactCSSTransitionGroup.js +++ b/src/addons/transitions/ReactCSSTransitionGroup.js @@ -13,8 +13,6 @@ var React = require('React'); -var assign = require('Object.assign'); - var ReactTransitionGroup = require('ReactTransitionGroup'); var ReactCSSTransitionGroupChild = require('ReactCSSTransitionGroupChild'); @@ -87,7 +85,7 @@ var ReactCSSTransitionGroup = React.createClass({ render: function() { return React.createElement( ReactTransitionGroup, - assign({}, this.props, {childFactory: this._wrapChild}) + Object.assign({}, this.props, {childFactory: this._wrapChild}) ); }, }); diff --git a/src/addons/transitions/ReactTransitionGroup.js b/src/addons/transitions/ReactTransitionGroup.js index 816edfacc57a5..6d6df1a80b608 100644 --- a/src/addons/transitions/ReactTransitionGroup.js +++ b/src/addons/transitions/ReactTransitionGroup.js @@ -14,7 +14,6 @@ var React = require('React'); var ReactTransitionChildMapping = require('ReactTransitionChildMapping'); -var assign = require('Object.assign'); var emptyFunction = require('emptyFunction'); var ReactTransitionGroup = React.createClass({ @@ -193,7 +192,7 @@ var ReactTransitionGroup = React.createClass({ this.performEnter(key); } else { this.setState(function(state) { - var newChildren = assign({}, state.children); + var newChildren = Object.assign({}, state.children); delete newChildren[key]; return {children: newChildren}; }); diff --git a/src/addons/update.js b/src/addons/update.js index 7c8ba4e3b1dbb..cc2434e2bd309 100644 --- a/src/addons/update.js +++ b/src/addons/update.js @@ -13,7 +13,6 @@ 'use strict'; -var assign = require('Object.assign'); var keyOf = require('keyOf'); var invariant = require('invariant'); var hasOwnProperty = {}.hasOwnProperty; @@ -22,7 +21,7 @@ function shallowCopy(x) { if (Array.isArray(x)) { return x.concat(); } else if (x && typeof x === 'object') { - return assign(new x.constructor(), x); + return Object.assign(new x.constructor(), x); } else { return x; } @@ -102,7 +101,7 @@ function update(value, spec) { COMMAND_MERGE, nextValue ); - assign(nextValue, spec[COMMAND_MERGE]); + Object.assign(nextValue, spec[COMMAND_MERGE]); } if (hasOwnProperty.call(spec, COMMAND_PUSH)) { diff --git a/src/isomorphic/React.js b/src/isomorphic/React.js index 5037feb7a4a67..37109d6ea13f0 100644 --- a/src/isomorphic/React.js +++ b/src/isomorphic/React.js @@ -20,7 +20,6 @@ var ReactElementValidator = require('ReactElementValidator'); var ReactPropTypes = require('ReactPropTypes'); var ReactVersion = require('ReactVersion'); -var assign = require('Object.assign'); var onlyChild = require('onlyChild'); var createElement = ReactElement.createElement; @@ -68,7 +67,7 @@ var React = { version: ReactVersion, // Hook for JSX spread, don't use this for anything else. - __spread: assign, + __spread: Object.assign, }; module.exports = React; diff --git a/src/isomorphic/classic/class/ReactClass.js b/src/isomorphic/classic/class/ReactClass.js index 8a2a6f30dd515..56f479a42e991 100644 --- a/src/isomorphic/classic/class/ReactClass.js +++ b/src/isomorphic/classic/class/ReactClass.js @@ -17,7 +17,6 @@ var ReactPropTypeLocations = require('ReactPropTypeLocations'); var ReactPropTypeLocationNames = require('ReactPropTypeLocationNames'); var ReactNoopUpdateQueue = require('ReactNoopUpdateQueue'); -var assign = require('Object.assign'); var emptyObject = require('emptyObject'); var invariant = require('invariant'); var keyMirror = require('keyMirror'); @@ -331,7 +330,7 @@ var RESERVED_SPEC_KEYS = { ReactPropTypeLocations.childContext ); } - Constructor.childContextTypes = assign( + Constructor.childContextTypes = Object.assign( {}, Constructor.childContextTypes, childContextTypes @@ -345,7 +344,7 @@ var RESERVED_SPEC_KEYS = { ReactPropTypeLocations.context ); } - Constructor.contextTypes = assign( + Constructor.contextTypes = Object.assign( {}, Constructor.contextTypes, contextTypes @@ -373,7 +372,7 @@ var RESERVED_SPEC_KEYS = { ReactPropTypeLocations.prop ); } - Constructor.propTypes = assign( + Constructor.propTypes = Object.assign( {}, Constructor.propTypes, propTypes @@ -726,7 +725,7 @@ var ReactClassMixin = { }; var ReactClassComponent = function() {}; -assign( +Object.assign( ReactClassComponent.prototype, ReactComponent.prototype, ReactClassMixin diff --git a/src/isomorphic/classic/element/ReactElement.js b/src/isomorphic/classic/element/ReactElement.js index 6e371596d06d1..ee46a5f392dbb 100644 --- a/src/isomorphic/classic/element/ReactElement.js +++ b/src/isomorphic/classic/element/ReactElement.js @@ -13,7 +13,6 @@ var ReactCurrentOwner = require('ReactCurrentOwner'); -var assign = require('Object.assign'); var warning = require('warning'); var canDefineProperty = require('canDefineProperty'); @@ -253,7 +252,7 @@ ReactElement.cloneElement = function(element, config, children) { var propName; // Original props are copied - var props = assign({}, element.props); + var props = Object.assign({}, element.props); // Reserved names are extracted var key = element.key; diff --git a/src/isomorphic/deprecated/OrderedMap.js b/src/isomorphic/deprecated/OrderedMap.js index 92cea05f828dd..4336cdc384495 100644 --- a/src/isomorphic/deprecated/OrderedMap.js +++ b/src/isomorphic/deprecated/OrderedMap.js @@ -11,7 +11,6 @@ 'use strict'; -var assign = require('Object.assign'); var invariant = require('invariant'); var PREFIX = 'key:'; @@ -475,7 +474,7 @@ var OrderedMapMethods = { }, }; -assign(OrderedMapImpl.prototype, OrderedMapMethods); +Object.assign(OrderedMapImpl.prototype, OrderedMapMethods); var OrderedMap = { from: function(orderedMap) { diff --git a/src/isomorphic/deprecated/ReactPropTransferer.js b/src/isomorphic/deprecated/ReactPropTransferer.js index b3e2a8269d32c..da009cafe0acd 100644 --- a/src/isomorphic/deprecated/ReactPropTransferer.js +++ b/src/isomorphic/deprecated/ReactPropTransferer.js @@ -11,7 +11,6 @@ 'use strict'; -var assign = require('Object.assign'); var emptyFunction = require('emptyFunction'); var joinClasses = require('joinClasses'); @@ -36,7 +35,7 @@ var transferStrategyMerge = createTransferStrategy(function(a, b) { // `merge` overrides the first object's (`props[key]` above) keys using the // second object's (`value`) keys. An object's style's existing `propA` would // get overridden. Flip the order here. - return assign({}, b, a); + return Object.assign({}, b, a); }); /** @@ -100,7 +99,7 @@ var ReactPropTransferer = { * @return {object} a new object containing both sets of props merged. */ mergeProps: function(oldProps, newProps) { - return transferInto(assign({}, oldProps), newProps); + return transferInto(Object.assign({}, oldProps), newProps); }, }; diff --git a/src/renderers/dom/client/ReactBrowserEventEmitter.js b/src/renderers/dom/client/ReactBrowserEventEmitter.js index 5f5dc8d267e54..dd7334f48463b 100644 --- a/src/renderers/dom/client/ReactBrowserEventEmitter.js +++ b/src/renderers/dom/client/ReactBrowserEventEmitter.js @@ -16,7 +16,6 @@ var EventPluginRegistry = require('EventPluginRegistry'); var ReactEventEmitterMixin = require('ReactEventEmitterMixin'); var ViewportMetrics = require('ViewportMetrics'); -var assign = require('Object.assign'); var getVendorPrefixedEventName = require('getVendorPrefixedEventName'); var isEventSupported = require('isEventSupported'); @@ -175,7 +174,7 @@ function getListeningForDocument(mountAt) { * * @internal */ -var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, { +var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, { /** * Injectable event backend diff --git a/src/renderers/dom/client/ReactEventListener.js b/src/renderers/dom/client/ReactEventListener.js index 1d69e02086df4..bbdbbcf29115e 100644 --- a/src/renderers/dom/client/ReactEventListener.js +++ b/src/renderers/dom/client/ReactEventListener.js @@ -17,7 +17,6 @@ var PooledClass = require('PooledClass'); var ReactDOMComponentTree = require('ReactDOMComponentTree'); var ReactUpdates = require('ReactUpdates'); -var assign = require('Object.assign'); var getEventTarget = require('getEventTarget'); var getUnboundedScrollPosition = require('getUnboundedScrollPosition'); @@ -44,7 +43,7 @@ function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) { this.nativeEvent = nativeEvent; this.ancestors = []; } -assign(TopLevelCallbackBookKeeping.prototype, { +Object.assign(TopLevelCallbackBookKeeping.prototype, { destructor: function() { this.topLevelType = null; this.nativeEvent = null; diff --git a/src/renderers/dom/client/ReactReconcileTransaction.js b/src/renderers/dom/client/ReactReconcileTransaction.js index 1835a2dbbc74f..fedd883bf1cb9 100644 --- a/src/renderers/dom/client/ReactReconcileTransaction.js +++ b/src/renderers/dom/client/ReactReconcileTransaction.js @@ -17,7 +17,6 @@ var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter'); var ReactInputSelection = require('ReactInputSelection'); var Transaction = require('Transaction'); -var assign = require('Object.assign'); /** * Ensures that, when possible, the selection range (currently selected text @@ -160,7 +159,7 @@ var Mixin = { }; -assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin); +Object.assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin); PooledClass.addPoolingTo(ReactReconcileTransaction); diff --git a/src/renderers/dom/client/eventPlugins/FallbackCompositionState.js b/src/renderers/dom/client/eventPlugins/FallbackCompositionState.js index 68c12841e02a7..e26e259a0f125 100644 --- a/src/renderers/dom/client/eventPlugins/FallbackCompositionState.js +++ b/src/renderers/dom/client/eventPlugins/FallbackCompositionState.js @@ -13,7 +13,6 @@ var PooledClass = require('PooledClass'); -var assign = require('Object.assign'); var getTextContentAccessor = require('getTextContentAccessor'); /** @@ -33,7 +32,7 @@ function FallbackCompositionState(root) { this._fallbackText = null; } -assign(FallbackCompositionState.prototype, { +Object.assign(FallbackCompositionState.prototype, { destructor: function() { this._root = null; this._startText = null; diff --git a/src/renderers/dom/client/syntheticEvents/SyntheticEvent.js b/src/renderers/dom/client/syntheticEvents/SyntheticEvent.js index daad64d18e2cb..d3cdf3c399d3c 100644 --- a/src/renderers/dom/client/syntheticEvents/SyntheticEvent.js +++ b/src/renderers/dom/client/syntheticEvents/SyntheticEvent.js @@ -13,7 +13,6 @@ var PooledClass = require('PooledClass'); -var assign = require('Object.assign'); var emptyFunction = require('emptyFunction'); var warning = require('warning'); @@ -111,7 +110,7 @@ function SyntheticEvent(dispatchConfig, targetInst, nativeEvent, nativeEventTarg return this; } -assign(SyntheticEvent.prototype, { +Object.assign(SyntheticEvent.prototype, { preventDefault: function() { this.defaultPrevented = true; @@ -229,11 +228,11 @@ SyntheticEvent.augmentClass = function(Class, Interface) { E.prototype = Super.prototype; var prototype = new E(); - assign(prototype, Class.prototype); + Object.assign(prototype, Class.prototype); Class.prototype = prototype; Class.prototype.constructor = Class; - Class.Interface = assign({}, Super.Interface, Interface); + Class.Interface = Object.assign({}, Super.Interface, Interface); Class.augmentClass = Super.augmentClass; PooledClass.addPoolingTo(Class, PooledClass.fourArgumentPooler); diff --git a/src/renderers/dom/client/validateDOMNesting.js b/src/renderers/dom/client/validateDOMNesting.js index d479ea9af9a44..431d80fd2d5db 100644 --- a/src/renderers/dom/client/validateDOMNesting.js +++ b/src/renderers/dom/client/validateDOMNesting.js @@ -11,7 +11,6 @@ 'use strict'; -var assign = require('Object.assign'); var emptyFunction = require('emptyFunction'); var warning = require('warning'); @@ -76,7 +75,7 @@ if (__DEV__) { }; var updatedAncestorInfo = function(oldInfo, tag, instance) { - var ancestorInfo = assign({}, oldInfo || emptyAncestorInfo); + var ancestorInfo = Object.assign({}, oldInfo || emptyAncestorInfo); var info = {tag: tag, instance: instance}; if (inScopeTags.indexOf(tag) !== -1) { diff --git a/src/renderers/dom/client/wrappers/ReactDOMInput.js b/src/renderers/dom/client/wrappers/ReactDOMInput.js index e52c199b24a15..e9cd9b541ad91 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMInput.js +++ b/src/renderers/dom/client/wrappers/ReactDOMInput.js @@ -16,7 +16,6 @@ var LinkedValueUtils = require('LinkedValueUtils'); var ReactDOMComponentTree = require('ReactDOMComponentTree'); var ReactUpdates = require('ReactUpdates'); -var assign = require('Object.assign'); var invariant = require('invariant'); var warning = require('warning'); @@ -69,7 +68,7 @@ var ReactDOMInput = { var value = LinkedValueUtils.getValue(props); var checked = LinkedValueUtils.getChecked(props); - var nativeProps = assign({ + var nativeProps = Object.assign({ // Make sure we set .type before any other properties (setting .value // before .type means .value is lost in IE11 and below) type: undefined, diff --git a/src/renderers/dom/client/wrappers/ReactDOMOption.js b/src/renderers/dom/client/wrappers/ReactDOMOption.js index 31e605003027e..917ed0ee4a167 100644 --- a/src/renderers/dom/client/wrappers/ReactDOMOption.js +++ b/src/renderers/dom/client/wrappers/ReactDOMOption.js @@ -14,7 +14,6 @@ var ReactChildren = require('ReactChildren'); var ReactDOMSelect = require('ReactDOMSelect'); -var assign = require('Object.assign'); var warning = require('warning'); /** @@ -59,7 +58,7 @@ var ReactDOMOption = { }, getNativeProps: function(inst, props) { - var nativeProps = assign({selected: undefined, children: undefined}, props); + var nativeProps = Object.assign({selected: undefined, children: undefined}, props); // Read state only from initial mount because