Skip to content

Commit

Permalink
Check in a forked version of object-assign only for UMD builds (#18180)
Browse files Browse the repository at this point in the history
* Check in a forked version of object-assign

This one uses ES modules so that we can inline it into UMD builds.

We could wait for object-assign to make an ESM export but we're going to
remove this dependency and assume global polyfills in the next version
anyway. However, we'd have to figure out how to keep the copyright header
and it'll get counted in terms of byte size (even if other tooling removes
it).

A lot of headache when we have our own implementation anyway. So I'll just
use that.

Ours is not resilient to checking certain browser bugs but those browsers
are mostly unused anyway. (Even FB breaks on them presumably.)

We also don't need to be resilient to Symbols since the way React uses it
we shouldn't need to copy symbols

* Don't transpile Object.assign to object-assign in object-assign

The polyfill needs to be able to feature detect Object.assign.
  • Loading branch information
sebmarkbage authored Feb 28, 2020
1 parent 053347e commit 58eedbb
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
31 changes: 31 additions & 0 deletions packages/shared/forks/object-assign.inline-umd.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* Copyright 2004-present Facebook. All Rights Reserved.
*/

const hasOwnProperty = Object.prototype.hasOwnProperty;

const _assign = function(to, from) {
for (let key in from) {
if (hasOwnProperty.call(from, key)) {
to[key] = from[key];
}
}
};

export default Object.assign ||
function(target, sources) {
if (target == null) {
throw new TypeError('Object.assign target cannot be null or undefined');
}

const to = Object(target);

for (let nextIndex = 1; nextIndex < arguments.length; nextIndex++) {
const nextSource = arguments[nextIndex];
if (nextSource != null) {
_assign(to, Object(nextSource));
}
}

return to;
};
8 changes: 8 additions & 0 deletions scripts/babel/transform-object-assign-require.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ module.exports = function autoImporter(babel) {

visitor: {
CallExpression: function(path, file) {
if (file.filename.indexOf('object-assign') !== -1) {
// Don't replace Object.assign if we're transforming object-assign
return;
}
if (path.get('callee').matchesPattern('Object.assign')) {
// generate identifier and require if it hasn't been already
const id = getAssignIdent(path, file, this);
Expand All @@ -36,6 +40,10 @@ module.exports = function autoImporter(babel) {
},

MemberExpression: function(path, file) {
if (file.filename.indexOf('object-assign') !== -1) {
// Don't replace Object.assign if we're transforming object-assign
return;
}
if (path.matchesPattern('Object.assign')) {
const id = getAssignIdent(path, file, this);
path.replaceWith(id);
Expand Down
10 changes: 7 additions & 3 deletions scripts/rollup/forks.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ const {RENDERER, RECONCILER} = moduleTypes;
// If you need to replace a file with another file for a specific environment,
// add it to this list with the logic for choosing the right replacement.
const forks = Object.freeze({
// Optimization: for UMDs, use object-assign polyfill that is already a part
// of the React package instead of bundling it again.
// Optimization: for UMDs, use a version that we can inline into the React bundle.
// Use that from all other bundles.
'object-assign': (bundleType, entry, dependencies) => {
if (
bundleType !== UMD_DEV &&
Expand All @@ -34,12 +34,16 @@ const forks = Object.freeze({
// happens. Other bundles just require('object-assign') anyway.
return null;
}
if (entry === 'react') {
// Use the forked version that uses ES modules instead of CommonJS.
return 'shared/forks/object-assign.inline-umd.js';
}
if (dependencies.indexOf('react') === -1) {
// We can only apply the optimizations to bundle that depend on React
// because we read assign() from an object exposed on React internals.
return null;
}
// We can use the fork!
// We can use the fork that reads the secret export!
return 'shared/forks/object-assign.umd.js';
},

Expand Down

0 comments on commit 58eedbb

Please sign in to comment.