enter(node, context, actions) {
        if (node.type === 'asset') {
          if (
            context?.type === 'dependency' &&
            context?.value.isEntry &&
            !entries.has(node.value)
          ) {
            // Skip whole subtrees of other targets by skipping those entries
            actions.skipChildren();
            return node;
          }
          assetToIndex.set(node.value, assets.length);
          assets.push(node.value);

          let bundleIdTuple = bundleRoots.get(node.value);
          if (bundleIdTuple && bundleIdTuple[0] === bundleIdTuple[1]) {
            // Push to the stack (only) when a new bundle is created
            stack.push([node.value, bundleIdTuple[0]]);
          } else if (bundleIdTuple) {
            // Otherwise, push on the last bundle that marks the start of a BundleGroup
            stack.push([node.value, stack[stack.length - 1][1]]);
          }
        } else if (node.type === 'dependency') {
          if (context == null) {
            return node;
          }
          let dependency = node.value;

          invariant(context?.type === 'asset');

          let assets = assetGraph.getDependencyAssets(dependency);
          if (assets.length === 0) {
            return node;
          }

          for (let childAsset of assets) {
            let bundleId = bundles.get(childAsset.id);
            let bundle;

            // MSB Step 1: Match glob on filepath and type for any asset
            let manualSharedBundleKey;
            let manualSharedObject = manualAssetToConfig.get(childAsset);

            if (manualSharedObject) {
              // MSB Step 2: Generate a key for which to look up this manual bundle with
              manualSharedBundleKey =
                manualSharedObject.name + ',' + childAsset.type;
            }

            if (
              // MSB Step 3: If a bundle for these globs already exsits, use it
              manualSharedBundleKey != null &&
              manualSharedMap.has(manualSharedBundleKey)
            ) {
              bundleId = nullthrows(manualSharedMap.get(manualSharedBundleKey));
            }
            if (
              dependency.priority === 'lazy' ||
              (dependency.priority !== 'parallel' &&
                (dependency.bundleBehavior === 'isolated' ||
                  childAsset.bundleBehavior === 'isolated')) // An isolated Dependency, or Bundle must contain all assets it needs to load.
            ) {
              if (bundleId == null) {
                let firstBundleGroup = nullthrows(
                  bundleGraph.getNode(stack[0][1]),
                );
                invariant(firstBundleGroup !== 'root');
                bundle = createBundle({
                  asset: childAsset,
                  target: firstBundleGroup.target,
                  needsStableName:
                    dependency.bundleBehavior === 'inline' ||
                    childAsset.bundleBehavior === 'inline'
                      ? false
                      : dependency.isEntry || dependency.needsStableName,
                  bundleBehavior:
                    dependency.bundleBehavior ?? childAsset.bundleBehavior,
                });
                bundleId = bundleGraph.addNode(bundle);
                bundles.set(childAsset.id, bundleId);
                bundleRoots.set(childAsset, [bundleId, bundleId]);
                bundleGroupBundleIds.add(bundleId);
                bundleGraph.addEdge(bundleGraphRootNodeId, bundleId);
                if (manualSharedObject) {
                  // MSB Step 4: If this was the first instance of a match, mark mainAsset for internalization
                  // since MSBs should not have main entry assets
                  manualBundleToInternalizedAsset
                    .get(bundleId)
                    .push(childAsset);
                }
              } else {
                bundle = nullthrows(bundleGraph.getNode(bundleId));
                invariant(bundle !== 'root');

                if (
                  // If this dependency requests isolated, but the bundle is not,
                  // make the bundle isolated for all uses.
                  dependency.bundleBehavior === 'isolated' &&
                  bundle.bundleBehavior == null
                ) {
                  bundle.bundleBehavior = dependency.bundleBehavior;
                }
              }

              dependencyBundleGraph.addEdge(
                dependencyBundleGraph.addNodeByContentKeyIfNeeded(
                  dependency.id,
                  {
                    value: dependency,
                    type: 'dependency',
                  },
                ),
                dependencyBundleGraph.addNodeByContentKeyIfNeeded(
                  String(bundleId),
                  {
                    value: bundle,
                    type: 'bundle',
                  },
                ),
                dependencyPriorityEdges[dependency.priority],
              );

              // If this is a sync dependency on a JS asset that won't be replaced with a URL runtime,
              // add a reference so the bundle is loaded by the parent. This happens with React Server Components.
              if (
                dependency.priority === 'sync' &&
                childAsset.type === 'js' &&
                childAsset?.meta.jsRuntime !== 'url'
              ) {
                assetReference.get(childAsset).push([dependency, bundle]);
              }
            } else if (
              dependency.priority === 'parallel' ||
              childAsset.bundleBehavior === 'inline'
            ) {
              // The referencing bundleRoot is the root of a Bundle that first brings in another bundle (essentially the FIRST parent of a bundle, this may or may not be a bundleGroup)
              let [referencingBundleRoot, bundleGroupNodeId] = nullthrows(
                stack[stack.length - 1],
              );
              let bundleGroup = nullthrows(
                bundleGraph.getNode(bundleGroupNodeId),
              );
              invariant(bundleGroup !== 'root');

              let referencingBundleId = nullthrows(
                bundleRoots.get(referencingBundleRoot),
              )[0];
              let referencingBundle = nullthrows(
                bundleGraph.getNode(referencingBundleId),
              );
              invariant(referencingBundle !== 'root');

              if (bundleId == null) {
                bundle = createBundle({
                  // Bundles created from type changes shouldn't have an entry asset.
                  asset: childAsset,
                  type: childAsset.type,
                  env: childAsset.env,
                  bundleBehavior:
                    dependency.bundleBehavior ?? childAsset.bundleBehavior,
                  target: referencingBundle.target,
                  needsStableName:
                    childAsset.bundleBehavior === 'inline' ||
                    dependency.bundleBehavior === 'inline' ||
                    (dependency.priority === 'parallel' &&
                      !dependency.needsStableName)
                      ? false
                      : referencingBundle.needsStableName,
                });
                bundleId = bundleGraph.addNode(bundle);
              } 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.
                  dependency.bundleBehavior === 'isolated' &&
                  bundle.bundleBehavior == null
                ) {
                  bundle.bundleBehavior = dependency.bundleBehavior;
                }
              }

              bundles.set(childAsset.id, bundleId);

              // A bundle can belong to multiple bundlegroups, all the bundle groups of it's
              // ancestors, and all async and entry bundles before it are "bundle groups"
              // TODO: We may need to track bundles to all bundleGroups it belongs to in the future.
              bundleRoots.set(childAsset, [bundleId, bundleGroupNodeId]);
              bundleGraph.addEdge(referencingBundleId, bundleId);

              if (bundleId != bundleGroupNodeId) {
                dependencyBundleGraph.addEdge(
                  dependencyBundleGraph.addNodeByContentKeyIfNeeded(
                    dependency.id,
                    {
                      value: dependency,
                      type: 'dependency',
                    },
                  ),
                  dependencyBundleGraph.addNodeByContentKeyIfNeeded(
                    String(bundleId),
                    {
                      value: bundle,
                      type: 'bundle',
                    },
                  ),
                  dependencyPriorityEdges.parallel,
                );
              }

              assetReference.get(childAsset).push([dependency, bundle]);
            } else {
              bundleId = null;
            }
            if (manualSharedObject && bundleId != null) {
              // MSB Step 5:  At this point we've either created or found an existing MSB bundle
              // add the asset if it doesn't already have it and set key

              invariant(
                bundle !== 'root' && bundle != null && bundleId != null,
              );

              manualAssetToBundle.set(childAsset, bundleId);

              if (!bundle.assets.has(childAsset)) {
                // Add asset to bundle
                bundle.assets.add(childAsset);
                bundle.size += childAsset.stats.size;
              }

              bundles.set(childAsset.id, bundleId);
              bundleRoots.set(childAsset, [bundleId, bundleId]);

              invariant(manualSharedBundleKey != null);
              // Ensure we set key to BundleId so the next glob match uses the appropriate bundle
              if (!manualSharedMap.has(manualSharedBundleKey)) {
                manualSharedMap.set(manualSharedBundleKey, bundleId);
              }
              bundle.manualSharedBundle = manualSharedObject.name;
              bundle.uniqueKey = manualSharedObject.name + childAsset.type;
            }
          }
        }
        return node;
      }
Step Create Bundles: Traverse the assetGraph (aka MutableBundleGraph) and create bundles
for asset type changes, parallel, inline, and async or lazy dependencies,
adding only that asset to each bundle, not its entire subgraph.