Son CV dans un terminal web en Javascript!
https://terminal-cv.gregandev.fr
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1441 lines
53 KiB
1441 lines
53 KiB
"use strict";
|
|
|
|
Object.defineProperty(exports, "__esModule", {
|
|
value: true
|
|
});
|
|
exports.default = exports.bundleGraphEdgeTypes = void 0;
|
|
|
|
function _assert() {
|
|
const data = _interopRequireDefault(require("assert"));
|
|
|
|
_assert = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _nullthrows() {
|
|
const data = _interopRequireDefault(require("nullthrows"));
|
|
|
|
_nullthrows = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _graph() {
|
|
const data = require("@parcel/graph");
|
|
|
|
_graph = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _hash() {
|
|
const data = require("@parcel/hash");
|
|
|
|
_hash = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
function _utils() {
|
|
const data = require("@parcel/utils");
|
|
|
|
_utils = function () {
|
|
return data;
|
|
};
|
|
|
|
return data;
|
|
}
|
|
|
|
var _types = require("./types");
|
|
|
|
var _utils2 = require("./utils");
|
|
|
|
var _Environment = require("./public/Environment");
|
|
|
|
var _projectPath = require("./projectPath");
|
|
|
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
|
|
const bundleGraphEdgeTypes = {
|
|
// A lack of an edge type indicates to follow the edge while traversing
|
|
// the bundle's contents, e.g. `bundle.traverse()` during packaging.
|
|
null: 1,
|
|
// Used for constant-time checks of presence of a dependency or asset in a bundle,
|
|
// avoiding bundle traversal in cases like `isAssetInAncestors`
|
|
contains: 2,
|
|
// Connections between bundles and bundle groups, for quick traversal of the
|
|
// bundle hierarchy.
|
|
bundle: 3,
|
|
// When dependency -> asset: Indicates that the asset a dependency references
|
|
// is contained in another bundle.
|
|
// When dependency -> bundle: Indicates the bundle is necessary for any bundles
|
|
// with the dependency.
|
|
// When bundle -> bundle: Indicates the target bundle is necessary for the
|
|
// source bundle.
|
|
// This type prevents referenced assets from being traversed from dependencies
|
|
// along the untyped edge, and enables traversal to referenced bundles that are
|
|
// not directly connected to bundle group nodes.
|
|
references: 4,
|
|
// Signals that the dependency is internally resolvable via the bundle's ancestry,
|
|
// and that the bundle connected to the dependency is not necessary for the source bundle.
|
|
internal_async: 5
|
|
};
|
|
exports.bundleGraphEdgeTypes = bundleGraphEdgeTypes;
|
|
|
|
function makeReadOnlySet(set) {
|
|
return new Proxy(set, {
|
|
get(target, property) {
|
|
if (property === 'delete' || property === 'add' || property === 'clear') {
|
|
return undefined;
|
|
} else {
|
|
// $FlowFixMe[incompatible-type]
|
|
let value = target[property];
|
|
return typeof value === 'function' ? value.bind(target) : value;
|
|
}
|
|
}
|
|
|
|
});
|
|
}
|
|
|
|
class BundleGraph {
|
|
// TODO: These hashes are being invalidated in mutative methods, but this._graph is not a private
|
|
// property so it is possible to reach in and mutate the graph without invalidating these hashes.
|
|
// It needs to be exposed in BundlerRunner for now based on how applying runtimes works and the
|
|
// BundlerRunner takes care of invalidating hashes when runtimes are applied, but this is not ideal.
|
|
_targetEntryRoots = new Map();
|
|
|
|
constructor({
|
|
graph,
|
|
publicIdByAssetId,
|
|
assetPublicIds,
|
|
bundleContentHashes,
|
|
symbolPropagationRan
|
|
}) {
|
|
this._graph = graph;
|
|
this._assetPublicIds = assetPublicIds;
|
|
this._publicIdByAssetId = publicIdByAssetId;
|
|
this._bundleContentHashes = bundleContentHashes;
|
|
this._symbolPropagationRan = symbolPropagationRan;
|
|
}
|
|
|
|
static fromAssetGraph(assetGraph, publicIdByAssetId = new Map(), assetPublicIds = new Set()) {
|
|
let graph = new (_graph().ContentGraph)();
|
|
let assetGroupIds = new Set();
|
|
let assetGraphNodeIdToBundleGraphNodeId = new Map();
|
|
let assetGraphRootNode = assetGraph.rootNodeId != null ? assetGraph.getNode(assetGraph.rootNodeId) : null;
|
|
(0, _assert().default)(assetGraphRootNode != null && assetGraphRootNode.type === 'root');
|
|
|
|
for (let [nodeId, node] of assetGraph.nodes) {
|
|
if (node.type === 'asset') {
|
|
let {
|
|
id: assetId
|
|
} = node.value; // Generate a new, short public id for this asset to use.
|
|
// If one already exists, use it.
|
|
|
|
let publicId = publicIdByAssetId.get(assetId);
|
|
|
|
if (publicId == null) {
|
|
publicId = (0, _utils2.getPublicId)(assetId, existing => assetPublicIds.has(existing));
|
|
publicIdByAssetId.set(assetId, publicId);
|
|
assetPublicIds.add(publicId);
|
|
}
|
|
} // Don't copy over asset groups into the bundle graph.
|
|
|
|
|
|
if (node.type === 'asset_group') {
|
|
assetGroupIds.add(nodeId);
|
|
} else {
|
|
let bundleGraphNodeId = graph.addNodeByContentKey(node.id, node);
|
|
|
|
if (node.id === (assetGraphRootNode === null || assetGraphRootNode === void 0 ? void 0 : assetGraphRootNode.id)) {
|
|
graph.setRootNodeId(bundleGraphNodeId);
|
|
}
|
|
|
|
assetGraphNodeIdToBundleGraphNodeId.set(nodeId, bundleGraphNodeId);
|
|
}
|
|
}
|
|
|
|
for (let edge of assetGraph.getAllEdges()) {
|
|
let fromIds;
|
|
|
|
if (assetGroupIds.has(edge.from)) {
|
|
fromIds = [...assetGraph.getNodeIdsConnectedTo(edge.from, bundleGraphEdgeTypes.null)];
|
|
} else {
|
|
fromIds = [edge.from];
|
|
}
|
|
|
|
for (let from of fromIds) {
|
|
if (assetGroupIds.has(edge.to)) {
|
|
for (let to of assetGraph.getNodeIdsConnectedFrom(edge.to, bundleGraphEdgeTypes.null)) {
|
|
graph.addEdge((0, _nullthrows().default)(assetGraphNodeIdToBundleGraphNodeId.get(from)), (0, _nullthrows().default)(assetGraphNodeIdToBundleGraphNodeId.get(to)));
|
|
}
|
|
} else {
|
|
graph.addEdge((0, _nullthrows().default)(assetGraphNodeIdToBundleGraphNodeId.get(from)), (0, _nullthrows().default)(assetGraphNodeIdToBundleGraphNodeId.get(edge.to)));
|
|
}
|
|
}
|
|
}
|
|
|
|
return new BundleGraph({
|
|
graph,
|
|
assetPublicIds,
|
|
bundleContentHashes: new Map(),
|
|
publicIdByAssetId,
|
|
symbolPropagationRan: assetGraph.symbolPropagationRan
|
|
});
|
|
}
|
|
|
|
serialize() {
|
|
return {
|
|
$$raw: true,
|
|
graph: this._graph.serialize(),
|
|
assetPublicIds: this._assetPublicIds,
|
|
bundleContentHashes: this._bundleContentHashes,
|
|
publicIdByAssetId: this._publicIdByAssetId,
|
|
symbolPropagationRan: this._symbolPropagationRan
|
|
};
|
|
}
|
|
|
|
static deserialize(serialized) {
|
|
return new BundleGraph({
|
|
graph: _graph().ContentGraph.deserialize(serialized.graph),
|
|
assetPublicIds: serialized.assetPublicIds,
|
|
bundleContentHashes: serialized.bundleContentHashes,
|
|
publicIdByAssetId: serialized.publicIdByAssetId,
|
|
symbolPropagationRan: serialized.symbolPropagationRan
|
|
});
|
|
}
|
|
|
|
addAssetToBundle(asset, bundle) {
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
this._graph.addEdge(bundleNodeId, this._graph.getNodeIdByContentKey(asset.id), bundleGraphEdgeTypes.contains);
|
|
|
|
this._graph.addEdge(bundleNodeId, this._graph.getNodeIdByContentKey(asset.id));
|
|
|
|
let dependencies = this.getDependencies(asset);
|
|
|
|
for (let dependency of dependencies) {
|
|
let dependencyNodeId = this._graph.getNodeIdByContentKey(dependency.id);
|
|
|
|
this._graph.addEdge(bundleNodeId, dependencyNodeId, bundleGraphEdgeTypes.contains);
|
|
|
|
for (let [bundleGroupNodeId, bundleGroupNode] of this._graph.getNodeIdsConnectedFrom(dependencyNodeId).map(id => [id, (0, _nullthrows().default)(this._graph.getNode(id))]).filter(([, node]) => node.type === 'bundle_group')) {
|
|
(0, _assert().default)(bundleGroupNode.type === 'bundle_group');
|
|
|
|
this._graph.addEdge(bundleNodeId, bundleGroupNodeId, bundleGraphEdgeTypes.bundle);
|
|
} // If the dependency references a target bundle, add a reference edge from
|
|
// the source bundle to the dependency for easy traversal.
|
|
// TODO: Consider bundle being created from dependency
|
|
|
|
|
|
if (this._graph.getNodeIdsConnectedFrom(dependencyNodeId, bundleGraphEdgeTypes.references).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).some(node => node.type === 'bundle')) {
|
|
this._graph.addEdge(bundleNodeId, dependencyNodeId, bundleGraphEdgeTypes.references);
|
|
}
|
|
}
|
|
}
|
|
|
|
addAssetGraphToBundle(asset, bundle, shouldSkipDependency = d => this.isDependencySkipped(d)) {
|
|
let assetNodeId = this._graph.getNodeIdByContentKey(asset.id);
|
|
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id); // The root asset should be reached directly from the bundle in traversal.
|
|
// Its children will be traversed from there.
|
|
|
|
|
|
this._graph.addEdge(bundleNodeId, assetNodeId);
|
|
|
|
this._graph.traverse((nodeId, _, actions) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type === 'bundle_group') {
|
|
actions.skipChildren();
|
|
return;
|
|
}
|
|
|
|
if (node.type === 'dependency' && shouldSkipDependency(node.value)) {
|
|
actions.skipChildren();
|
|
return;
|
|
}
|
|
|
|
if (node.type === 'asset' || node.type === 'dependency') {
|
|
this._graph.addEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.contains);
|
|
}
|
|
|
|
if (node.type === 'dependency') {
|
|
for (let [bundleGroupNodeId, bundleGroupNode] of this._graph.getNodeIdsConnectedFrom(nodeId).map(id => [id, (0, _nullthrows().default)(this._graph.getNode(id))]).filter(([, node]) => node.type === 'bundle_group')) {
|
|
(0, _assert().default)(bundleGroupNode.type === 'bundle_group');
|
|
|
|
this._graph.addEdge(bundleNodeId, bundleGroupNodeId, bundleGraphEdgeTypes.bundle);
|
|
} // If the dependency references a target bundle, add a reference edge from
|
|
// the source bundle to the dependency for easy traversal.
|
|
|
|
|
|
if (this._graph.getNodeIdsConnectedFrom(nodeId, bundleGraphEdgeTypes.references).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).some(node => node.type === 'bundle')) {
|
|
this._graph.addEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.references);
|
|
|
|
this.markDependencyReferenceable(node.value); //all bundles that have this dependency need to have an edge from bundle to that dependency
|
|
}
|
|
}
|
|
}, assetNodeId);
|
|
|
|
this._bundleContentHashes.delete(bundle.id);
|
|
}
|
|
|
|
markDependencyReferenceable(dependency) {
|
|
for (let bundle of this.getBundlesWithDependency(dependency)) {
|
|
this._graph.addEdge(this._graph.getNodeIdByContentKey(bundle.id), this._graph.getNodeIdByContentKey(dependency.id), bundleGraphEdgeTypes.references);
|
|
}
|
|
}
|
|
|
|
addEntryToBundle(asset, bundle, shouldSkipDependency) {
|
|
this.addAssetGraphToBundle(asset, bundle, shouldSkipDependency);
|
|
|
|
if (!bundle.entryAssetIds.includes(asset.id)) {
|
|
bundle.entryAssetIds.push(asset.id);
|
|
}
|
|
}
|
|
|
|
internalizeAsyncDependency(bundle, dependency) {
|
|
if (dependency.priority === _types.Priority.sync) {
|
|
throw new Error('Expected an async dependency');
|
|
} // It's possible for internalized async dependencies to not have
|
|
// reference edges and still have untyped edges.
|
|
// TODO: Maybe don't use internalized async edges at all?
|
|
|
|
|
|
let dependencyNodeId = this._graph.getNodeIdByContentKey(dependency.id);
|
|
|
|
let resolved = this.getResolvedAsset(dependency);
|
|
|
|
if (resolved) {
|
|
let resolvedNodeId = this._graph.getNodeIdByContentKey(resolved.id);
|
|
|
|
if (!this._graph.hasEdge(dependencyNodeId, resolvedNodeId, bundleGraphEdgeTypes.references)) {
|
|
this._graph.addEdge(dependencyNodeId, resolvedNodeId, bundleGraphEdgeTypes.references);
|
|
|
|
this._graph.removeEdge(dependencyNodeId, resolvedNodeId);
|
|
}
|
|
}
|
|
|
|
this._graph.addEdge(this._graph.getNodeIdByContentKey(bundle.id), this._graph.getNodeIdByContentKey(dependency.id), bundleGraphEdgeTypes.internal_async);
|
|
|
|
this.removeExternalDependency(bundle, dependency);
|
|
}
|
|
|
|
isDependencySkipped(dependency) {
|
|
let node = this._graph.getNodeByContentKey(dependency.id);
|
|
|
|
(0, _assert().default)(node && node.type === 'dependency');
|
|
return !!node.hasDeferred || node.excluded;
|
|
}
|
|
|
|
getParentBundlesOfBundleGroup(bundleGroup) {
|
|
return this._graph.getNodeIdsConnectedTo(this._graph.getNodeIdByContentKey((0, _utils2.getBundleGroupId)(bundleGroup)), bundleGraphEdgeTypes.bundle).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'bundle').map(node => {
|
|
(0, _assert().default)(node.type === 'bundle');
|
|
return node.value;
|
|
});
|
|
}
|
|
|
|
resolveAsyncDependency(dependency, bundle) {
|
|
let depNodeId = this._graph.getNodeIdByContentKey(dependency.id);
|
|
|
|
let bundleNodeId = bundle != null ? this._graph.getNodeIdByContentKey(bundle.id) : null;
|
|
|
|
if (bundleNodeId != null && this._graph.hasEdge(bundleNodeId, depNodeId, bundleGraphEdgeTypes.internal_async)) {
|
|
let referencedAssetNodeIds = this._graph.getNodeIdsConnectedFrom(depNodeId, bundleGraphEdgeTypes.references);
|
|
|
|
let resolved;
|
|
|
|
if (referencedAssetNodeIds.length === 0) {
|
|
resolved = this.getResolvedAsset(dependency, bundle);
|
|
} else if (referencedAssetNodeIds.length === 1) {
|
|
let referencedAssetNode = this._graph.getNode(referencedAssetNodeIds[0]); // If a referenced asset already exists, resolve this dependency to it.
|
|
|
|
|
|
(0, _assert().default)((referencedAssetNode === null || referencedAssetNode === void 0 ? void 0 : referencedAssetNode.type) === 'asset');
|
|
resolved = referencedAssetNode.value;
|
|
} else {
|
|
throw new Error('Dependencies can only reference one asset');
|
|
}
|
|
|
|
if (resolved == null) {
|
|
return;
|
|
} else {
|
|
return {
|
|
type: 'asset',
|
|
value: resolved
|
|
};
|
|
}
|
|
}
|
|
|
|
let node = this._graph.getNodeIdsConnectedFrom(this._graph.getNodeIdByContentKey(dependency.id)).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).find(node => node.type === 'bundle_group');
|
|
|
|
if (node == null) {
|
|
return;
|
|
}
|
|
|
|
(0, _assert().default)(node.type === 'bundle_group');
|
|
return {
|
|
type: 'bundle_group',
|
|
value: node.value
|
|
};
|
|
} // eslint-disable-next-line no-unused-vars
|
|
|
|
|
|
getReferencedBundle(dependency) {
|
|
let dependencyNodeId = this._graph.getNodeIdByContentKey(dependency.id); // If this dependency is async, there will be a bundle group attached to it.
|
|
|
|
|
|
let node = this._graph.getNodeIdsConnectedFrom(dependencyNodeId).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).find(node => node.type === 'bundle_group');
|
|
|
|
if (node != null) {
|
|
(0, _assert().default)(node.type === 'bundle_group');
|
|
return this.getBundlesInBundleGroup(node.value, {
|
|
includeInline: true
|
|
}).find(b => {
|
|
let mainEntryId = b.entryAssetIds[b.entryAssetIds.length - 1];
|
|
return mainEntryId != null && node.value.entryAssetId === mainEntryId;
|
|
});
|
|
} // Otherwise, find an attached bundle via a reference edge (e.g. from createAssetReference).
|
|
|
|
|
|
let bundleNode = this._graph.getNodeIdsConnectedFrom(dependencyNodeId, bundleGraphEdgeTypes.references).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).find(node => node.type === 'bundle');
|
|
|
|
if (bundleNode) {
|
|
(0, _assert().default)(bundleNode.type === 'bundle');
|
|
return bundleNode.value;
|
|
}
|
|
}
|
|
|
|
removeAssetGraphFromBundle(asset, bundle) {
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
let assetNodeId = this._graph.getNodeIdByContentKey(asset.id); // Remove all contains edges from the bundle to the nodes in the asset's
|
|
// subgraph.
|
|
|
|
|
|
this._graph.traverse((nodeId, context, actions) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type === 'bundle_group') {
|
|
actions.skipChildren();
|
|
return;
|
|
}
|
|
|
|
if (node.type !== 'dependency' && node.type !== 'asset') {
|
|
return;
|
|
}
|
|
|
|
if (this._graph.hasEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.contains)) {
|
|
this._graph.removeEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.contains, // Removing this contains edge should not orphan the connected node. This
|
|
// is disabled for performance reasons as these edges are removed as part
|
|
// of a traversal, and checking for orphans becomes quite expensive in
|
|
// aggregate.
|
|
false
|
|
/* removeOrphans */
|
|
);
|
|
} else {
|
|
actions.skipChildren();
|
|
}
|
|
|
|
if (node.type === 'asset' && this._graph.hasEdge(bundleNodeId, nodeId)) {
|
|
// Remove the untyped edge from the bundle to the node (it's an entry)
|
|
this._graph.removeEdge(bundleNodeId, nodeId);
|
|
|
|
let entryIndex = bundle.entryAssetIds.indexOf(node.value.id);
|
|
|
|
if (entryIndex >= 0) {
|
|
// Shared bundles have untyped edges to their asset graphs but don't
|
|
// have entry assets. For those that have entry asset ids, remove them.
|
|
bundle.entryAssetIds.splice(entryIndex, 1);
|
|
}
|
|
}
|
|
|
|
if (node.type === 'dependency') {
|
|
this.removeExternalDependency(bundle, node.value);
|
|
|
|
if (this._graph.hasEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.references)) {
|
|
this._graph.addEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.references);
|
|
|
|
this.markDependencyReferenceable(node.value);
|
|
}
|
|
|
|
if (this._graph.hasEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.internal_async)) {
|
|
this._graph.removeEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.internal_async);
|
|
}
|
|
}
|
|
}, assetNodeId); // Remove bundle node if it no longer has any entry assets
|
|
|
|
|
|
if (this._graph.getNodeIdsConnectedFrom(bundleNodeId).length === 0) {
|
|
this.removeBundle(bundle);
|
|
}
|
|
|
|
this._bundleContentHashes.delete(bundle.id);
|
|
}
|
|
|
|
removeBundle(bundle) {
|
|
// Remove bundle node if it no longer has any entry assets
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
let bundleGroupNodeIds = this._graph.getNodeIdsConnectedTo(bundleNodeId, bundleGraphEdgeTypes.bundle);
|
|
|
|
this._graph.removeNode(bundleNodeId);
|
|
|
|
let removedBundleGroups = new Set(); // Remove bundle group node if it no longer has any bundles
|
|
|
|
for (let bundleGroupNodeId of bundleGroupNodeIds) {
|
|
let bundleGroupNode = (0, _nullthrows().default)(this._graph.getNode(bundleGroupNodeId));
|
|
(0, _assert().default)(bundleGroupNode.type === 'bundle_group');
|
|
let bundleGroup = bundleGroupNode.value;
|
|
|
|
if ( // If the bundle group's entry asset belongs to this bundle, the group
|
|
// was created because of this bundle. Remove the group.
|
|
bundle.entryAssetIds.includes(bundleGroup.entryAssetId) || // If the bundle group is now empty, remove it.
|
|
this.getBundlesInBundleGroup(bundleGroup, {
|
|
includeInline: true
|
|
}).length === 0) {
|
|
removedBundleGroups.add(bundleGroup);
|
|
this.removeBundleGroup(bundleGroup);
|
|
}
|
|
}
|
|
|
|
this._bundleContentHashes.delete(bundle.id);
|
|
|
|
return removedBundleGroups;
|
|
}
|
|
|
|
removeBundleGroup(bundleGroup) {
|
|
let bundleGroupNode = (0, _nullthrows().default)(this._graph.getNodeByContentKey((0, _utils2.getBundleGroupId)(bundleGroup)));
|
|
(0, _assert().default)(bundleGroupNode.type === 'bundle_group');
|
|
let bundlesInGroup = this.getBundlesInBundleGroup(bundleGroupNode.value, {
|
|
includeInline: true
|
|
});
|
|
|
|
for (let bundle of bundlesInGroup) {
|
|
if (this.getBundleGroupsContainingBundle(bundle).length === 1) {
|
|
let removedBundleGroups = this.removeBundle(bundle);
|
|
|
|
if (removedBundleGroups.has(bundleGroup)) {
|
|
// This function can be reentered through removeBundle above. In the case this
|
|
// bundle group has already been removed, stop.
|
|
return;
|
|
}
|
|
}
|
|
} // This function can be reentered through removeBundle above. In this case,
|
|
// the node may already been removed.
|
|
|
|
|
|
if (this._graph.hasContentKey(bundleGroupNode.id)) {
|
|
this._graph.removeNode(this._graph.getNodeIdByContentKey(bundleGroupNode.id));
|
|
}
|
|
|
|
(0, _assert().default)(bundlesInGroup.every(bundle => this.getBundleGroupsContainingBundle(bundle).length > 0));
|
|
}
|
|
|
|
removeExternalDependency(bundle, dependency) {
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
for (let bundleGroupNode of this._graph.getNodeIdsConnectedFrom(this._graph.getNodeIdByContentKey(dependency.id)).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'bundle_group')) {
|
|
let bundleGroupNodeId = this._graph.getNodeIdByContentKey(bundleGroupNode.id);
|
|
|
|
if (!this._graph.hasEdge(bundleNodeId, bundleGroupNodeId, bundleGraphEdgeTypes.bundle)) {
|
|
continue;
|
|
}
|
|
|
|
let inboundDependencies = this._graph.getNodeIdsConnectedTo(bundleGroupNodeId).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'dependency').map(node => {
|
|
(0, _assert().default)(node.type === 'dependency');
|
|
return node.value;
|
|
}); // If every inbound dependency to this bundle group does not belong to this bundle,
|
|
// or the dependency is internal to the bundle, then the connection between
|
|
// this bundle and the group is safe to remove.
|
|
|
|
|
|
if (inboundDependencies.every(dependency => !this.bundleHasDependency(bundle, dependency) || this._graph.hasEdge(bundleNodeId, this._graph.getNodeIdByContentKey(dependency.id), bundleGraphEdgeTypes.internal_async))) {
|
|
this._graph.removeEdge(bundleNodeId, bundleGroupNodeId, bundleGraphEdgeTypes.bundle);
|
|
}
|
|
}
|
|
}
|
|
|
|
createAssetReference(dependency, asset, bundle) {
|
|
let dependencyId = this._graph.getNodeIdByContentKey(dependency.id);
|
|
|
|
let assetId = this._graph.getNodeIdByContentKey(asset.id);
|
|
|
|
let bundleId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
this._graph.addEdge(dependencyId, assetId, bundleGraphEdgeTypes.references);
|
|
|
|
this._graph.addEdge(dependencyId, bundleId, bundleGraphEdgeTypes.references);
|
|
|
|
this.markDependencyReferenceable(dependency);
|
|
|
|
if (this._graph.hasEdge(dependencyId, assetId)) {
|
|
this._graph.removeEdge(dependencyId, assetId);
|
|
}
|
|
}
|
|
|
|
createBundleReference(from, to) {
|
|
this._graph.addEdge(this._graph.getNodeIdByContentKey(from.id), this._graph.getNodeIdByContentKey(to.id), bundleGraphEdgeTypes.references);
|
|
}
|
|
|
|
getBundlesWithAsset(asset) {
|
|
return this._graph.getNodeIdsConnectedTo(this._graph.getNodeIdByContentKey(asset.id), bundleGraphEdgeTypes.contains).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'bundle').map(node => {
|
|
(0, _assert().default)(node.type === 'bundle');
|
|
return node.value;
|
|
});
|
|
}
|
|
|
|
getBundlesWithDependency(dependency) {
|
|
return this._graph.getNodeIdsConnectedTo((0, _nullthrows().default)(this._graph.getNodeIdByContentKey(dependency.id)), bundleGraphEdgeTypes.contains).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'bundle').map(node => {
|
|
(0, _assert().default)(node.type === 'bundle');
|
|
return node.value;
|
|
});
|
|
}
|
|
|
|
getDependencyAssets(dependency) {
|
|
return this._graph.getNodeIdsConnectedFrom(this._graph.getNodeIdByContentKey(dependency.id)).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'asset').map(node => {
|
|
(0, _assert().default)(node.type === 'asset');
|
|
return node.value;
|
|
});
|
|
}
|
|
|
|
getResolvedAsset(dep, bundle) {
|
|
let assets = this.getDependencyAssets(dep);
|
|
let firstAsset = assets[0];
|
|
let resolved = // If no bundle is specified, use the first concrete asset.
|
|
bundle == null ? firstAsset : // Otherwise, find the first asset that belongs to this bundle.
|
|
assets.find(asset => this.bundleHasAsset(bundle, asset)) || firstAsset; // If a resolution still hasn't been found, return the first referenced asset.
|
|
|
|
if (resolved == null) {
|
|
this._graph.traverse((nodeId, _, traversal) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type === 'asset') {
|
|
resolved = node.value;
|
|
traversal.stop();
|
|
} else if (node.id !== dep.id) {
|
|
traversal.skipChildren();
|
|
}
|
|
}, this._graph.getNodeIdByContentKey(dep.id), bundleGraphEdgeTypes.references);
|
|
}
|
|
|
|
return resolved;
|
|
}
|
|
|
|
getDependencies(asset) {
|
|
let nodeId = this._graph.getNodeIdByContentKey(asset.id);
|
|
|
|
return this._graph.getNodeIdsConnectedFrom(nodeId).map(id => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(id));
|
|
(0, _assert().default)(node.type === 'dependency');
|
|
return node.value;
|
|
});
|
|
}
|
|
|
|
traverseAssets(bundle, visit) {
|
|
return this.traverseBundle(bundle, (0, _graph().mapVisitor)(node => node.type === 'asset' ? node.value : null, visit));
|
|
}
|
|
|
|
isAssetReferenced(bundle, asset) {
|
|
let assetNodeId = (0, _nullthrows().default)(this._graph.getNodeIdByContentKey(asset.id));
|
|
|
|
if (this._graph.getNodeIdsConnectedTo(assetNodeId, bundleGraphEdgeTypes.references).map(id => this._graph.getNode(id)).some(node => (node === null || node === void 0 ? void 0 : node.type) === 'dependency' && node.value.priority === _types.Priority.lazy && node.value.specifierType !== _types.SpecifierType.url)) {
|
|
// If this asset is referenced by any async dependency, it's referenced.
|
|
return true;
|
|
}
|
|
|
|
let dependencies = this._graph.getNodeIdsConnectedTo(assetNodeId).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'dependency').map(node => {
|
|
(0, _assert().default)(node.type === 'dependency');
|
|
return node.value;
|
|
});
|
|
|
|
const bundleHasReference = bundle => {
|
|
return !this.bundleHasAsset(bundle, asset) && dependencies.some(dependency => this.bundleHasDependency(bundle, dependency));
|
|
};
|
|
|
|
let visitedBundles = new Set();
|
|
let siblingBundles = new Set(this.getBundleGroupsContainingBundle(bundle).flatMap(bundleGroup => this.getBundlesInBundleGroup(bundleGroup, {
|
|
includeInline: true
|
|
}))); // Check if any of this bundle's descendants, referencers, bundles referenced
|
|
// by referencers, or descendants of its referencers use the asset without
|
|
// an explicit reference edge. This can happen if e.g. the asset has been
|
|
// deduplicated.
|
|
|
|
return [...siblingBundles].some(referencer => {
|
|
let isReferenced = false;
|
|
this.traverseBundles((descendant, _, actions) => {
|
|
if (descendant.id === bundle.id) {
|
|
return;
|
|
}
|
|
|
|
if (visitedBundles.has(descendant)) {
|
|
actions.skipChildren();
|
|
return;
|
|
}
|
|
|
|
visitedBundles.add(descendant);
|
|
|
|
if (descendant.type !== bundle.type || descendant.env.context !== bundle.env.context) {
|
|
actions.skipChildren();
|
|
return;
|
|
}
|
|
|
|
if (bundleHasReference(descendant)) {
|
|
isReferenced = true;
|
|
actions.stop();
|
|
}
|
|
}, referencer);
|
|
return isReferenced;
|
|
});
|
|
}
|
|
|
|
hasParentBundleOfType(bundle, type) {
|
|
let parents = this.getParentBundles(bundle);
|
|
return parents.length > 0 && parents.every(parent => parent.type === type);
|
|
}
|
|
|
|
getParentBundles(bundle) {
|
|
let parentBundles = new Set();
|
|
|
|
for (let bundleGroup of this.getBundleGroupsContainingBundle(bundle)) {
|
|
for (let parentBundle of this.getParentBundlesOfBundleGroup(bundleGroup)) {
|
|
parentBundles.add(parentBundle);
|
|
}
|
|
}
|
|
|
|
return [...parentBundles];
|
|
}
|
|
|
|
isAssetReachableFromBundle(asset, bundle) {
|
|
// If a bundle's environment is isolated, it can't access assets present
|
|
// in any ancestor bundles. Don't consider any assets reachable.
|
|
if (_Environment.ISOLATED_ENVS.has(bundle.env.context) || !bundle.isSplittable || bundle.bundleBehavior === _types.BundleBehavior.isolated || bundle.bundleBehavior === _types.BundleBehavior.inline) {
|
|
return false;
|
|
} // For an asset to be reachable from a bundle, it must either exist in a sibling bundle,
|
|
// or in an ancestor bundle group reachable from all parent bundles.
|
|
|
|
|
|
let bundleGroups = this.getBundleGroupsContainingBundle(bundle);
|
|
return bundleGroups.every(bundleGroup => {
|
|
// If the asset is in any sibling bundles of the original bundle, it is reachable.
|
|
let bundles = this.getBundlesInBundleGroup(bundleGroup);
|
|
|
|
if (bundles.some(b => b.id !== bundle.id && b.bundleBehavior !== _types.BundleBehavior.isolated && b.bundleBehavior !== _types.BundleBehavior.inline && this.bundleHasAsset(b, asset))) {
|
|
return true;
|
|
} // Get a list of parent bundle nodes pointing to the bundle group
|
|
|
|
|
|
let parentBundleNodes = this._graph.getNodeIdsConnectedTo(this._graph.getNodeIdByContentKey((0, _utils2.getBundleGroupId)(bundleGroup)), bundleGraphEdgeTypes.bundle); // Check that every parent bundle has a bundle group in its ancestry that contains the asset.
|
|
|
|
|
|
return parentBundleNodes.every(bundleNodeId => {
|
|
let bundleNode = (0, _nullthrows().default)(this._graph.getNode(bundleNodeId));
|
|
|
|
if (bundleNode.type !== 'bundle' || bundleNode.value.bundleBehavior === _types.BundleBehavior.isolated || bundleNode.value.bundleBehavior === _types.BundleBehavior.inline) {
|
|
return false;
|
|
}
|
|
|
|
let isReachable = true;
|
|
|
|
this._graph.traverseAncestors(bundleNodeId, (nodeId, ctx, actions) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId)); // If we've reached the root or a context change without
|
|
// finding this asset in the ancestry, it is not reachable.
|
|
|
|
if (node.type === 'root' || node.type === 'bundle' && (node.value.id === bundle.id || node.value.env.context !== bundle.env.context)) {
|
|
isReachable = false;
|
|
actions.stop();
|
|
return;
|
|
}
|
|
|
|
if (node.type === 'bundle_group') {
|
|
let childBundles = this.getBundlesInBundleGroup(node.value);
|
|
|
|
if (childBundles.some(b => b.id !== bundle.id && b.bundleBehavior !== _types.BundleBehavior.isolated && b.bundleBehavior !== _types.BundleBehavior.inline && this.bundleHasAsset(b, asset))) {
|
|
actions.skipChildren();
|
|
}
|
|
}
|
|
}, [bundleGraphEdgeTypes.references, bundleGraphEdgeTypes.bundle]);
|
|
|
|
return isReachable;
|
|
});
|
|
});
|
|
}
|
|
|
|
traverseBundle(bundle, visit) {
|
|
let entries = true;
|
|
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id); // A modified DFS traversal which traverses entry assets in the same order
|
|
// as their ids appear in `bundle.entryAssetIds`.
|
|
|
|
|
|
return this._graph.dfs({
|
|
visit: (0, _graph().mapVisitor)((nodeId, actions) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (nodeId === bundleNodeId) {
|
|
return;
|
|
}
|
|
|
|
if (node.type === 'dependency' || node.type === 'asset') {
|
|
if (this._graph.hasEdge(bundleNodeId, nodeId, bundleGraphEdgeTypes.contains)) {
|
|
return node;
|
|
}
|
|
}
|
|
|
|
actions.skipChildren();
|
|
}, visit),
|
|
startNodeId: bundleNodeId,
|
|
getChildren: nodeId => {
|
|
let children = this._graph.getNodeIdsConnectedFrom(nodeId).map(id => [id, (0, _nullthrows().default)(this._graph.getNode(id))]);
|
|
|
|
let sorted = entries && bundle.entryAssetIds.length > 0 ? children.sort(([, a], [, b]) => {
|
|
let aIndex = bundle.entryAssetIds.indexOf(a.id);
|
|
let bIndex = bundle.entryAssetIds.indexOf(b.id);
|
|
|
|
if (aIndex === bIndex) {
|
|
// If both don't exist in the entry asset list, or
|
|
// otherwise have the same index.
|
|
return 0;
|
|
} else if (aIndex === -1) {
|
|
return 1;
|
|
} else if (bIndex === -1) {
|
|
return -1;
|
|
}
|
|
|
|
return aIndex - bIndex;
|
|
}) : children;
|
|
entries = false;
|
|
return sorted.map(([id]) => id);
|
|
}
|
|
});
|
|
}
|
|
|
|
traverse(visit, start) {
|
|
return this._graph.filteredTraverse(nodeId => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type === 'asset' || node.type === 'dependency') {
|
|
return node;
|
|
}
|
|
}, visit, start ? this._graph.getNodeIdByContentKey(start.id) : undefined, // start with root
|
|
_graph().ALL_EDGE_TYPES);
|
|
}
|
|
|
|
getChildBundles(bundle) {
|
|
let siblings = new Set(this.getReferencedBundles(bundle));
|
|
let bundles = [];
|
|
this.traverseBundles((b, _, actions) => {
|
|
if (bundle.id === b.id) {
|
|
return;
|
|
}
|
|
|
|
if (!siblings.has(b)) {
|
|
bundles.push(b);
|
|
}
|
|
|
|
actions.skipChildren();
|
|
}, bundle);
|
|
return bundles;
|
|
}
|
|
|
|
traverseBundles(visit, startBundle) {
|
|
return this._graph.filteredTraverse(nodeId => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
return node.type === 'bundle' ? node.value : null;
|
|
}, visit, startBundle ? this._graph.getNodeIdByContentKey(startBundle.id) : null, [bundleGraphEdgeTypes.bundle, bundleGraphEdgeTypes.references]);
|
|
}
|
|
|
|
getBundles(opts) {
|
|
let bundles = [];
|
|
this.traverseBundles(bundle => {
|
|
if (opts !== null && opts !== void 0 && opts.includeInline || bundle.bundleBehavior !== _types.BundleBehavior.inline) {
|
|
bundles.push(bundle);
|
|
}
|
|
});
|
|
return bundles;
|
|
}
|
|
|
|
getTotalSize(asset) {
|
|
let size = 0;
|
|
|
|
this._graph.traverse((nodeId, _, actions) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type === 'bundle_group') {
|
|
actions.skipChildren();
|
|
return;
|
|
}
|
|
|
|
if (node.type === 'asset') {
|
|
size += node.value.stats.size;
|
|
}
|
|
}, this._graph.getNodeIdByContentKey(asset.id));
|
|
|
|
return size;
|
|
}
|
|
|
|
getReferencingBundles(bundle) {
|
|
let referencingBundles = new Set();
|
|
|
|
this._graph.traverseAncestors(this._graph.getNodeIdByContentKey(bundle.id), nodeId => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type === 'bundle' && node.value.id !== bundle.id) {
|
|
referencingBundles.add(node.value);
|
|
}
|
|
}, bundleGraphEdgeTypes.references);
|
|
|
|
return [...referencingBundles];
|
|
}
|
|
|
|
getBundleGroupsContainingBundle(bundle) {
|
|
let bundleGroups = new Set();
|
|
|
|
for (let currentBundle of [bundle, ...this.getReferencingBundles(bundle)]) {
|
|
for (let bundleGroup of this.getDirectParentBundleGroups(currentBundle)) {
|
|
bundleGroups.add(bundleGroup);
|
|
}
|
|
}
|
|
|
|
return [...bundleGroups];
|
|
}
|
|
|
|
getDirectParentBundleGroups(bundle) {
|
|
return this._graph.getNodeIdsConnectedTo((0, _nullthrows().default)(this._graph.getNodeIdByContentKey(bundle.id)), bundleGraphEdgeTypes.bundle).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(node => node.type === 'bundle_group').map(node => {
|
|
(0, _assert().default)(node.type === 'bundle_group');
|
|
return node.value;
|
|
});
|
|
}
|
|
|
|
getBundlesInBundleGroup(bundleGroup, opts) {
|
|
let bundles = new Set();
|
|
|
|
for (let bundleNodeId of this._graph.getNodeIdsConnectedFrom(this._graph.getNodeIdByContentKey((0, _utils2.getBundleGroupId)(bundleGroup)), bundleGraphEdgeTypes.bundle)) {
|
|
let bundleNode = (0, _nullthrows().default)(this._graph.getNode(bundleNodeId));
|
|
(0, _assert().default)(bundleNode.type === 'bundle');
|
|
let bundle = bundleNode.value;
|
|
|
|
if (opts !== null && opts !== void 0 && opts.includeInline || bundle.bundleBehavior !== _types.BundleBehavior.inline) {
|
|
bundles.add(bundle);
|
|
}
|
|
|
|
for (let referencedBundle of this.getReferencedBundles(bundle, {
|
|
includeInline: true
|
|
})) {
|
|
bundles.add(referencedBundle);
|
|
}
|
|
}
|
|
|
|
return [...bundles];
|
|
}
|
|
|
|
getReferencedBundles(bundle, opts) {
|
|
var _opts$recursive, _opts$includeInline;
|
|
|
|
let recursive = (_opts$recursive = opts === null || opts === void 0 ? void 0 : opts.recursive) !== null && _opts$recursive !== void 0 ? _opts$recursive : true;
|
|
let includeInline = (_opts$includeInline = opts === null || opts === void 0 ? void 0 : opts.includeInline) !== null && _opts$includeInline !== void 0 ? _opts$includeInline : false;
|
|
let referencedBundles = new Set();
|
|
|
|
this._graph.dfs({
|
|
visit: (nodeId, _, actions) => {
|
|
let node = (0, _nullthrows().default)(this._graph.getNode(nodeId));
|
|
|
|
if (node.type !== 'bundle') {
|
|
return;
|
|
}
|
|
|
|
if (node.value.id === bundle.id) {
|
|
return;
|
|
}
|
|
|
|
if (includeInline || node.value.bundleBehavior !== _types.BundleBehavior.inline) {
|
|
referencedBundles.add(node.value);
|
|
}
|
|
|
|
if (!recursive) {
|
|
actions.skipChildren();
|
|
}
|
|
},
|
|
startNodeId: this._graph.getNodeIdByContentKey(bundle.id),
|
|
getChildren: nodeId => // Shared bundles seem to depend on being used in the opposite order
|
|
// they were added.
|
|
// TODO: Should this be the case?
|
|
this._graph.getNodeIdsConnectedFrom(nodeId, bundleGraphEdgeTypes.references).reverse()
|
|
});
|
|
|
|
return [...referencedBundles];
|
|
}
|
|
|
|
getIncomingDependencies(asset) {
|
|
if (!this._graph.hasContentKey(asset.id)) {
|
|
return [];
|
|
} // Dependencies can be a a parent node via an untyped edge (like in the AssetGraph but without AssetGroups)
|
|
// or they can be parent nodes via a 'references' edge
|
|
|
|
|
|
return this._graph.getNodeIdsConnectedTo(this._graph.getNodeIdByContentKey(asset.id), _graph().ALL_EDGE_TYPES).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).filter(n => n.type === 'dependency').map(n => {
|
|
(0, _assert().default)(n.type === 'dependency');
|
|
return n.value;
|
|
});
|
|
}
|
|
|
|
getAssetWithDependency(dep) {
|
|
if (!this._graph.hasContentKey(dep.id)) {
|
|
return null;
|
|
}
|
|
|
|
let res = this._graph.getNodeIdsConnectedTo(this._graph.getNodeIdByContentKey(dep.id));
|
|
|
|
(0, _assert().default)(res.length <= 1, 'Expected a single asset to be connected to a dependency');
|
|
|
|
let resNode = this._graph.getNode(res[0]);
|
|
|
|
if ((resNode === null || resNode === void 0 ? void 0 : resNode.type) === 'asset') {
|
|
return resNode.value;
|
|
}
|
|
}
|
|
|
|
bundleHasAsset(bundle, asset) {
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
let assetNodeId = this._graph.getNodeIdByContentKey(asset.id);
|
|
|
|
return this._graph.hasEdge(bundleNodeId, assetNodeId, bundleGraphEdgeTypes.contains);
|
|
}
|
|
|
|
bundleHasDependency(bundle, dependency) {
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
let dependencyNodeId = this._graph.getNodeIdByContentKey(dependency.id);
|
|
|
|
return this._graph.hasEdge(bundleNodeId, dependencyNodeId, bundleGraphEdgeTypes.contains);
|
|
}
|
|
|
|
filteredTraverse(bundleNodeId, filter, visit) {
|
|
return this._graph.filteredTraverse(filter, visit, bundleNodeId);
|
|
}
|
|
|
|
getSymbolResolution(asset, symbol, boundary) {
|
|
var _asset$symbols, _asset$symbols$get;
|
|
|
|
let assetOutside = boundary && !this.bundleHasAsset(boundary, asset);
|
|
let identifier = (_asset$symbols = asset.symbols) === null || _asset$symbols === void 0 ? void 0 : (_asset$symbols$get = _asset$symbols.get(symbol)) === null || _asset$symbols$get === void 0 ? void 0 : _asset$symbols$get.local;
|
|
|
|
if (symbol === '*') {
|
|
var _asset$symbols2, _asset$symbols2$get;
|
|
|
|
return {
|
|
asset,
|
|
exportSymbol: '*',
|
|
symbol: identifier !== null && identifier !== void 0 ? identifier : null,
|
|
loc: (_asset$symbols2 = asset.symbols) === null || _asset$symbols2 === void 0 ? void 0 : (_asset$symbols2$get = _asset$symbols2.get(symbol)) === null || _asset$symbols2$get === void 0 ? void 0 : _asset$symbols2$get.loc
|
|
};
|
|
}
|
|
|
|
let found = false;
|
|
let skipped = false;
|
|
let deps = this.getDependencies(asset).reverse();
|
|
let potentialResults = [];
|
|
|
|
for (let dep of deps) {
|
|
var _depSymbols$get;
|
|
|
|
let depSymbols = dep.symbols;
|
|
|
|
if (!depSymbols) {
|
|
found = true;
|
|
continue;
|
|
} // If this is a re-export, find the original module.
|
|
|
|
|
|
let symbolLookup = new Map([...depSymbols].map(([key, val]) => [val.local, key]));
|
|
let depSymbol = symbolLookup.get(identifier);
|
|
|
|
if (depSymbol != null) {
|
|
let resolved = this.getResolvedAsset(dep);
|
|
|
|
if (!resolved || resolved.id === asset.id) {
|
|
var _asset$symbols3, _asset$symbols3$get;
|
|
|
|
// External module or self-reference
|
|
return {
|
|
asset,
|
|
exportSymbol: symbol,
|
|
symbol: identifier,
|
|
loc: (_asset$symbols3 = asset.symbols) === null || _asset$symbols3 === void 0 ? void 0 : (_asset$symbols3$get = _asset$symbols3.get(symbol)) === null || _asset$symbols3$get === void 0 ? void 0 : _asset$symbols3$get.loc
|
|
};
|
|
}
|
|
|
|
if (assetOutside) {
|
|
// We found the symbol, but `asset` is outside, return `asset` and the original symbol
|
|
found = true;
|
|
break;
|
|
}
|
|
|
|
if (this.isDependencySkipped(dep)) {
|
|
// We found the symbol and `dep` was skipped
|
|
skipped = true;
|
|
break;
|
|
}
|
|
|
|
let {
|
|
asset: resolvedAsset,
|
|
symbol: resolvedSymbol,
|
|
exportSymbol,
|
|
loc
|
|
} = this.getSymbolResolution(resolved, depSymbol, boundary);
|
|
|
|
if (!loc) {
|
|
var _asset$symbols4, _asset$symbols4$get;
|
|
|
|
// Remember how we got there
|
|
loc = (_asset$symbols4 = asset.symbols) === null || _asset$symbols4 === void 0 ? void 0 : (_asset$symbols4$get = _asset$symbols4.get(symbol)) === null || _asset$symbols4$get === void 0 ? void 0 : _asset$symbols4$get.loc;
|
|
}
|
|
|
|
return {
|
|
asset: resolvedAsset,
|
|
symbol: resolvedSymbol,
|
|
exportSymbol,
|
|
loc
|
|
};
|
|
} // If this module exports wildcards, resolve the original module.
|
|
// Default exports are excluded from wildcard exports.
|
|
// Wildcard reexports are never listed in the reexporting asset's symbols.
|
|
|
|
|
|
if (identifier == null && ((_depSymbols$get = depSymbols.get('*')) === null || _depSymbols$get === void 0 ? void 0 : _depSymbols$get.local) === '*' && symbol !== 'default') {
|
|
let resolved = this.getResolvedAsset(dep);
|
|
|
|
if (!resolved) {
|
|
continue;
|
|
}
|
|
|
|
let result = this.getSymbolResolution(resolved, symbol, boundary); // We found the symbol
|
|
|
|
if (result.symbol != undefined) {
|
|
var _resolved$symbols, _resolved$symbols$get;
|
|
|
|
if (assetOutside) {
|
|
// ..., but `asset` is outside, return `asset` and the original symbol
|
|
found = true;
|
|
break;
|
|
}
|
|
|
|
if (this.isDependencySkipped(dep)) {
|
|
// We found the symbol and `dep` was skipped
|
|
skipped = true;
|
|
break;
|
|
}
|
|
|
|
return {
|
|
asset: result.asset,
|
|
symbol: result.symbol,
|
|
exportSymbol: result.exportSymbol,
|
|
loc: (_resolved$symbols = resolved.symbols) === null || _resolved$symbols === void 0 ? void 0 : (_resolved$symbols$get = _resolved$symbols.get(symbol)) === null || _resolved$symbols$get === void 0 ? void 0 : _resolved$symbols$get.loc
|
|
};
|
|
}
|
|
|
|
if (result.symbol === null) {
|
|
found = true;
|
|
|
|
if (boundary && !this.bundleHasAsset(boundary, result.asset)) {
|
|
// If the returned asset is outside (and it's the first asset that is outside), return it.
|
|
if (!assetOutside) {
|
|
var _resolved$symbols2, _resolved$symbols2$ge;
|
|
|
|
return {
|
|
asset: result.asset,
|
|
symbol: result.symbol,
|
|
exportSymbol: result.exportSymbol,
|
|
loc: (_resolved$symbols2 = resolved.symbols) === null || _resolved$symbols2 === void 0 ? void 0 : (_resolved$symbols2$ge = _resolved$symbols2.get(symbol)) === null || _resolved$symbols2$ge === void 0 ? void 0 : _resolved$symbols2$ge.loc
|
|
};
|
|
} else {
|
|
// Otherwise the original asset will be returned at the end.
|
|
break;
|
|
}
|
|
} else {
|
|
var _resolved$symbols3, _resolved$symbols3$ge;
|
|
|
|
// We didn't find it in this dependency, but it might still be there: bailout.
|
|
// Continue searching though, with the assumption that there are no conficting reexports
|
|
// and there might be a another (re)export (where we might statically find the symbol).
|
|
potentialResults.push({
|
|
asset: result.asset,
|
|
symbol: result.symbol,
|
|
exportSymbol: result.exportSymbol,
|
|
loc: (_resolved$symbols3 = resolved.symbols) === null || _resolved$symbols3 === void 0 ? void 0 : (_resolved$symbols3$ge = _resolved$symbols3.get(symbol)) === null || _resolved$symbols3$ge === void 0 ? void 0 : _resolved$symbols3$ge.loc
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} // We didn't find the exact symbol...
|
|
|
|
|
|
if (potentialResults.length == 1) {
|
|
// ..., but if it does exist, it has to be behind this one reexport.
|
|
return potentialResults[0];
|
|
} else {
|
|
var _asset$symbols5, _asset$symbols6, _asset$symbols6$get;
|
|
|
|
// ... and there is no single reexport, but `bailout` tells us if it might still be exported.
|
|
return {
|
|
asset,
|
|
exportSymbol: symbol,
|
|
symbol: skipped ? false : found ? null : identifier !== null && identifier !== void 0 ? identifier : (_asset$symbols5 = asset.symbols) !== null && _asset$symbols5 !== void 0 && _asset$symbols5.has('*') ? null : undefined,
|
|
loc: (_asset$symbols6 = asset.symbols) === null || _asset$symbols6 === void 0 ? void 0 : (_asset$symbols6$get = _asset$symbols6.get(symbol)) === null || _asset$symbols6$get === void 0 ? void 0 : _asset$symbols6$get.loc
|
|
};
|
|
}
|
|
}
|
|
|
|
getAssetById(contentKey) {
|
|
let node = this._graph.getNodeByContentKey(contentKey);
|
|
|
|
if (node == null) {
|
|
throw new Error('Node not found');
|
|
} else if (node.type !== 'asset') {
|
|
throw new Error('Node was not an asset');
|
|
}
|
|
|
|
return node.value;
|
|
}
|
|
|
|
getAssetPublicId(asset) {
|
|
let publicId = this._publicIdByAssetId.get(asset.id);
|
|
|
|
if (publicId == null) {
|
|
throw new Error("Asset or it's public id not found");
|
|
}
|
|
|
|
return publicId;
|
|
}
|
|
|
|
getExportedSymbols(asset, boundary) {
|
|
if (!asset.symbols) {
|
|
return [];
|
|
}
|
|
|
|
let symbols = [];
|
|
|
|
for (let symbol of asset.symbols.keys()) {
|
|
symbols.push({ ...this.getSymbolResolution(asset, symbol, boundary),
|
|
exportAs: symbol
|
|
});
|
|
}
|
|
|
|
let deps = this.getDependencies(asset);
|
|
|
|
for (let dep of deps) {
|
|
var _depSymbols$get2;
|
|
|
|
let depSymbols = dep.symbols;
|
|
if (!depSymbols) continue;
|
|
|
|
if (((_depSymbols$get2 = depSymbols.get('*')) === null || _depSymbols$get2 === void 0 ? void 0 : _depSymbols$get2.local) === '*') {
|
|
let resolved = this.getResolvedAsset(dep);
|
|
if (!resolved) continue;
|
|
let exported = this.getExportedSymbols(resolved, boundary).filter(s => s.exportSymbol !== 'default').map(s => s.exportSymbol !== '*' ? { ...s,
|
|
exportAs: s.exportSymbol
|
|
} : s);
|
|
symbols.push(...exported);
|
|
}
|
|
}
|
|
|
|
return symbols;
|
|
}
|
|
|
|
getContentHash(bundle) {
|
|
let existingHash = this._bundleContentHashes.get(bundle.id);
|
|
|
|
if (existingHash != null) {
|
|
return existingHash;
|
|
}
|
|
|
|
let hash = new (_hash().Hash)(); // TODO: sort??
|
|
|
|
this.traverseAssets(bundle, asset => {
|
|
{
|
|
hash.writeString([this.getAssetPublicId(asset), asset.outputHash, asset.filePath, asset.query, asset.type, asset.uniqueKey].join(':'));
|
|
}
|
|
});
|
|
let hashHex = hash.finish();
|
|
|
|
this._bundleContentHashes.set(bundle.id, hashHex);
|
|
|
|
return hashHex;
|
|
}
|
|
|
|
getInlineBundles(bundle) {
|
|
let bundles = [];
|
|
let seen = new Set();
|
|
|
|
let addReferencedBundles = bundle => {
|
|
if (seen.has(bundle.id)) {
|
|
return;
|
|
}
|
|
|
|
seen.add(bundle.id);
|
|
let referencedBundles = this.getReferencedBundles(bundle, {
|
|
includeInline: true
|
|
});
|
|
|
|
for (let referenced of referencedBundles) {
|
|
if (referenced.bundleBehavior === _types.BundleBehavior.inline) {
|
|
bundles.push(referenced);
|
|
addReferencedBundles(referenced);
|
|
}
|
|
}
|
|
};
|
|
|
|
addReferencedBundles(bundle);
|
|
this.traverseBundles((childBundle, _, traversal) => {
|
|
if (childBundle.bundleBehavior === _types.BundleBehavior.inline) {
|
|
bundles.push(childBundle);
|
|
} else if (childBundle.id !== bundle.id) {
|
|
traversal.skipChildren();
|
|
}
|
|
}, bundle);
|
|
return bundles;
|
|
}
|
|
|
|
getHash(bundle) {
|
|
let hash = new (_hash().Hash)();
|
|
hash.writeString(bundle.id + bundle.target.publicUrl + this.getContentHash(bundle));
|
|
let inlineBundles = this.getInlineBundles(bundle);
|
|
|
|
for (let inlineBundle of inlineBundles) {
|
|
hash.writeString(this.getContentHash(inlineBundle));
|
|
}
|
|
|
|
for (let referencedBundle of this.getReferencedBundles(bundle)) {
|
|
hash.writeString(referencedBundle.id);
|
|
}
|
|
|
|
hash.writeString(JSON.stringify((0, _utils().objectSortedEntriesDeep)(bundle.env)));
|
|
return hash.finish();
|
|
}
|
|
|
|
getBundleGraphHash() {
|
|
let hashes = '';
|
|
|
|
for (let bundle of this.getBundles()) {
|
|
hashes += this.getHash(bundle);
|
|
}
|
|
|
|
return (0, _hash().hashString)(hashes);
|
|
}
|
|
|
|
addBundleToBundleGroup(bundle, bundleGroup) {
|
|
let bundleGroupNodeId = this._graph.getNodeIdByContentKey((0, _utils2.getBundleGroupId)(bundleGroup));
|
|
|
|
let bundleNodeId = this._graph.getNodeIdByContentKey(bundle.id);
|
|
|
|
if (this._graph.hasEdge(bundleGroupNodeId, bundleNodeId, bundleGraphEdgeTypes.bundle)) {
|
|
// Bundle group already has bundle
|
|
return;
|
|
}
|
|
|
|
this._graph.addEdge(bundleGroupNodeId, bundleNodeId);
|
|
|
|
this._graph.addEdge(bundleGroupNodeId, bundleNodeId, bundleGraphEdgeTypes.bundle);
|
|
|
|
for (let entryAssetId of bundle.entryAssetIds) {
|
|
let entryAssetNodeId = this._graph.getNodeIdByContentKey(entryAssetId);
|
|
|
|
if (this._graph.hasEdge(bundleGroupNodeId, entryAssetNodeId)) {
|
|
this._graph.removeEdge(bundleGroupNodeId, entryAssetNodeId);
|
|
}
|
|
}
|
|
}
|
|
|
|
getUsedSymbolsAsset(asset) {
|
|
let node = this._graph.getNodeByContentKey(asset.id);
|
|
|
|
(0, _assert().default)(node && node.type === 'asset');
|
|
return this._symbolPropagationRan ? makeReadOnlySet(node.usedSymbols) : null;
|
|
}
|
|
|
|
getUsedSymbolsDependency(dep) {
|
|
let node = this._graph.getNodeByContentKey(dep.id);
|
|
|
|
(0, _assert().default)(node && node.type === 'dependency');
|
|
return this._symbolPropagationRan ? makeReadOnlySet(node.usedSymbolsUp) : null;
|
|
}
|
|
|
|
merge(other) {
|
|
let otherGraphIdToThisNodeId = new Map();
|
|
|
|
for (let [otherNodeId, otherNode] of other._graph.nodes) {
|
|
if (this._graph.hasContentKey(otherNode.id)) {
|
|
let existingNodeId = this._graph.getNodeIdByContentKey(otherNode.id);
|
|
|
|
otherGraphIdToThisNodeId.set(otherNodeId, existingNodeId);
|
|
let existingNode = (0, _nullthrows().default)(this._graph.getNode(existingNodeId)); // Merge symbols, recompute dep.exluded based on that
|
|
|
|
if (existingNode.type === 'asset') {
|
|
(0, _assert().default)(otherNode.type === 'asset');
|
|
existingNode.usedSymbols = new Set([...existingNode.usedSymbols, ...otherNode.usedSymbols]);
|
|
} else if (existingNode.type === 'dependency') {
|
|
(0, _assert().default)(otherNode.type === 'dependency');
|
|
existingNode.usedSymbolsDown = new Set([...existingNode.usedSymbolsDown, ...otherNode.usedSymbolsDown]);
|
|
existingNode.usedSymbolsUp = new Set([...existingNode.usedSymbolsUp, ...otherNode.usedSymbolsUp]);
|
|
existingNode.excluded = (existingNode.excluded || Boolean(existingNode.hasDeferred)) && (otherNode.excluded || Boolean(otherNode.hasDeferred));
|
|
}
|
|
} else {
|
|
let updateNodeId = this._graph.addNodeByContentKey(otherNode.id, otherNode);
|
|
|
|
otherGraphIdToThisNodeId.set(otherNodeId, updateNodeId);
|
|
}
|
|
}
|
|
|
|
for (let edge of other._graph.getAllEdges()) {
|
|
this._graph.addEdge((0, _nullthrows().default)(otherGraphIdToThisNodeId.get(edge.from)), (0, _nullthrows().default)(otherGraphIdToThisNodeId.get(edge.to)), edge.type);
|
|
}
|
|
}
|
|
|
|
isEntryBundleGroup(bundleGroup) {
|
|
return this._graph.getNodeIdsConnectedTo((0, _nullthrows().default)(this._graph.getNodeIdByContentKey((0, _utils2.getBundleGroupId)(bundleGroup))), bundleGraphEdgeTypes.bundle).map(id => (0, _nullthrows().default)(this._graph.getNode(id))).some(n => n.type === 'root');
|
|
}
|
|
|
|
getEntryRoot(projectRoot, target) {
|
|
let cached = this._targetEntryRoots.get(target.distDir);
|
|
|
|
if (cached != null) {
|
|
return cached;
|
|
}
|
|
|
|
let entryBundleGroupIds = this._graph.getNodeIdsConnectedFrom((0, _nullthrows().default)(this._graph.rootNodeId), bundleGraphEdgeTypes.bundle);
|
|
|
|
let entries = [];
|
|
|
|
for (let bundleGroupId of entryBundleGroupIds) {
|
|
let bundleGroupNode = this._graph.getNode(bundleGroupId);
|
|
|
|
(0, _assert().default)((bundleGroupNode === null || bundleGroupNode === void 0 ? void 0 : bundleGroupNode.type) === 'bundle_group');
|
|
|
|
if (bundleGroupNode.value.target.distDir === target.distDir) {
|
|
let entryAssetNode = this._graph.getNodeByContentKey(bundleGroupNode.value.entryAssetId);
|
|
|
|
(0, _assert().default)((entryAssetNode === null || entryAssetNode === void 0 ? void 0 : entryAssetNode.type) === 'asset');
|
|
entries.push((0, _projectPath.fromProjectPath)(projectRoot, entryAssetNode.value.filePath));
|
|
}
|
|
}
|
|
|
|
let root = (0, _utils().getRootDir)(entries);
|
|
|
|
this._targetEntryRoots.set(target.distDir, root);
|
|
|
|
return root;
|
|
}
|
|
|
|
}
|
|
|
|
exports.default = BundleGraph; |