Repository: parcel-bundler/parcel
File: packages/shared/scope-hoisting/src/hoist.js (JavaScript)

Code before:
          imported = 'default';
        } else if (t.isExportNamespaceSpecifier(specifier)) {
          imported = '*';
        } else if (t.isExportSpecifier(specifier)) {
          imported = specifier.local.name;
        } else {
          throw new Error('Unknown export construct');
        }

        let id = getIdentifier(asset, 'import', exported.name);

        let dep = asset
          .getDependencies()
          .find(dep => dep.moduleSpecifier === source.value);
        if (dep && imported) {
          let existing = dep.symbols.get(imported);
          if (existing) {
            id.name = existing;
          }
          // this will merge with the existing dependency
          asset.addDependency({
            moduleSpecifier: dep.moduleSpecifier,
            symbols: new Map([[imported, id.name]]),
            // `symbols` is empty if this dependency was added by JSTransformer/collectDependencies
            // in that case, override `isWeak`
            isWeak: dep.symbols.size === 0 ? true : dep.isWeak
          });
        }

        asset.symbols.set(exported.name, id.name);

        path.insertAfter(
          EXPORT_ASSIGN_TEMPLATE({
            EXPORTS: getExportsIdentifier(asset, path.scope),
            NAME: exported,
            LOCAL: id
          })
        );
      }

      addImport(asset, path);
      path.remove();
    } else if (declaration) {
      path.replaceWith(declaration);

      if (t.isIdentifier(declaration.id)) {
        addExport(asset, path, declaration.id, declaration.id);
      } else {
        let identifiers = t.getBindingIdentifiers(declaration);
        for (let id of Object.keys(identifiers)) {
          addExport(asset, path, identifiers[id], identifiers[id]);

Review comment (suggestion):
Not sure what the best way to solve this, the behaviour here needs to be:
- If `isWeak` is not set (after the dependency was added by the dependencies collector in JSTransformer), override it with `true`. But `isWeak` is a `boolean`, not `?boolean`.
- otherwise, only set `isWeak` if it already is weak.

I see three possible solutions:
- add weak dependencies in the dependency visitor (might cause some side effects in the graph but then makes the handling completely straight forward)
- change `isWeak` to also allow `undefined/null`
- don't run the dependency visitor with scope hoisting?
- (what I did here with the symbols seems fragile)

Code after:
        } else {
          throw new Error('Unknown export construct');
        }

        let id = getIdentifier(asset, 'import', exported.name);

        let dep = asset
          .getDependencies()
          .find(dep => dep.moduleSpecifier === source.value);
        if (dep && imported) {
          let existing = dep.symbols.get(imported);
          if (existing) {
            id.name = existing;
          } else {
            // this will merge with the existing dependency
            asset.addDependency({
              moduleSpecifier: dep.moduleSpecifier,
              symbols: new Map([[imported, id.name]]),
              isWeak: true
            });
          }
        }

        asset.symbols.set(exported.name, id.name);

        path.insertAfter(
          EXPORT_ASSIGN_TEMPLATE({
            EXPORTS: getExportsIdentifier(asset, path.scope),
            NAME: exported,
            LOCAL: id
          })
        );
      }

      addImport(asset, path);
      path.remove();
    } else if (declaration) {
      path.replaceWith(declaration);

      if (t.isIdentifier(declaration.id)) {
        addExport(asset, path, declaration.id, declaration.id);
      } else {
        let identifiers = t.getBindingIdentifiers(declaration);
        for (let id of Object.keys(identifiers)) {
          addExport(asset, path, identifiers[id], identifiers[id]);
        }
      }
    } else if (specifiers.length > 0) {
      for (let specifier of specifiers) {
        addExport(asset, path, specifier.local, specifier.exported);
      }