-
Notifications
You must be signed in to change notification settings - Fork 115
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
"TypeError: illegal invocation" when imported in multiple tests #53
Comments
This comment was marked as resolved.
This comment was marked as resolved.
Can you change the minimal example to use plain javascript instead of typescript? What version of Node.js are you using? If you're using >= 12, can you try with Node 10? |
Also, thank you for the report and for creating a minimal reproduction case! |
This is the minimal reproduction with JavaScript: https://github.com/rien/node-tree-sitter-bug-minimal-reproducible-example/ I'm currently using Node 10.17. |
I can't seem to reproduce this outside Jest. I have configured ava with more than 100 tests re-importing and successfully using I have made an issue at Jest: jestjs/jest#9206, maybe they know where to look for a solution. It seems I'll switch testing framework then. |
Whoops, I mean to comment here, but commented on the jest issue. I think this is a bug in Jest, or the way that you're using Jest. Each source file should be evaluated once, but in your case, Tree-sitter's entry-point file |
Thank you for looking into this. I'm not familiar with how native libraries should work. If they're not meant to be loaded more than once, then there is definitely something going wrong on Jest's side. |
I am struggling with exactly the same issue and hope this will be fixed. |
The reason this happens is becuase Jest runs a pool of child processes, and resets the state of each process for a new test. If 2 tests require |
The solution is to implement Language as a node addon. https://github.com/nodejs/node-addon-api/blob/main/doc/addon.md Note the description:
It explicitly states that it is expected behavior to load the same script multiple times, as Jest is doing here. Thus #52 is definitely a step in the direction to fix this and probably all the other instabilities (crashing on running certain queries in Docker) |
more context - I ported everything to N-API and it did not fix this issue. The reason is that the issue is actually in /*
* Tree
*/
const {rootNode, edit} = Tree.prototype;
Object.defineProperty(Tree.prototype, 'rootNode', {
get() {
return unmarshalNode(rootNode.call(this), this);
}
}); to be /*
* Tree
*/
const {rootNode, edit} = Tree.prototype;
Object.defineProperty(Tree.prototype, 'rootNode', {
get() {
if (!this.input) {
console.log(this);
}
return unmarshalNode(rootNode.call(this), this);
}
}); I got back basically, we can't do this pattern of extending a native module in node in a multi-threaded env. When I eliminated the prototype overwrite, and instead used this function: function getRootNode(tree) {
return unmarshalNode(rootNode.call(tree), tree);
} const node = jsParser.parse(`
const Parser = require(".");
const Javascript = require("tree-sitter-javascript");
const jsParser = new Parser();
`);
getRootNode(node).toString(); This worked great. To fix will require a breaking change to the API. |
I have a fix, PR incoming |
It turns out Jest runs poorly with tree-sitter. tree-sitter/node-tree-sitter#53 None of the mentioned workarounds worked.
provide a simple idea if (globalThis.__module__exports__) {
module.exports = globalThis.__module__exports__
}
else {
//....
globalThis.__module__exports__ = module.exports;
} readFile("node_modules\\tree-sitter\\index.js", "utf-8", (err, str) =>
{
if (err)
{
console.error("hack tree-sitter error!", err);
return;
}
if (str.includes("__tree_sitter__module__export__")) return;
str = `if (globalThis.__tree_sitter__module__export__)
module.exports = globalThis.__tree_sitter__module__export__
else {
${str}
globalThis.__tree_sitter__module__export__ = module.exports;
}`;
});
readFile("node_modules\\tree-sitter-cpp\\bindings\\node\\index.js", "utf-8", (err, str) =>
{
if (err)
{
console.error("hack tree-sitter-cpp error!", err);
return;
}
if (str.includes("__tree_sitter_cpp__module__export__")) return;
str = `if (globalThis.__tree_sitter_cpp__module__export__)
module.exports = globalThis.__tree_sitter_cpp__module__export__
else {
${str}
globalThis.__tree_sitter_cpp__module__export__ = module.exports;
}`;
writeFile("node_modules\\tree-sitter-cpp\\bindings\\node\\index.js", str, err => { });
}); |
Thanks for tree-sitter, it's been a joy to work with thus far. I ran into this today. Any chance #75 could get merged, please? |
I am having a strange bug when two (or more) test files indirectly use
tree-sitter
, the second import throws the following error:I have made a minimal reproducible example at https://github.com/rien/node-tree-sitter-bug-minimal-reproducible-example with more info.
Running each test individually (so
tree-sitter
is only imported once) does not exhibit this behaviour.I am writing a CLI app using typescript and using jest as testing framework.
Any idea what could be causing this issue?
The text was updated successfully, but these errors were encountered: