Conversation
This fixes the tests on VSCode 1.74.0. The issue is as follows: 1. Jest wil try reset all mocks after each test, as it should. 2. When Jest does this, it will loop over all global variables and check if they are mocks. 3. One of the global variables it checks is _VSCODE_NODE_MODULES, which is a proxy object. 4. When Jest checks whether it is a proxy by getting _isMockFunction on it, the `get` function on the proxy object will be called. 5. This will in turn call require, which will try to load the non-existing `_isMockFunction` module. This throws the error we are seeing. By removing the `_VSCODE_NODE_MODULES` property from the global object in the Jest environment, Jest will not try to reset it, and the tests should work again. See: https://github.com/facebook/jest/blob/41bf2300895a2c00d0525d21260f0a392819871f/packages/jest-runtime/src/index.ts#L1173-L1186 See: https://github.com/microsoft/vscode/blob/ed442a9e99ff68a3bb9e4953081305766862f450/src/bootstrap-amd.js#L15
| + // The _VSCODE_NODE_MODULES is a proxy which will require a module if any property | ||
| + // on it is accessed. This is a workaround for the fact that jest will call | ||
| + // _isMockFunction on the module, which will cause that function to be required. | ||
| + delete this.global._VSCODE_NODE_MODULES; |
There was a problem hiding this comment.
So, this deletes a global variable. Is this variable used anywhere else?
Would it be safer to change the part of jest that checks for proxies in globals? We can explicitly avoid checking this variable. Eg-
const globalMock = envGlobal[key];
if (key !== '_VSCODE_NODE_MODULES' &&
((typeof globalMock === 'object' && globalMock !== null) ||
typeof globalMock === 'function') &&
globalMock._isMockFunction === true
) {
globalMock.mockClear();
There was a problem hiding this comment.
You're right that this deletes a global variable. It shouldn't be used anywhere else, it's only used when VSCode is loading code and the Jest environment should always load after all extensions have loaded. There seem to be some specific usecases where it is being used, but as long as we don't use any of those code paths while testing the extension, it should be fine.
I tried using this.global = {...this.global}; before deleting it from this.global, but this unfortunately doesn't work.
The reason for adding it in here rather than as a patch for the jest-runtime package is that I'd highly prefer to have as few patched packages as possible and this is something very specific to VSCode, so should be in the jest-runner-vscode. If we do patch jest-runtime, we could try to be more generic by checking for a Proxy object instead of checking for this specific key, that should be more generic and have the same effect.
Another option would be to wrap the global. _VSCODE_NODE_MODULES in another Proxy layer which specifically excludes _isMockFunction from being required. I believe this may actually be the safest option, and it would be something that can be done in jest-runner-vscode. I'll try whether this actually works and commit it if that does work.
Instead of deleting the complete `_VSCODE_NODE_MODULES` object, we now use a `Proxy` to intercept the `_isMockFunction` property. This is safer and will not delete a global variable that VSCode expects to exist.
aeisenberg
left a comment
There was a problem hiding this comment.
Thanks for the explanation. This makes sense and I think the second approach is slightly better.
|
I am going to merge this PR right now since we have tests on semmle-code that are currently failing and should pass with this change in. |
This fixes the tests on VSCode 1.74.0. The issue is as follows:
getfunction on the proxy object will be called._isMockFunctionmodule. This throws the error we are seeing.By removing the
_VSCODE_NODE_MODULESproperty from the global object in the Jest environment, Jest will not try to reset it, and the tests should work again.See: https://github.com/facebook/jest/blob/41bf2300895a2c00d0525d21260f0a392819871f/packages/jest-runtime/src/index.ts#L1173-L1186
See: https://github.com/microsoft/vscode/blob/ed442a9e99ff68a3bb9e4953081305766862f450/src/bootstrap-amd.js#L15
Checklist
ready-for-doc-reviewlabel there.