-
-
Notifications
You must be signed in to change notification settings - Fork 2.3k
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
[Symbol Propagation] Non-deterministic bundle hashes #8212
Conversation
…ong/nondeterministic-shared-bundle-hashes
…ong/nondeterministic-shared-bundle-hashes
…ong/nondeterministic-shared-bundle-hashes
…/github.com/parcel-bundler/parcel into gkong/nondeterministic-shared-bundle-hashes
@mischnic would like to know what you think 🙂 |
Benchmark ResultsKitchen Sink ✅
Timings
Cold BundlesNo bundle changes detected. Cached BundlesNo bundle changes detected. React HackerNews ✅
Timings
Cold BundlesNo bundle changes detected. Cached BundlesNo bundle changes detected. AtlasKit Editor ✅
Timings
Cold Bundles
Cached BundlesNo bundle changes detected. Three.js ✅
Timings
Cold BundlesNo bundle changes detected. Cached BundlesNo bundle changes detected. |
The dependency graph for test case currently looks like this: graph TB;
index[index.js]
library[library/index.js]
foo[library/foo.js]
bar[library/bar.js]
utils[utils/index.js]
bag[utils/bag.js]
empty[utils/empty.js]
index-->|"import {foo, bar} from 'library'"|library
library-->|"export {foo} from './foo'"|foo
library-->|"export {bar} from './bar'"|bar
foo-->|"import {bag} from '../utils'"|utils
bar-->|"import {baz, bag} from '../utils'"|utils
utils-->|"export * from './bag'"|bag
utils-->|"export * from './empty'"|empty
We aren't sure if this is the minimal form or not. Maybe the diamond shape isn't actually necessary? |
…ong/nondeterministic-shared-bundle-hashes
…/github.com/parcel-bundler/parcel into gkong/nondeterministic-shared-bundle-hashes
I do think the diamond (plus the "open" diamond at the end) is needed. But that linear chain before the diamond (html, (And you could also run into this situation if you do a build with only the "right" diamond branch, and then do another cached build with the "left" diamond branch added. The result would also have a different order of incoming dependencies compared to adding them in the reverse order). So this is just an inherent problem of
The only solution I can think of is sorting the dependencies somehow. There is simply no existing/inherent order for incoming dependencies. |
…ong/nondeterministic-shared-bundle-hashes
…/github.com/parcel-bundler/parcel into gkong/nondeterministic-shared-bundle-hashes
…ong/nondeterministic-shared-bundle-hashes
…istic-shared-bundle-hashes
…/github.com/parcel-bundler/parcel into gkong/nondeterministic-shared-bundle-hashes
It has to be that new workerfarm which is causing CI to fail. Using the existing one should work better: diff --git packages/core/integration-tests/test/scope-hoisting.js packages/core/integration-tests/test/scope-hoisting.js
index 3375ac891..7509826fb 100644
--- packages/core/integration-tests/test/scope-hoisting.js
+++ packages/core/integration-tests/test/scope-hoisting.js
@@ -2,7 +2,6 @@ import assert from 'assert';
import path from 'path';
import nullthrows from 'nullthrows';
import {normalizePath} from '@parcel/utils';
-import {createWorkerFarm} from '@parcel/core';
import {md} from '@parcel/diagnostic';
import {
assertBundles,
@@ -18,6 +17,7 @@ import {
overlayFS,
run,
runBundle,
+ workerFarm,
} from '@parcel/test-utils';
const bundle = (name, opts = {}) => {
@@ -5535,10 +5535,6 @@ describe('scope hoisting', function () {
});
it('produce the same bundle hash regardless of transformation order', async function () {
- let workerFarm = createWorkerFarm({
- maxConcurrentWorkers: 0,
- });
-
let testDir = path.join(
__dirname,
'integration/scope-hoisting/es6/non-deterministic-bundle-hashes', But that makes the test pass sometimes when commenting out the fix... |
Another thing I noticed: parcel/packages/core/integration-tests/test/cache.js Lines 3932 to 3938 in a9193ce
So having two workerfarms still running and receiving events from each other probably triggers the assertion |
@mischnic doesn't the workerFarm in |
…ong/nondeterministic-shared-bundle-hashes
…/github.com/parcel-bundler/parcel into gkong/nondeterministic-shared-bundle-hashes
532309d
to
3df2a78
Compare
* upstream/v2: (22 commits) Cross compile toolchains are built into docker image already Also fix release build Update centos node version v2.7.0 Changelog for v2.7.0 Use placeholder expression when replacing unused symbols (#8358) Lint (#8359) Add support for errorRecovery option in @parcel/transformer-css (#8352) VS Code Extension for Parcel (#8139) Add multi module compilation for elm (#8076) Bump terser from 5.7.2 to 5.14.2 (#8322) Bump node-forge from 1.2.1 to 1.3.0 (#8271) allow cjs config files on type module projects (#8253) inject script for hmr when there is only normal script in html (#8330) feat: support react refresh for @emotion/react (#8205) Update index.d.ts (#8293) remove charset from jsloader script set (#8346) Log resolved targets in verbose log level (#8254) Fix missing module in large app from Experimental Bundler (#8303) [Symbol Propagation] Non-deterministic bundle hashes (#8212) ...
↪️ Pull Request
In collaboration with @lettertwo
This PR addresses non-determinism in bundle hashes in the absence of file content changes.
In our test case,
foo
importsbag
bar
imports bothbaz
andbag
We end up with either one of two output bundle contents (and hence hashes) depending on whether
foo
orbar
is transformed first (example below):💻 Examples
When transformation of
foo.js
is delayed,baz
is ordered beforebag
since we seebaz
being used first (inbar.js
):The order of these exports are flipped when we delay
bar.js
's transformation.💡Proposed Fix
Keep track of dependencies that have changes to their used symbols and sort their used symbols after symbol propagation.
🚨 Test instructions
The test case implements a custom
readFile
that proxiesoverlayFS
to delay transformation. This was done (as opposed to deferring) to avoid changing source content of assets being transformed when introducing these delays.