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

Fix export namespace of an excluded asset #4220

Closed
wants to merge 8 commits into from
Closed

Conversation

mischnic
Copy link
Member

↪️ Pull Request

Closes #4216

An asset with export * from ... might be excluded by concat, so the exportsSpecifier will be undefined (so $parcel$exportWildcard(something, ReexportingExportsSpecifier) doesn't work).

Solution: don't emit $parcel$exportWildcard if the imported asset is a ES6 module, in which case bundleGraph.getExportedSymbols(mod) are traversed and assignments emitted.

cc @wbinnssmith, does this fix your problem?

@mischnic mischnic changed the title export namespace of a excluded asset Fix export namespace of a excluded asset Feb 25, 2020
@mischnic mischnic changed the title Fix export namespace of a excluded asset Fix export namespace of an excluded asset Feb 25, 2020
@parcel-benchmark
Copy link

parcel-benchmark commented Feb 25, 2020

Benchmark Results

packages/benchmarks/three ✅

Timings

Description Time Difference
Cold 1.48m -2.02s
Cached 5.09s +166.00ms

Cold Bundles

No bundle changes detected.

Cached Bundles

Bundle Size Difference Time Difference
dist/three/entry.js 2.68mb +0.00b 44.00ms -395.00ms 🚀

packages/benchmarks/kitchen-sink ✅

Timings

Description Time Difference
Cold 7.48s -65.00ms
Cached 3.67s -194.00ms 🚀

Cold Bundles

Bundle Size Difference Time Difference
dist/legacy/parcel.d5807e82.webp 102.94kb +0.00b 251.00ms +24.00ms ⚠️
dist/modern/parcel.d5807e82.webp 102.94kb +0.00b 311.00ms -35.00ms 🚀

Cached Bundles

Bundle Size Difference Time Difference
dist/legacy/parcel.d5807e82.webp 102.94kb +0.00b 6.00ms +1.00ms ⚠️
dist/modern/parcel.d5807e82.webp 102.94kb +0.00b 4.00ms +1.00ms ⚠️
dist/legacy/index.html 709.00b +0.00b 12.00ms +1.00ms ⚠️
dist/modern/styles.27b3555b.css 29.00b +0.00b 5.00ms +1.00ms ⚠️

packages/benchmarks/react-hn ✅

Timings

Description Time Difference
Cold 10.28s -362.00ms
Cached 3.69s +64.00ms

Cold Bundles

No bundle changes detected.

Cached Bundles

Bundle Size Difference Time Difference
dist/main/index.js 66.50kb +0.00b 9.00ms -2.00ms 🚀
dist/module/index.js 37.46kb +0.00b 3.00ms -1.00ms 🚀

packages/benchmarks/ak-editor 🚨

Timings

Description Time Difference
Cold FAILED -0.00ms
Cached FAILED -0.00ms

Cold Bundles

No bundles found, this is probably a failed build...

Cached Bundles

No bundles found, this is probably a failed build...

Click here to view a detailed benchmark overview.

@mischnic mischnic force-pushed the wildcard-excluded branch 5 times, most recently from ac16275 to b23482c Compare February 26, 2020 20:53
@devongovett
Copy link
Member

An asset with export * from ... might be excluded by concat

Should it have been excluded though? Seems like if later code is referencing it, then maybe excluding it was wrong? Probably misunderstanding.

@mischnic mischnic force-pushed the wildcard-excluded branch 2 times, most recently from 4810963 to 77d7f0d Compare March 4, 2020 20:45
@mischnic
Copy link
Member Author

mischnic commented Mar 4, 2020

Should it have been excluded though?

Well, symbols in concat are marked used with bundleGraph.resolveSymbol(), so in the example below, "exports.js" is not actually "used".
But when calling the wildcard function, that asset's exportidentifier is needed.

// index.js
export * from "./exports";

export const Main = "main";

//  exports.js
export { a } from "./version";
export { b } from "./version2";

// version(2) just export a variable

The big questions: should we not emit the helper function is possible :?
output when simply including the missing asset:

(function(){
function $parcel$exportWildcard(dest, source) {
  Object.keys(source).forEach(function (key) {
    if (key === 'default' || key === '__esModule') {
      return;
    }

    Object.defineProperty(dest, key, {
      enumerable: true,
      get: function get() {
        return source[key];
      }
    });
  });
  return dest;
}

// ASSET: /Users/niklas/Documents/_dev/_git/parcel/parcel/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-namespace-sideEffects/other/index.js
var $e367b6edc7f6de5eef03bc6e42a99$exports = {};
// ASSET: /Users/niklas/Documents/_dev/_git/parcel/parcel/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-namespace-sideEffects/other/exports.js
var $d52a61ca40f5bad1d825ae05f8$exports = {};
var $e7fabb81ca3e1f1a1428a4a075efc$export$a = "foo";
var $c295ce722e44b4d388a0f05140b040$export$b = "bar";
$d52a61ca40f5bad1d825ae05f8$exports.a = $e7fabb81ca3e1f1a1428a4a075efc$export$a;
$d52a61ca40f5bad1d825ae05f8$exports.b = $c295ce722e44b4d388a0f05140b040$export$b;
$parcel$exportWildcard($e367b6edc7f6de5eef03bc6e42a99$exports, $d52a61ca40f5bad1d825ae05f8$exports);
const $e367b6edc7f6de5eef03bc6e42a99$export$Main = "main";
$e367b6edc7f6de5eef03bc6e42a99$exports.Main = $e367b6edc7f6de5eef03bc6e42a99$export$Main;
output = $e367b6edc7f6de5eef03bc6e42a99$exports;
})();

output with this change:

(function(){
// ASSET: /Users/niklas/Documents/_dev/_git/parcel/parcel/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-namespace-sideEffects/other/exports.js
// ASSET: /Users/niklas/Documents/_dev/_git/parcel/parcel/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-namespace-sideEffects/other/version.js
var $e7fabb81ca3e1f1a1428a4a075efc$export$a = "foo";
var $c295ce722e44b4d388a0f05140b040$export$b = "bar";
// ASSET: /Users/niklas/Documents/_dev/_git/parcel/parcel/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-namespace-sideEffects/other/index.js
var $e367b6edc7f6de5eef03bc6e42a99$exports = {};
$e367b6edc7f6de5eef03bc6e42a99$exports.a = $e7fabb81ca3e1f1a1428a4a075efc$export$a;
$e367b6edc7f6de5eef03bc6e42a99$exports.b = $c295ce722e44b4d388a0f05140b040$export$b;
const $e367b6edc7f6de5eef03bc6e42a99$export$Main = "main";
$e367b6edc7f6de5eef03bc6e42a99$exports.Main = $e367b6edc7f6de5eef03bc6e42a99$export$Main;
output = $e367b6edc7f6de5eef03bc6e42a99$exports;
})();

package.json Outdated Show resolved Hide resolved
@mischnic mischnic added the 📝 WIP Work In Progress label Mar 18, 2020
Copy link
Member

@devongovett devongovett left a comment

Choose a reason for hiding this comment

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

I don't think I fully understand what's going on here. 😉

Could we schedule a time to go through your changes over video so you can explain them to me?

@@ -438,6 +459,86 @@ export function link({
);
let mod = nullthrows(bundleGraph.getDependencyResolution(dep, bundle));
path.replaceWith(t.valueToNode(mod.id));
} else if (callee.name === '$parcel$exportAll') {
Copy link
Member

Choose a reason for hiding this comment

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

Not sure I totally understand why this is necessary vs the old $parcel$exportWildcard with a $parcelRequire inside. Seems like a bunch of logic got duplicated?

@mischnic
Copy link
Member Author

This is indeed a giant hack and way too complex, let's do #4387 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Scope hoisting: import * with re-exporting does not include all exports
4 participants