-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Description
Describe the bug
I've been running into a problem which results in certain module imports failing with an error of "exports.hasOwnProperty is not a function". From what I can tell, this happens when the following conditions are met:
- The evaluated code was generated by a version of TypeScript older than 4 (technically older than 4.0.0-dev.20200711) and used CommonJS as the target format
- The evaluated code was generated from source which contained an
export * from ...statement to re-export all the named exports from another module - The module is included in the
deps.inlinearray of the Vitest config
I've learned the following things:
- The error does not appear if the module is evaluated using Node directly. I think this is what Vitest essentially does by default, and is why using
deps.inlinecauses the issue, but please correct me if I'm wrong - During the development of TypeScript 4, a PR, fix(helpers): Use
hasOwnProperty.callmicrosoft/TypeScript#39537, was merge which altered the way TypeScript compilesimport * fromstatements so that the generated code would useObject.prototype.hasOwnProperty.callto invoke the method rather than relying onexportshavingObjectin its prototype chain. This fix made it into the 4.0.0-dev-20200711 nightly, and appears to be present in all subsequent versions - Vitest appears to use
Object.create(null)to create itsexportsobject
This bug took a fair amount of digging, and I only ran into it because I was dealing with another, much stranger bug where a CommonJS module from (an internal company) package generated with TypeScript 3.7 had all the exports (which were re-exported from other files) it was supposed to when evaluated in a browser (after being bundled by Vite), but when used in Vitest only had a subset of those exports available. (I'm still trying to figure out the reason for that difference so I can either figure out the right thing to do or file an issue.) That smelled like a resolution issue, so I tried using deps.inline, which lead me to the exports.hasOwnProperty problem. I edited the problematic code to use call to invoke the hasOwnProperty method on the exports object, and that made my tests pass.
As I mentioned earlier, newer versions of TypeScript shouldn't produce this issue. Sadly, I've run into code which can't be migrated to a newer version at the moment. Presumably there's other code out there written for Node which expected exports to have Object in its prototype chain. Both of these seem like good reasons to me that this is a bug which should be fixed. If others agree, I'd be happy to try and put together a PR to do so.
Reproduction
I created rimunroe/vitest-commonjs-exports-prototype-issue to demonstrate the issue. A summary of this issue is included in the readme along with steps to reproduce it.
System Info
System:
OS: macOS 13.1
CPU: (16) x64 Intel(R) Core(TM) i9-9980HK CPU @ 2.40GHz
Memory: 26.67 GB / 64.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 16.17.0 - ~/.nvm/versions/node/v16.17.0/bin/node
npm: 8.15.0 - ~/.nvm/versions/node/v16.17.0/bin/npm
Browsers:
Chrome: 109.0.5414.119
Firefox: 109.0
Safari: 16.2
npmPackages:
vitest: 0.28.1 => 0.28.1Used Package Manager
npm
Validations
- Follow our Code of Conduct
- Read the Contributing Guidelines.
- Read the docs.
- Check that there isn't already an issue that reports the same bug to avoid creating a duplicate.
- Check that this is a concrete bug. For Q&A open a GitHub Discussion or join our Discord Chat Server.
- The provided reproduction is a minimal reproducible example of the bug.