-
-
Notifications
You must be signed in to change notification settings - Fork 6.5k
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
fix: hoist imports of @jest/globals
correctly
#9806
Conversation
0b30ac2
to
8e1319b
Compare
@@ -183,6 +183,12 @@ export default (): {visitor: Visitor} => { | |||
path.node._blockHoist = Infinity; | |||
} | |||
}, | |||
ImportDeclaration(path) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should probably look for a require
instead (or as well?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried this:
const visitor: Visitor = {
CallExpression(path) {
const callee = path.get('callee') as NodePath;
const callArguments = path.get('arguments');
if (
callee.isIdentifier() &&
callee.node.name === 'require' &&
callArguments.length === 1
) {
const [argument] = callArguments;
if (
argument.isStringLiteral() &&
argument.node.value === '@jest/globals'
) {
// @ts-ignore: private, magical property
path.node._blockHoist = Infinity;
}
}
},
};
and it gets into the _blockHoist
thing, but doesn't seem to actually hoist it. Halp? 😀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New try:
const visitor: Visitor = {
VariableDeclaration(path) {
const declarations = path.get('declarations');
if (declarations.length === 1) {
const declarationInit = declarations[0].get('init');
if (declarationInit.isCallExpression()) {
const callee = declarationInit.get('callee') as NodePath;
const callArguments = declarationInit.get('arguments') as Array<
NodePath
>;
if (
callee.isIdentifier() &&
callee.node.name === 'require' &&
callArguments.length === 1
) {
const [argument] = callArguments;
if (
argument.isStringLiteral() &&
argument.node.value === '@jest/globals'
) {
// @ts-ignore: private, magical property
path.node._blockHoist = Infinity;
}
}
}
}
}
}
This seems to hoist the require
, but not above the jest.mock
call.
"use strict";
_globals.jest.mock('virtual-module', function () {
return 'kiwi';
}, {
virtual: true
});
var _globals = require("@jest/globals");
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
// The virtual mock call below will be hoisted above this `require` call.
var virtualModule = require('virtual-module');
test('works with virtual modules', function () {
expect(virtualModule).toBe('kiwi');
});
Getting pretty close though 🙂
EDIT: wait no, that's the same as not having it at all 😅 I give up
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I pushed up that last one, since it feels like it's somewhere close
Another issue here is that we only hoist |
@SimenB is there a way I can get |
I'll publish after fixing this bug |
@ahnpnl thanks for taking the initiative regarding |
@SimenB I'll take a shot 🙃 |
I have done some well-deserved cleanup in jeysal@fdecf04 and went in a direction with the visitor that we might want to go in (similar to what I understand |
Ah, that's great @jeysal! The plugin definitely needs some TLC and if we can get rid of the |
@jeysal @nicolo-ribaudo any progress? 🙏 I'd love to release this, but with this bug I'd rather revert and re-land later. If you don't have time that of course perfectly fine! 😀 |
I was hoping to get back to it on one of the evenings this week but that didn't happen :/ maybe tonight or tomorrow |
@jeysal Please ping me when you are done, so that I can review it! |
Woo, thanks both! |
I think an easy way of safely fixing this is to rely on what is natively hoisted: functions. The output in the PR description would become something like this: "use strict";
_globals().jest.mock('virtual-module', function () {
return 'kiwi';
}, {
virtual: true
});
function _globals() {
var tmp = require("@jest/globals");
_globals = () => tmp;
return tmp;
}
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
// The virtual mock call below will be hoisted above this `require` call.
var virtualModule = require('virtual-module');
test('works with virtual modules', function () {
expect(virtualModule).toBe('kiwi');
}); By dining so, we don't have to worry about |
Ah, that's a great idea! |
@nicolo-ribaudo wanna open up a separate PR with that? Feel free to take the test from this one. The whole plugin probably needs some more tlc regardless, but it's a good start, and something I feel comfortable shipping |
@nicolo-ribaudo also, it might be good to start from the commit I posted (jeysal@fdecf04) since there's a lot of cleanup in there. I already don't remember what exactly and not sure if you aren't gonna end up rewriting everything anyway but yeah maybe do that if you can. It also has all the tests (including new one) |
Oh sorry I thought you were preparing a PR based on 'looking at this right now'. But I can also definitely take over again with your guidance! |
I wrote "looking at this right now" before seeing your comment, then I deleted it because I didn't want to "steal" it from you 😛 |
👍 cool will do |
Very sorry I didn't get back to it this weekend. I'll try to make some time during the workdays next week to make sure to it asap |
CI seems like it wants to revert the snapshot changes you made? |
This reverts commit e4778f8.
On my machine the 3 snapshot updates (incl. the stack trace ones) no longer try to update after a |
We might wanna add |
Definitely the latter I think. Although just version doesn't help for development in the Jest repo? |
We can read its source. We include |
All greeeeeeeeen 🎉 would be great to get another look by @nicolo-ribaudo then ship 👌 |
Is it a problem if I review this tomorrow instead of today? |
No no totally not! ❤️ |
@nicolo-ribaudo gentle ping, if you don't have time to review just let us know, I'm mostly confident in this and we could land without 😄 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not a blocker for this PR, but what do you think about adding some input/output tests for this plugin, as we do in the Babel repository? That way if something breaks it's easier to identify why.
Def agree about the tests, I really don't like the current test suite, it's very confusing. |
Yeah, we should definitely add some unit tests as well that's just input=>output. I like the current tests, but they are integration tests, not unit tests. Probably not for this PR, though 😀 |
Added the unit tests rewrite to my legendary Jest todo list 👌 😂 |
Thanks for landing this @jeysal, and thanks for your help @nicolo-ribaudo! |
This pull request has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs. |
Summary
This doesn't work. Output after running babel on it is
So the mock call is correctly hoisted (which is probably a bug actually, we should only hoist the "global"
jest
, not any variable namedjest
), but therequire
call is not high enough.@jeysal @nicolo-ribaudo any help appreciated - I'm on very thin ground when doing AST modifications 😀
Test plan
Test added.