Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Importing CommonJS module fails due to exports object having a null prototype #2761

Closed
6 tasks done
rimunroe opened this issue Jan 27, 2023 · 1 comment · Fixed by #2769
Closed
6 tasks done

Importing CommonJS module fails due to exports object having a null prototype #2761

rimunroe opened this issue Jan 27, 2023 · 1 comment · Fixed by #2769

Comments

@rimunroe
Copy link

rimunroe commented Jan 27, 2023

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.inline array 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.inline causes the issue, but please correct me if I'm wrong
  • During the development of TypeScript 4, a PR, fix(helpers): Use hasOwnProperty.call microsoft/TypeScript#39537, was merge which altered the way TypeScript compiles import * from statements so that the generated code would use Object.prototype.hasOwnProperty.call to invoke the method rather than relying on exports having Object in 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 its exports object

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.1

Used Package Manager

npm

Validations

@sheremet-va
Copy link
Member

I guess we can support object prototype methods on cjsExport Proxy.

@github-actions github-actions bot locked and limited conversation to collaborators Jun 5, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants