Skip to content

Commit

Permalink
add implementation and make necessary changes to bitset reachable
Browse files Browse the repository at this point in the history
  • Loading branch information
AGawrys committed Oct 4, 2023
1 parent fefce78 commit 1be1574
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 60 deletions.
157 changes: 101 additions & 56 deletions packages/bundlers/default/src/DefaultBundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ type ManualSharedBundles = Array<{|
assets: Array<Glob>,
types?: Array<string>,
parent?: string,
active?: Array<string>,
split?: number,
|}>;

Expand Down Expand Up @@ -426,30 +427,48 @@ function createIdealGraph(
function makeManualAssetToConfigLookup() {
let manualAssetToConfig = new Map();
let constantModuleToMSB = new DefaultMap(() => []);

let configToActiveAsset = new DefaultMap(() => []);
if (config.manualSharedBundles.length === 0) {
return {manualAssetToConfig, constantModuleToMSB};
return {manualAssetToConfig, constantModuleToMSB, configToActiveAsset};
}

let parentsToConfig = new DefaultMap(() => []);
let activeToConfig = new DefaultMap(() => []);

for (let c of config.manualSharedBundles) {
if (c.parent != null) {
parentsToConfig.get(path.join(config.projectRoot, c.parent)).push(c);
}
if (c.active != null) {
for (let a of c.active) {
activeToConfig.get(path.join(config.projectRoot, a)).push(c);
}
}
}
let numParentsToFind = parentsToConfig.size;
let numActivesToFind = activeToConfig.size;
let configToParentAsset = new Map();

assetGraph.traverse((node, _, actions) => {
if (node.type === 'asset' && parentsToConfig.has(node.value.filePath)) {
for (let c of parentsToConfig.get(node.value.filePath)) {
configToParentAsset.set(c, node.value);
if (
node.type === 'asset' &&
(parentsToConfig.has(node.value.filePath) ||
activeToConfig.has(node.value.filePath))
) {
if (parentsToConfig.has(node.value.filePath)) {
for (let c of parentsToConfig.get(node.value.filePath)) {
configToParentAsset.set(c, node.value);
numParentsToFind--;
}
}
if (activeToConfig.has(node.value.filePath)) {
for (let c of activeToConfig.get(node.value.filePath)) {
configToActiveAsset.get(c).push(node.value);
numActivesToFind--;
}
}

numParentsToFind--;

if (numParentsToFind === 0) {
if (numParentsToFind === 0 && numActivesToFind === 0) {
// If we've found all parents we can stop traversal
actions.stop();
}
Expand Down Expand Up @@ -499,15 +518,15 @@ function createIdealGraph(
}, parentAsset);
}

return {manualAssetToConfig, constantModuleToMSB};
return {manualAssetToConfig, constantModuleToMSB, configToActiveAsset};
}

//Manual is a map of the user-given name to the bundle node Id that corresponds to ALL the assets that match any glob in that user-specified array
let manualSharedMap: Map<string, NodeId> = new Map();
// May need a map to be able to look up NON- bundle root assets which need special case instructions
// Use this when placing assets into bundles, to avoid duplication
let manualAssetToBundle: Map<Asset, NodeId> = new Map();
let {manualAssetToConfig, constantModuleToMSB} =
let {manualAssetToConfig, constantModuleToMSB, configToActiveAsset} =
makeManualAssetToConfigLookup();
let manualBundleToInternalizedAsset: Map<
NodeId,
Expand Down Expand Up @@ -1149,6 +1168,7 @@ function createIdealGraph(
let reachable = new BitSet(assets.length);
let reachableNonEntries = new BitSet(assets.length);
let reachableIntersection = new BitSet(assets.length);
let manualReachable = new BitSet(assets.length);
for (let i = 0; i < assets.length; i++) {
let asset = assets[i];
let manualSharedObject = manualAssetToConfig.get(asset);
Expand Down Expand Up @@ -1202,61 +1222,80 @@ function createIdealGraph(

// If we encounter a "manual" asset, draw an edge from reachable to its MSB
if (manualSharedObject && !reachable.empty()) {
let bundle;
let bundleId;
let manualSharedBundleKey = manualSharedObject.name + ',' + asset.type;
let sourceBundles = [];
reachable.forEach(id => {
sourceBundles.push(nullthrows(bundleRoots.get(assets[id]))[0]);
});

if (!manualSharedMap.has(manualSharedBundleKey)) {
let firstSourceBundle = nullthrows(
bundleGraph.getNode(sourceBundles[0]),
);
invariant(firstSourceBundle !== 'root');

bundle = createBundle({
target: firstSourceBundle.target,
type: firstSourceBundle.type,
env: firstSourceBundle.env,
manualSharedBundle: manualSharedObject?.name,
manualReachable.clear();

if (configToActiveAsset.has(manualSharedObject)) {
let activeSet = new Set(configToActiveAsset.get(manualSharedObject));
reachableRoots[i].forEach(nodeId => {
let assetId = bundleRootGraph.getNode(nodeId);
if (assetId == null) return; // deleted
let entry = assets[assetId];
if (activeSet.has(entry)) {
manualReachable.add(assetId);
reachable.delete(assetId); //ensure assets can still be processed afterwards
}
});
bundle.sourceBundles = new Set(sourceBundles);
bundle.assets.add(asset);
bundleId = bundleGraph.addNode(bundle);
manualSharedMap.set(manualSharedBundleKey, bundleId);
} else {
bundleId = nullthrows(manualSharedMap.get(manualSharedBundleKey));
bundle = nullthrows(bundleGraph.getNode(bundleId));
invariant(
bundle != null && bundle !== 'root',
'We tried to use the root incorrectly',
);
manualReachable = reachable.clone();
}
if (!manualReachable.empty()) {
let bundle;
let bundleId;
let manualSharedBundleKey = manualSharedObject.name + ',' + asset.type;
let sourceBundles = [];
manualReachable.forEach(id => {
sourceBundles.push(nullthrows(bundleRoots.get(assets[id]))[0]);
});

if (!manualSharedMap.has(manualSharedBundleKey)) {
let firstSourceBundle = nullthrows(
bundleGraph.getNode(sourceBundles[0]),
);
invariant(firstSourceBundle !== 'root');

if (!bundle.assets.has(asset)) {
bundle = createBundle({
target: firstSourceBundle.target,
type: firstSourceBundle.type,
env: firstSourceBundle.env,
manualSharedBundle: manualSharedObject?.name,
});
bundle.sourceBundles = new Set(sourceBundles);
bundle.assets.add(asset);
bundle.size += asset.stats.size;
}
bundleId = bundleGraph.addNode(bundle);
manualSharedMap.set(manualSharedBundleKey, bundleId);
} else {
bundleId = nullthrows(manualSharedMap.get(manualSharedBundleKey));
bundle = nullthrows(bundleGraph.getNode(bundleId));
invariant(
bundle != null && bundle !== 'root',
'We tried to use the root incorrectly',
);

for (let s of sourceBundles) {
if (s != bundleId) {
bundle.sourceBundles.add(s);
if (!bundle.assets.has(asset)) {
bundle.assets.add(asset);
bundle.size += asset.stats.size;
}
}
}

for (let sourceBundleId of sourceBundles) {
if (bundleId !== sourceBundleId) {
bundleGraph.addEdge(sourceBundleId, bundleId);
for (let s of sourceBundles) {
if (s != bundleId) {
bundle.sourceBundles.add(s);
}
}
}
for (let sourceBundleId of sourceBundles) {
if (bundleId !== sourceBundleId) {
bundleGraph.addEdge(sourceBundleId, bundleId);
}
}
}

dependencyBundleGraph.addNodeByContentKeyIfNeeded(String(bundleId), {
value: bundle,
type: 'bundle',
});
continue;
dependencyBundleGraph.addNodeByContentKeyIfNeeded(String(bundleId), {
value: bundle,
type: 'bundle',
});
}
if (reachable.empty() || manualSharedObject.active == null) {
continue;
}
}

// Finally, filter out bundleRoots (bundles) from this assets
Expand Down Expand Up @@ -1745,6 +1784,12 @@ const CONFIG_SCHEMA: SchemaEntity = {
parent: {
type: 'string',
},
active: {
type: 'array',
items: {
type: 'string',
},
},
split: {
type: 'number',
},
Expand Down
8 changes: 4 additions & 4 deletions packages/core/integration-tests/test/bundler.js
Original file line number Diff line number Diff line change
Expand Up @@ -1566,7 +1566,7 @@ describe('bundler', function () {
}
index.js:
import('./foo');
import('./activeSource');
import('./bar');
export default 1;
Expand Down Expand Up @@ -1599,7 +1599,7 @@ describe('bundler', function () {
assets: ['activeSource.js'],
},
{
assets: ['a.js', 'b.js'],
assets: ['vendor.js', 'b.js'],
},
{
assets: ['bar.js', 'b.js'], // b is duplicated because 'bar' is not an 'Active' for this MSB
Expand Down Expand Up @@ -1667,10 +1667,10 @@ describe('bundler', function () {
//assert that bar and bazz share b, despite b being a "manual asset"
assertBundles(b, [
{
assets: ['foo.js'],
assets: ['activeSource.js'],
},
{
assets: ['a.js', 'b.js'],
assets: ['vendor.js', 'b.js'],
},
{
assets: ['bar.js'],
Expand Down

0 comments on commit 1be1574

Please sign in to comment.