Skip to content

Commit

Permalink
Hide Object.assign polyfill behind a module
Browse files Browse the repository at this point in the history
Because the JS community's polyfilling infrastructure sucks and we'll
have to fix it for them before we require this.

JSX spread uses React.__spread
(which might get special behavior for key/ref, not sure yet)

This never uses the native implementation and throws for prototype chains.
Once the native implementations are faster, we'll start using them.
  • Loading branch information
sebmarkbage committed Oct 16, 2014
1 parent 5263f61 commit 8210bee
Show file tree
Hide file tree
Showing 41 changed files with 182 additions and 128 deletions.
2 changes: 0 additions & 2 deletions jest/environment.js
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
__DEV__ = true;

require.requireActual('../src/vendor/polyfill/Object.es6.js');
4 changes: 3 additions & 1 deletion src/addons/transitions/ReactCSSTransitionGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

var React = require('React');

var assign = require('Object.assign');

var ReactTransitionGroup = React.createFactory(
require('ReactTransitionGroup')
);
Expand Down Expand Up @@ -54,7 +56,7 @@ var ReactCSSTransitionGroup = React.createClass({
render: function() {
return (
ReactTransitionGroup(
Object.assign({}, this.props, {childFactory: this._wrapChild})
assign({}, this.props, {childFactory: this._wrapChild})
)
);
}
Expand Down
3 changes: 2 additions & 1 deletion src/addons/transitions/ReactTransitionGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
var React = require('React');
var ReactTransitionChildMapping = require('ReactTransitionChildMapping');

var assign = require('Object.assign');
var cloneWithProps = require('cloneWithProps');
var emptyFunction = require('emptyFunction');

Expand Down Expand Up @@ -151,7 +152,7 @@ var ReactTransitionGroup = React.createClass({
// This entered again before it fully left. Add it again.
this.performEnter(key);
} else {
var newChildren = Object.assign({}, this.state.children);
var newChildren = assign({}, this.state.children);
delete newChildren[key];
this.setState({children: newChildren});
}
Expand Down
5 changes: 3 additions & 2 deletions src/addons/update.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@

"use strict";

var assign = require('Object.assign');
var keyOf = require('keyOf');
var invariant = require('invariant');

function shallowCopy(x) {
if (Array.isArray(x)) {
return x.concat();
} else if (x && typeof x === 'object') {
return Object.assign(new x.constructor(), x);
return assign(new x.constructor(), x);
} else {
return x;
}
Expand Down Expand Up @@ -98,7 +99,7 @@ function update(value, spec) {
COMMAND_MERGE,
nextValue
);
Object.assign(nextValue, spec[COMMAND_MERGE]);
assign(nextValue, spec[COMMAND_MERGE]);
}

if (spec.hasOwnProperty(COMMAND_PUSH)) {
Expand Down
3 changes: 2 additions & 1 deletion src/browser/ReactBrowserEventEmitter.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var EventPluginRegistry = require('EventPluginRegistry');
var ReactEventEmitterMixin = require('ReactEventEmitterMixin');
var ViewportMetrics = require('ViewportMetrics');

var assign = require('Object.assign');
var isEventSupported = require('isEventSupported');

/**
Expand Down Expand Up @@ -147,7 +148,7 @@ function getListeningForDocument(mountAt) {
*
* @internal
*/
var ReactBrowserEventEmitter = Object.assign({}, ReactEventEmitterMixin, {
var ReactBrowserEventEmitter = assign({}, ReactEventEmitterMixin, {

/**
* Injectable event backend
Expand Down
4 changes: 3 additions & 1 deletion src/browser/ReactPutListenerQueue.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
var PooledClass = require('PooledClass');
var ReactBrowserEventEmitter = require('ReactBrowserEventEmitter');

var assign = require('Object.assign');

function ReactPutListenerQueue() {
this.listenersToPut = [];
}

Object.assign(ReactPutListenerQueue.prototype, {
assign(ReactPutListenerQueue.prototype, {
enqueuePutListener: function(rootNodeID, propKey, propValue) {
this.listenersToPut.push({
rootNodeID: rootNodeID,
Expand Down
4 changes: 3 additions & 1 deletion src/browser/ReactReconcileTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ var ReactInputSelection = require('ReactInputSelection');
var ReactPutListenerQueue = require('ReactPutListenerQueue');
var Transaction = require('Transaction');

var assign = require('Object.assign');

/**
* Ensures that, when possible, the selection range (currently selected text
* input) is not disturbed by performing the transaction.
Expand Down Expand Up @@ -165,7 +167,7 @@ var Mixin = {
};


Object.assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);
assign(ReactReconcileTransaction.prototype, Transaction.Mixin, Mixin);

PooledClass.addPoolingTo(ReactReconcileTransaction);

Expand Down
3 changes: 2 additions & 1 deletion src/browser/ReactTextComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ var DOMPropertyOperations = require('DOMPropertyOperations');
var ReactComponent = require('ReactComponent');
var ReactElement = require('ReactElement');

var assign = require('Object.assign');
var escapeTextForBrowser = require('escapeTextForBrowser');

/**
Expand All @@ -37,7 +38,7 @@ var ReactTextComponent = function(props) {
// This constructor and it's argument is currently used by mocks.
};

Object.assign(ReactTextComponent.prototype, ReactComponent.Mixin, {
assign(ReactTextComponent.prototype, ReactComponent.Mixin, {

/**
* Creates the markup for this text node. This node is not intended to have
Expand Down
3 changes: 2 additions & 1 deletion src/browser/server/ReactServerRenderingTransaction.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ var CallbackQueue = require('CallbackQueue');
var ReactPutListenerQueue = require('ReactPutListenerQueue');
var Transaction = require('Transaction');

var assign = require('Object.assign');
var emptyFunction = require('emptyFunction');

/**
Expand Down Expand Up @@ -99,7 +100,7 @@ var Mixin = {
};


Object.assign(
assign(
ReactServerRenderingTransaction.prototype,
Transaction.Mixin,
Mixin
Expand Down
7 changes: 4 additions & 3 deletions src/browser/syntheticEvents/SyntheticEvent.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

var PooledClass = require('PooledClass');

var assign = require('Object.assign');
var emptyFunction = require('emptyFunction');
var getEventTarget = require('getEventTarget');

Expand Down Expand Up @@ -82,7 +83,7 @@ function SyntheticEvent(dispatchConfig, dispatchMarker, nativeEvent) {
this.isPropagationStopped = emptyFunction.thatReturnsFalse;
}

Object.assign(SyntheticEvent.prototype, {
assign(SyntheticEvent.prototype, {

preventDefault: function() {
this.defaultPrevented = true;
Expand Down Expand Up @@ -140,11 +141,11 @@ SyntheticEvent.augmentClass = function(Class, Interface) {
var Super = this;

var prototype = Object.create(Super.prototype);
Object.assign(prototype, Class.prototype);
assign(prototype, Class.prototype);
Class.prototype = prototype;
Class.prototype.constructor = Class;

Class.Interface = Object.assign({}, Super.Interface, Interface);
Class.Interface = assign({}, Super.Interface, Interface);
Class.augmentClass = Super.augmentClass;

PooledClass.addPoolingTo(Class, PooledClass.threeArgumentPooler);
Expand Down
8 changes: 4 additions & 4 deletions src/browser/ui/React.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@

"use strict";

// TODO: Move this elsewhere - it only exists in open source until a better
// solution is found.
require('Object.es6');

var DOMPropertyOperations = require('DOMPropertyOperations');
var EventPluginUtils = require('EventPluginUtils');
var ReactChildren = require('ReactChildren');
Expand All @@ -36,6 +32,7 @@ var ReactPropTypes = require('ReactPropTypes');
var ReactServerRendering = require('ReactServerRendering');
var ReactTextComponent = require('ReactTextComponent');

var assign = require('Object.assign');
var deprecated = require('deprecated');
var onlyChild = require('onlyChild');

Expand Down Expand Up @@ -84,6 +81,9 @@ var React = {
isValidElement: ReactElement.isValidElement,
withContext: ReactContext.withContext,

// Hook for JSX spread, don't use this for anything else.
__spread: assign,

// Deprecations (remove for 0.13)
renderComponent: deprecated(
'React',
Expand Down
7 changes: 4 additions & 3 deletions src/browser/ui/ReactDOMComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ var ReactMount = require('ReactMount');
var ReactMultiChild = require('ReactMultiChild');
var ReactPerf = require('ReactPerf');

var assign = require('Object.assign');
var escapeTextForBrowser = require('escapeTextForBrowser');
var invariant = require('invariant');
var isEventSupported = require('isEventSupported');
Expand Down Expand Up @@ -213,7 +214,7 @@ ReactDOMComponent.Mixin = {
} else {
if (propKey === STYLE) {
if (propValue) {
propValue = props.style = Object.assign({}, props.style);
propValue = props.style = assign({}, props.style);
}
propValue = CSSPropertyOperations.createMarkupForStyles(propValue);
}
Expand Down Expand Up @@ -362,7 +363,7 @@ ReactDOMComponent.Mixin = {
}
if (propKey === STYLE) {
if (nextProp) {
nextProp = nextProps.style = Object.assign({}, nextProp);
nextProp = nextProps.style = assign({}, nextProp);
}
if (lastProp) {
// Unset styles on `lastProp` but not on `nextProp`.
Expand Down Expand Up @@ -471,7 +472,7 @@ ReactDOMComponent.Mixin = {

};

Object.assign(
assign(
ReactDOMComponent.prototype,
ReactComponent.Mixin,
ReactDOMComponent.Mixin,
Expand Down
3 changes: 2 additions & 1 deletion src/browser/ui/ReactEventListener.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ var ReactInstanceHandles = require('ReactInstanceHandles');
var ReactMount = require('ReactMount');
var ReactUpdates = require('ReactUpdates');

var assign = require('Object.assign');
var getEventTarget = require('getEventTarget');
var getUnboundedScrollPosition = require('getUnboundedScrollPosition');

Expand Down Expand Up @@ -46,7 +47,7 @@ function TopLevelCallbackBookKeeping(topLevelType, nativeEvent) {
this.nativeEvent = nativeEvent;
this.ancestors = [];
}
Object.assign(TopLevelCallbackBookKeeping.prototype, {
assign(TopLevelCallbackBookKeeping.prototype, {
destructor: function() {
this.topLevelType = null;
this.nativeEvent = null;
Expand Down
11 changes: 6 additions & 5 deletions src/browser/ui/__tests__/ReactDOMComponent-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

"use strict";

var assign = require('Object.assign');
var mocks = require('mocks');

describe('ReactDOMComponent', function() {
Expand Down Expand Up @@ -223,7 +224,7 @@ describe('ReactDOMComponent', function() {
this.props = initialProps || {};
this._rootNodeID = 'test';
};
Object.assign(NodeStub.prototype, ReactDOMComponent.Mixin);
assign(NodeStub.prototype, ReactDOMComponent.Mixin);

genMarkup = function(props) {
var transaction = new ReactReconcileTransaction();
Expand Down Expand Up @@ -273,7 +274,7 @@ describe('ReactDOMComponent', function() {
this.props = initialProps || {};
this._rootNodeID = 'test';
};
Object.assign(NodeStub.prototype, ReactDOMComponent.Mixin);
assign(NodeStub.prototype, ReactDOMComponent.Mixin);

genMarkup = function(props) {
var transaction = new ReactReconcileTransaction();
Expand Down Expand Up @@ -310,9 +311,9 @@ describe('ReactDOMComponent', function() {
var StubNativeComponent = function(element) {
ReactComponent.Mixin.construct.call(this, element);
};
Object.assign(StubNativeComponent.prototype, ReactComponent.Mixin);
Object.assign(StubNativeComponent.prototype, ReactDOMComponent.Mixin);
Object.assign(StubNativeComponent.prototype, ReactMultiChild.Mixin);
assign(StubNativeComponent.prototype, ReactComponent.Mixin);
assign(StubNativeComponent.prototype, ReactDOMComponent.Mixin);
assign(StubNativeComponent.prototype, ReactMultiChild.Mixin);

mountComponent = function(props) {
var transaction = new ReactReconcileTransaction();
Expand Down
3 changes: 2 additions & 1 deletion src/browser/ui/dom/components/ReactDOMInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ var ReactDOM = require('ReactDOM');
var ReactMount = require('ReactMount');
var ReactUpdates = require('ReactUpdates');

var assign = require('Object.assign');
var invariant = require('invariant');

// Store a reference to the <input> `ReactDOMComponent`. TODO: use string
Expand Down Expand Up @@ -66,7 +67,7 @@ var ReactDOMInput = ReactCompositeComponent.createClass({

render: function() {
// Clone `this.props` so we don't mutate the input.
var props = Object.assign({}, this.props);
var props = assign({}, this.props);

props.defaultChecked = null;
props.defaultValue = null;
Expand Down
4 changes: 3 additions & 1 deletion src/browser/ui/dom/components/ReactDOMSelect.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ var ReactElement = require('ReactElement');
var ReactDOM = require('ReactDOM');
var ReactUpdates = require('ReactUpdates');

var assign = require('Object.assign');

// Store a reference to the <select> `ReactDOMComponent`. TODO: use string
var select = ReactElement.createFactory(ReactDOM.select.type);

Expand Down Expand Up @@ -129,7 +131,7 @@ var ReactDOMSelect = ReactCompositeComponent.createClass({

render: function() {
// Clone `this.props` so we don't mutate the input.
var props = Object.assign({}, this.props);
var props = assign({}, this.props);

props.onChange = this._handleChange;
props.value = null;
Expand Down
3 changes: 2 additions & 1 deletion src/browser/ui/dom/components/ReactDOMTextarea.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ var ReactElement = require('ReactElement');
var ReactDOM = require('ReactDOM');
var ReactUpdates = require('ReactUpdates');

var assign = require('Object.assign');
var invariant = require('invariant');

var warning = require('warning');
Expand Down Expand Up @@ -95,7 +96,7 @@ var ReactDOMTextarea = ReactCompositeComponent.createClass({

render: function() {
// Clone `this.props` so we don't mutate the input.
var props = Object.assign({}, this.props);
var props = assign({}, this.props);

invariant(
props.dangerouslySetInnerHTML == null,
Expand Down
5 changes: 3 additions & 2 deletions src/core/ReactComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ var ReactElement = require('ReactElement');
var ReactOwner = require('ReactOwner');
var ReactUpdates = require('ReactUpdates');

var assign = require('Object.assign');
var invariant = require('invariant');
var keyMirror = require('keyMirror');

Expand Down Expand Up @@ -143,7 +144,7 @@ var ReactComponent = {
// element props.
var element = this._pendingElement || this._currentElement;
this.replaceProps(
Object.assign({}, element.props, partialProps),
assign({}, element.props, partialProps),
callback
);
},
Expand Down Expand Up @@ -192,7 +193,7 @@ var ReactComponent = {
var element = this._pendingElement || this._currentElement;
this._pendingElement = ReactElement.cloneAndReplaceProps(
element,
Object.assign({}, element.props, partialProps)
assign({}, element.props, partialProps)
);
ReactUpdates.enqueueUpdate(this, callback);
},
Expand Down
Loading

0 comments on commit 8210bee

Please sign in to comment.