metro: resolver.unstable_enablePackageExports results in exception around interopRequireDefault
New Version
0.72.RC-3
Old Version
na
Build Target(s)
io sim
Output of react-native info
yarn run v1.22.19
$ /Users/deodad/Repos/RN0720RC32/node_modules/.bin/react-native info
info Fetching system and libraries information...
System:
OS: macOS 13.3.1
CPU: (12) arm64 Apple M2 Pro
Memory: 1.04 GB / 32.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 18.14.0
path: /var/folders/1p/8plc0yx167q53qdktkcfd20m0000gn/T/yarn--1683918327548-0.8468867441091508/node
Yarn:
version: 1.22.19
path: /var/folders/1p/8plc0yx167q53qdktkcfd20m0000gn/T/yarn--1683918327548-0.8468867441091508/yarn
npm:
version: 9.6.3
path: ~/Library/Caches/fnm_multishells/15355_1683908029786/bin/npm
Watchman: Not Found
Managers:
CocoaPods:
version: 1.12.1
path: /var/folders/1p/8plc0yx167q53qdktkcfd20m0000gn/T/frum_15377_1683908029799/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 22.4
- iOS 16.4
- macOS 13.3
- tvOS 16.4
- watchOS 9.4
Android SDK: Not Found
IDEs:
Android Studio: Not Found
Xcode:
version: 14.3/14E222b
path: /usr/bin/xcodebuild
Languages:
Java: Not Found
Ruby:
version: 3.1.3
path: /var/folders/1p/8plc0yx167q53qdktkcfd20m0000gn/T/frum_15377_1683908029799/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.72.0-rc.3
wanted: 0.72.0-rc.3
react-native-macos: Not Found
npmGlobalPackages:
"*react-native*": Not Found
Android:
hermesEnabled: true
newArchEnabled: false
iOS:
hermesEnabled: true
newArchEnabled: false
Done in 0.97s.
Issue and Reproduction Steps
npx react-native@latest init RN0720RC3 --version 0.72.0-rc.3 set resolver.unstable_enablePackageExports true in metro.config.js yarn start
Unhandled JS Exception: _$$_REQUIRE(_dependencyMap[0], "(...)/helpers/interopRequireDefault") is not a function (it is Object)
TypeError: _$$_REQUIRE(_dependencyMap[0], "(...)/helpers/interopRequireDefault") is not a function (it is Object)
at anonymous (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:25075:104)
at loadModuleImplementation (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:328:14)
at guardedLoadModule (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:227:38)
at metroRequire (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:123:92)
at anonymous (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:25052:108)
at loadModuleImplementation (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:328:14)
at guardedLoadModule (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:227:38)
at metroRequire (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:123:92)
at anonymous (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:24992:14)
at loadModuleImplementation (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:328:14)
at guardedLoadModule (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:219:47)
at metroRequire (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:123:92)
at global (http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:124286:4)
anonymous
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:25075:104
loadModuleImplementation
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:328:14
guardedLoadModule
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:227:38
metroRequire
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:123:92
anonymous
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:25052:108
loadModuleImplementation
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:328:14
guardedLoadModule
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:227:38
metroRequire
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:123:92
anonymous
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:24992:14
loadModuleImplementation
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:328:14
guardedLoadModule
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:219:47
metroRequire
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:123:92
global
index.bundle?platform=ios&dev=true&minify=false&modulesOnly=false&runModule=true&app=org.reactjs.native.example.RN0720RC32:124286:4
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 15 (12 by maintainers)
Commits related to this issue
- Add "exports" special case handling for @babel/runtime Summary: This is a workaround for https://github.com/facebook/metro/issues/984. It adds a specific exception in the resolver for `babel/runtime`... — committed to huntie/metro by huntie a year ago
- Add "exports" special case handling for @babel/runtime (#990) Summary: Pull Request resolved: https://github.com/facebook/metro/pull/990 This is a workaround for https://github.com/facebook/metro/is... — committed to huntie/metro by huntie a year ago
- Add "exports" special case handling for @babel/runtime (#990) Summary: Pull Request resolved: https://github.com/facebook/metro/pull/990 This is a workaround for https://github.com/facebook/metro/is... — committed to huntie/metro by huntie a year ago
- Add "exports" special case handling for @babel/runtime (#990) Summary: Pull Request resolved: https://github.com/facebook/metro/pull/990 This is a workaround for https://github.com/facebook/metro/is... — committed to facebook/metro by huntie a year ago
I’m unable to take a close look at the moment, but I suspect this has something to do with https://github.com/facebook/metro/commit/e70ceef126a528c5e18d58c5ed47adb864e8a76b. My guess is that Babel generates code that assumes the
importandrequireconditions will be asserted precisely for the respective kinds of dependencies, and never both at once like Metro does. So we end uprequireing the version intended for use withimport, and not doing any ESM interop unwrapping of the result. (Because this is the ESM interop unwrapping function.)Resolved in https://github.com/facebook/metro, shipping today in Metro 0.76.5 and will also be updated in React Native CLI today.
@NickGerleman - Yeah, we could remove the
importassertion and fall right back to non-exports resolution if exports resolution fails. It’s fiddly though, partly because this is beyond justmain/react-native/browserpackage entry points but also affects subpath resolution - re your condition 2., just because there’s an entry in theexportsmap for a subpath with theimportcondition asserted, that doesn’t necessarily match how it’d be resolved “traditionally”, where the subpath is expected to literally match a path on disk (after appending extensions).Indeed if we’ve reached the source file by successfully following the
exportsmap, it might reasonably use subpath imports for its own dependencies that don’t point to file locations and must be resolved withexportssupport - particularly if the dependencies are within a multi-package project like Babel. I haven’t seen a concrete example of that, to be fair, but I feel like there are edge cases to whichever spec deviation we choose here.Re the particular issue with
interopRequireDefault, it’s worth reiterating as @motiz88 pointed out, this is the module that allowsconst foo = require('foo')to work interchangeably withimport foo from 'foo'. Maybe a surgical fix for that particular module is all we really need, and after that we’re fine to assertimport.One possibility might simply to downgrade it - the problem export was only introduced in
@babel/runtime@7.14.0- compare@babel/runtime@17.13.7/package.json, where the CJS version takes precedence.The problem we’d have here is that effectively in OSS takes us back to https://github.com/facebook/react-native/pull/36584, which was reverted because it breaks compatibility with ESM-only packages.
We’ve come back a few times to the idea that we should assert
importas a last resort or fallback, maybe afterdefaultor only if resolution fails - such behaviour is definitely not within the exports spec, but it might be on a migration path.@kelset I’ll take a look at this tomorrow. Just to check, is that repro on a fresh
react-native initproject?