Skip to content

Commit

Permalink
Merge branch 'v2' of github.com:parcel-bundler/parcel into bdo/single…
Browse files Browse the repository at this point in the history
…-thread-rebuild
  • Loading branch information
devongovett committed Oct 30, 2022
2 parents 8bf905a + 0759d1b commit 1caafeb
Show file tree
Hide file tree
Showing 34 changed files with 1,445 additions and 115 deletions.
54 changes: 30 additions & 24 deletions packages/bundlers/experimental/src/ExperimentalBundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -511,9 +511,8 @@ function createIdealGraph(
let bundleGroupRootAsset = nullthrows(bundleGroup.mainEntryAsset);
if (
entries.has(bundleGroupRootAsset) &&
bundleGroupRootAsset.type === childAsset.type &&
childAsset.bundleBehavior !== 'inline' &&
dependency.bundleBehavior !== 'isolated'
canMerge(bundleGroupRootAsset, childAsset) &&
dependency.bundleBehavior == null
) {
bundleId = bundleGroupNodeId;
}
Expand All @@ -523,7 +522,8 @@ function createIdealGraph(
asset: childAsset,
type: childAsset.type,
env: childAsset.env,
bundleBehavior: childAsset.bundleBehavior,
bundleBehavior:
dependency.bundleBehavior ?? childAsset.bundleBehavior,
target: referencingBundle.target,
needsStableName:
childAsset.bundleBehavior === 'inline' ||
Expand All @@ -534,8 +534,15 @@ function createIdealGraph(
: referencingBundle.needsStableName,
});
bundleId = bundleGraph.addNode(bundle);

// Store Type-Change bundles for later since we need to know ALL bundlegroups they are part of to reduce/combine them
typeChangeIds.add(bundleId);
if (parentAsset.type !== childAsset.type) {
typeChangeIds.add(bundleId);
}
} else {
bundle = bundleGraph.getNode(bundleId);
invariant(bundle != null && bundle !== 'root');

if (
// If this dependency requests isolated, but the bundle is not,
// make the bundle isolated for all uses.
Expand All @@ -544,10 +551,6 @@ function createIdealGraph(
) {
bundle.bundleBehavior = dependency.bundleBehavior;
}
} else {
// Otherwise, merge.
bundle = bundleGraph.getNode(bundleId);
invariant(bundle != null && bundle !== 'root');
}

bundles.set(childAsset.id, bundleId);
Expand Down Expand Up @@ -603,9 +606,7 @@ function createIdealGraph(
b !== 'root' &&
a !== b &&
typeChangeIds.has(nodeIdB) &&
a.bundleBehavior !== 'inline' &&
b.bundleBehavior !== 'inline' &&
a.type === b.type
canMerge(a, b)
) {
let bundleBbundleGroups = getBundleGroupsForBundle(nodeIdB);
if (setEqual(bundleBbundleGroups, bundleABundleGroups)) {
Expand Down Expand Up @@ -670,8 +671,9 @@ function createIdealGraph(
);
if (
bundle !== 'root' &&
bundle.bundleBehavior !== 'inline' &&
!bundle.env.isIsolated()
bundle.bundleBehavior == null &&
!bundle.env.isIsolated() &&
bundle.env.context === root.env.context
) {
bundleRootGraph.addEdge(
bundleRootGraph.getNodeIdByContentKey(root.id),
Expand All @@ -691,11 +693,7 @@ function createIdealGraph(
}
//asset node type
let asset = node.value;
if (
asset.bundleBehavior === 'isolated' ||
asset.bundleBehavior === 'inline' ||
root.type !== asset.type
) {
if (asset.bundleBehavior != null || root.type !== asset.type) {
actions.skipChildren();
return;
}
Expand Down Expand Up @@ -748,10 +746,7 @@ function createIdealGraph(
]) {
let bundleInGroup = nullthrows(bundleGraph.getNode(bundleIdInGroup));
invariant(bundleInGroup !== 'root');
if (
bundleInGroup.bundleBehavior === 'isolated' ||
bundleInGroup.bundleBehavior === 'inline'
) {
if (bundleInGroup.bundleBehavior != null) {
continue;
}

Expand Down Expand Up @@ -784,7 +779,7 @@ function createIdealGraph(
let child = bundleRootGraph.getNode(childId);
invariant(child !== 'root' && child != null);
let bundleBehavior = getBundleFromBundleRoot(child).bundleBehavior;
if (bundleBehavior === 'isolated' || bundleBehavior === 'inline') {
if (bundleBehavior != null) {
continue;
}
let isParallel = bundleRootGraph.hasEdge(
Expand Down Expand Up @@ -1345,3 +1340,14 @@ function getEntryByTarget(
});
return targets;
}

function canMerge(a, b) {
// Bundles can be merged if they have the same type and environment,
// unless they are explicitly marked as isolated or inline.
return (
a.type === b.type &&
a.env.context === b.env.context &&
a.bundleBehavior == null &&
b.bundleBehavior == null
);
}
1 change: 1 addition & 0 deletions packages/core/core/src/AssetGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ export default class AssetGraph extends ContentGraph<AssetGraphNode> {
hash: ?string;
envCache: Map<string, Environment>;
symbolPropagationRan: boolean;
safeToIncrementallyBundle: boolean = true;

constructor(opts: ?AssetGraphOpts) {
if (opts) {
Expand Down
19 changes: 17 additions & 2 deletions packages/core/core/src/BundleGraph.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import type {
} from './types';
import type AssetGraph from './AssetGraph';
import type {ProjectPath} from './projectPath';
import {nodeFromAsset} from './AssetGraph';

import assert from 'assert';
import invariant from 'assert';
Expand Down Expand Up @@ -1887,8 +1888,7 @@ export default class BundleGraph {
otherGraphIdToThisNodeId.set(otherNodeId, existingNodeId);

let existingNode = nullthrows(this._graph.getNode(existingNodeId));
// Merge symbols, recompute dep.exluded based on that

// Merge symbols, recompute dep.excluded based on that
if (existingNode.type === 'asset') {
invariant(otherNode.type === 'asset');
existingNode.usedSymbols = new Set([
Expand Down Expand Up @@ -1940,6 +1940,21 @@ export default class BundleGraph {
.some(n => n.type === 'root');
}

/**
* Update the asset in a Bundle Graph and clear the associated Bundle hash.
*/
updateAsset(asset: Asset) {
this._graph.updateNode(
this._graph.getNodeIdByContentKey(asset.id),
nodeFromAsset(asset),
);
let bundles = this.getBundlesWithAsset(asset);
for (let bundle of bundles) {
// the bundle content will change with a modified asset
this._bundleContentHashes.delete(bundle.id);
}
}

getEntryRoot(projectRoot: FilePath, target: Target): FilePath {
let cached = this._targetEntryRoots.get(target.distDir);
if (cached != null) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/core/src/UncommittedAsset.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ export default class UncommittedAsset {
}

/*
* Prepares the asset for being serialized to the cache by commiting its
* Prepares the asset for being serialized to the cache by committing its
* content and map of the asset to the cache.
*/
async commit(pipelineKey: string): Promise<void> {
Expand Down
99 changes: 90 additions & 9 deletions packages/core/core/src/requests/AssetGraphRequest.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@ type AssetGraphRequestInput = {|
requestedAssetIds?: Set<string>,
|};

type AssetGraphRequestResult = {|
type AssetGraphRequestResult = AssetGraphBuilderResult & {|
previousAssetGraphHash: ?string,
|};

type AssetGraphBuilderResult = {|
assetGraph: AssetGraph,
changedAssets: Map<string, Asset>,
assetRequests: Array<AssetGroup>,
Expand All @@ -63,11 +67,7 @@ type RunInput = {|
type AssetGraphRequest = {|
id: string,
+type: 'asset_graph_request',
run: RunInput => Async<{|
assetGraph: AssetGraph,
changedAssets: Map<string, Asset>,
assetRequests: Array<AssetGroup>,
|}>,
run: RunInput => Async<AssetGraphRequestResult>,
input: AssetGraphRequestInput,
|};

Expand All @@ -80,8 +80,23 @@ export default function createAssetGraphRequest(
run: async input => {
let prevResult =
await input.api.getPreviousResult<AssetGraphRequestResult>();
let previousAssetGraphHash = prevResult?.assetGraph.getHash();

let builder = new AssetGraphBuilder(input, prevResult);
return builder.build();
let assetGraphRequest = await await builder.build();

// early break for incremental bundling if production or flag is off;
if (
!input.options.shouldBundleIncrementally ||
input.options.mode === 'production'
) {
assetGraphRequest.assetGraph.safeToIncrementallyBundle = false;
}

return {
...assetGraphRequest,
previousAssetGraphHash,
};
},
input,
};
Expand Down Expand Up @@ -109,7 +124,7 @@ export class AssetGraphBuilder {

constructor(
{input, api, options}: RunInput,
prevResult: ?AssetGraphRequestResult,
prevResult: ?AssetGraphBuilderResult,
) {
let {
entries,
Expand All @@ -120,6 +135,7 @@ export class AssetGraphBuilder {
shouldBuildLazily,
} = input;
let assetGraph = prevResult?.assetGraph ?? new AssetGraph();
assetGraph.safeToIncrementallyBundle = true;
assetGraph.setRootConnections({
entries,
assetGroups,
Expand All @@ -138,7 +154,7 @@ export class AssetGraphBuilder {
this.queue = new PromiseQueue();
}

async build(): Promise<AssetGraphRequestResult> {
async build(): Promise<AssetGraphBuilderResult> {
let errors = [];
let rootNodeId = nullthrows(
this.assetGraph.rootNodeId,
Expand Down Expand Up @@ -235,6 +251,7 @@ export class AssetGraphBuilder {
if (this.shouldBuildLazily) {
let node = nullthrows(this.assetGraph.getNode(nodeId));
let childNode = nullthrows(this.assetGraph.getNode(childNodeId));

if (node.type === 'asset' && childNode.type === 'dependency') {
if (this.requestedAssetIds.has(node.value.id)) {
node.requested = true;
Expand Down Expand Up @@ -284,6 +301,7 @@ export class AssetGraphBuilder {
assetSymbolsInverse = new Map<Symbol, Set<Symbol>>();
for (let [s, {local}] of assetSymbols) {
let set = assetSymbolsInverse.get(local);

if (!set) {
set = new Set();
assetSymbolsInverse.set(local, set);
Expand Down Expand Up @@ -512,6 +530,7 @@ export class AssetGraphBuilder {
}

let local = outgoingDepSymbols.get(s)?.local;

if (local == null) {
// Caused by '*' => '*', already handled
continue;
Expand Down Expand Up @@ -917,11 +936,34 @@ export class AssetGraphBuilder {
}

async runEntryRequest(input: ProjectPath) {
let prevEntries = this.assetGraph.safeToIncrementallyBundle
? this.assetGraph
.getEntryAssets()
.map(asset => asset.id)
.sort()
: [];

let request = createEntryRequest(input);
let result = await this.api.runRequest<ProjectPath, EntryResult>(request, {
force: true,
});
this.assetGraph.resolveEntry(request.input, result.entries, request.id);

if (this.assetGraph.safeToIncrementallyBundle) {
let currentEntries = this.assetGraph
.getEntryAssets()
.map(asset => asset.id)
.sort();
let didEntriesChange =
prevEntries.length !== currentEntries.length ||
prevEntries.every(
(entryId, index) => entryId === currentEntries[index],
);

if (didEntriesChange) {
this.assetGraph.safeToIncrementallyBundle = false;
}
}
}

async runTargetRequest(input: Entry) {
Expand Down Expand Up @@ -955,11 +997,50 @@ export class AssetGraphBuilder {

if (assets != null) {
for (let asset of assets) {
if (this.assetGraph.safeToIncrementallyBundle) {
let otherAsset = this.assetGraph.getNodeByContentKey(asset.id);
if (otherAsset != null) {
invariant(otherAsset.type === 'asset');
if (!this._areDependenciesEqualForAssets(asset, otherAsset.value)) {
this.assetGraph.safeToIncrementallyBundle = false;
}
} else {
// adding a new entry or dependency
this.assetGraph.safeToIncrementallyBundle = false;
}
}
this.changedAssets.set(asset.id, asset);
}
this.assetGraph.resolveAssetGroup(input, assets, request.id);
} else {
this.assetGraph.safeToIncrementallyBundle = false;
}
}

/**
* Used for incremental bundling of modified assets
*/
_areDependenciesEqualForAssets(asset: Asset, otherAsset: Asset): boolean {
let assetDependencies = Array.from(asset?.dependencies.keys()).sort();
let otherAssetDependencies = Array.from(
otherAsset?.dependencies.keys(),
).sort();

if (assetDependencies.length !== otherAssetDependencies.length) {
return false;
}

return assetDependencies.every((key, index) => {
if (key !== otherAssetDependencies[index]) {
return false;
}

return equalSet(
new Set(asset?.dependencies.get(key)?.symbols?.keys()),
new Set(otherAsset?.dependencies.get(key)?.symbols?.keys()),
);
});
}
}

function equalMap<K>(
Expand Down

0 comments on commit 1caafeb

Please sign in to comment.