Repository: parcel-bundler/parcel (js)

Issue:
Parcel 2: another SWC regression: `Uncaught ReferenceError: $55cef6b6a3de3a733971a44b5a0765e6$exports is not defined` on runtime
# 🐛 bug report

Congratulations on one of my scripts running error free in modern browsers with the new SWC nightlies!

However, there are still issues left when building for IE11.

In this case I get `Uncaught ReferenceError: $55cef6b6a3de3a733971a44b5a0765e6$exports is not defined` when running a script built for IE11.
I have narrowed it down to the String.prototype.replaceAll polyfill that I use. It seems to use https://github.com/inspect-js/object-inspect and something in there confuses SWC/Parcel.

What exactly it is is left as an exercise for the reader 😏 Easy reproduction .zip attached.

## 🎛 Configuration (.babelrc, package.json, cli command)

Please see attached .zip file.

## 🤔 Expected Behavior

No error / crash

## 😯 Current Behavior

Output doesn't run at all

## 💁 Possible Solution

Revert the behavior to my favorite version, 650, where everything works fine ☺️

## 🔦 Context

Modern version built and ran successfully. My hopes were high but I couldn't believe everything would actually work. Than I ran the version for older browsers and here we are. Back to 650 I go.

Also, there's another issue left with private class fields and I don't know what it is yet 😩

## 💻 Code Sample

[parcel-debugging-fun-for-mischnic.zip](https://github.com/parcel-bundler/parcel/files/6501026/parcel-debugging-fun-for-mischnic.zip)

Note: This .zip has a .babelrc, I don't know if it makes a difference.

## 🌍 Your Environment

<!--- Include as many relevant details about the environment you experienced the bug in -->

| Software         | Version(s) |
| ---------------- | ---------- |
| Parcel           |2.0.0-nightly.672+71b3b935|
| Node             |v16.1.0|
| npm/Yarn         |7.11.2|
| Operating System |macOS 10.15.7 (19H1030)|

<!-- Love parcel? Please consider supporting our collective:
👉  https://opencollective.com/parcel/donate -->


Pull request description:
Include namespace object when importing a missing symbol from a CJS asset
Closes #6304

A situation where the used symbols of a CJS object contains are `"x"`  while the symbols are `"*", "y"`. In this case, we insert `$id$exports$.x` at runtime, so the namespace object needs to be included.

Patch:
diff --git a/packages/packagers/js/src/ScopeHoistingPackager.js b/packages/packagers/js/src/ScopeHoistingPackager.js
index bbcbc65f2..d6f07a3f6 100644
--- a/packages/packagers/js/src/ScopeHoistingPackager.js
+++ b/packages/packagers/js/src/ScopeHoistingPackager.js
@@ -785,21 +785,25 @@ ${code}
       usedSymbols.has('default') &&
       !asset.symbols.hasExportSymbol('__esModule');
 
-    // If the asset has * in its used symbols, we might need the exports namespace.
-    // The one case where this isn't true is in ESM library entries, where the only
-    // dependency on * is the entry dependency. In this case, we will use ESM exports
-    // instead of the namespace object.
     let usedNamespace =
-      usedSymbols.has('*') &&
-      (this.bundle.env.outputFormat !== 'esmodule' ||
-        !this.bundle.env.isLibrary ||
-        asset !== this.bundle.getMainEntry() ||
-        this.bundleGraph
-          .getIncomingDependencies(asset)
-          .some(
-            dep =>
-              !dep.isEntry && this.bundleGraph.getUsedSymbols(dep).has('*'),
-          ));
+      // If the asset has * in its used symbols, we might need the exports namespace.
+      // The one case where this isn't true is in ESM library entries, where the only
+      // dependency on * is the entry dependency. In this case, we will use ESM exports
+      // instead of the namespace object.
+      (usedSymbols.has('*') &&
+        (this.bundle.env.outputFormat !== 'esmodule' ||
+          !this.bundle.env.isLibrary ||
+          asset !== this.bundle.getMainEntry() ||
+          this.bundleGraph
+            .getIncomingDependencies(asset)
+            .some(
+              dep =>
+                !dep.isEntry && this.bundleGraph.getUsedSymbols(dep).has('*'),
+            ))) ||
+      // If a symbol is imported (used) from a CJS asset but isn't listed in the symbols,
+      // we fallback on the namespace object.
+      (asset.symbols.hasExportSymbol('*') &&
+        [...usedSymbols].some(s => !asset.symbols.hasExportSymbol(s)));
 
     // If the asset doesn't have static exports, should wrap, the namespace is used,
     // or we need default interop, then we need to synthesize a namespace object for


Test patch:
diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-commonjs-missing/a.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-commonjs-missing/a.js
new file mode 100644
index 000000000..25b57bd8c
--- /dev/null
+++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-commonjs-missing/a.js
@@ -0,0 +1,3 @@
+import { x } from "./b.js";
+
+output = x;
diff --git a/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-commonjs-missing/b.js b/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-commonjs-missing/b.js
new file mode 100644
index 000000000..56cfe36d5
--- /dev/null
+++ b/packages/core/integration-tests/test/integration/scope-hoisting/es6/import-commonjs-missing/b.js
@@ -0,0 +1,1 @@
+module.exports.y = 2;
diff --git a/packages/core/integration-tests/test/scope-hoisting.js b/packages/core/integration-tests/test/scope-hoisting.js
index d601eb526..24303d84a 100644
--- a/packages/core/integration-tests/test/scope-hoisting.js
+++ b/packages/core/integration-tests/test/scope-hoisting.js
@@ -784,6 +784,18 @@ describe('scope hoisting', function() {
       });
     });
 
+    it('falls back when importing missing symbols from CJS', async function() {
+      let b = await bundle(
+        path.join(
+          __dirname,
+          '/integration/scope-hoisting/es6/import-commonjs-missing/a.js',
+        ),
+      );
+
+      let output = await run(b);
+      assert.strictEqual(output, undefined);
+    });
+
     it('does not export reassigned CommonJS exports references', async function() {
       let b = await bundle(
         path.join(