Skip to content

Commit efaac80

Browse files
authored
Prevent exceptions from being thrown on invalid code (#33)
* Update dependencies * Fix issue where invalid code would throw an exception. Now it will print a debug error message instead. * Add tests on Node 22.x
1 parent b2f7e1b commit efaac80

File tree

5 files changed

+81
-68
lines changed

5 files changed

+81
-68
lines changed

.github/workflows/node.js.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616

1717
strategy:
1818
matrix:
19-
node-version: [18.x, 20.x]
19+
node-version: [18.x, 20.x, 22.x]
2020
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
2121

2222
steps:

package-lock.json

+47-52
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
"estraverse": "^5.3.0"
3333
},
3434
"devDependencies": {
35-
"eslint": "^9.14.0",
36-
"husky": "^9.1.6"
35+
"eslint": "^9.16.0",
36+
"husky": "^9.1.7"
3737
}
3838
}

src/flast.js

+20-13
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import {parse} from 'espree';
2-
import {generate, attachComments} from 'escodegen';
32
import estraverse from 'estraverse';
43
import {analyze} from 'eslint-scope';
4+
import {logger} from './utils/logger.js';
5+
import {generate, attachComments} from 'escodegen';
56

67
const ecmaVersion = 'latest';
78
const sourceType = 'module';
@@ -74,12 +75,15 @@ function createSrcClosure(src) {
7475
*/
7576
function generateFlatAST(inputCode, opts = {}) {
7677
opts = { ...generateFlatASTDefaultOptions, ...opts };
78+
let tree = [];
7779
const rootNode = generateRootNode(inputCode, opts);
78-
const tree = extractNodesFromRoot(rootNode, opts);
79-
if (opts.detailed) {
80-
const scopes = getAllScopes(rootNode);
81-
for (let i = 0; i < tree.length; i++) injectScopeToNode(tree[i], scopes);
82-
tree[0].allScopes = scopes;
80+
if (rootNode) {
81+
tree = extractNodesFromRoot(rootNode, opts);
82+
if (opts.detailed) {
83+
const scopes = getAllScopes(rootNode);
84+
for (let i = 0; i < tree.length; i++) injectScopeToNode(tree[i], scopes);
85+
tree[0].allScopes = scopes;
86+
}
8387
}
8488
return tree;
8589
}
@@ -115,6 +119,7 @@ function generateRootNode(inputCode, opts = {}) {
115119
if (opts.includeSrc) rootNode.srcClosure = createSrcClosure(inputCode);
116120
} catch (e) {
117121
if (opts.alernateSourceTypeOnFailure && e.message.includes('in strict mode')) rootNode = parseCode(inputCode, {...parseOpts, sourceType: 'script'});
122+
else logger.debug(e);
118123
}
119124
return rootNode;
120125
}
@@ -279,15 +284,17 @@ function matchScopeToNode(node, allScopes) {
279284
*/
280285
async function generateFlatASTAsync(inputCode, opts = {}) {
281286
opts = { ...generateFlatASTDefaultOptions, ...opts };
282-
const rootNode = generateRootNode(inputCode, opts);
283-
const tree = extractNodesFromRoot(rootNode, opts);
287+
let tree = [];
284288
const promises = [];
285-
if (opts.detailed) {
286-
const scopes = getAllScopes(rootNode);
287-
for (let i = 0; i < tree.length; i++) {
288-
promises.push(injectScopeToNodeAsync(tree[i], scopes));
289+
const rootNode = generateRootNode(inputCode, opts);
290+
if (rootNode) {
291+
tree = extractNodesFromRoot(rootNode, opts);
292+
if (opts.detailed) {
293+
const scopes = getAllScopes(rootNode);
294+
for (let i = 0; i < tree.length; i++) {
295+
promises.push(injectScopeToNodeAsync(tree[i], scopes));
296+
}
289297
}
290-
291298
}
292299
return Promise.all(promises).then(() => tree);
293300
}

tests/functionality.test.js

+11
Original file line numberDiff line numberDiff line change
@@ -117,4 +117,15 @@ describe('Functionality tests', () => {
117117
assert.equal(unparsedAst.length, 0, `Script was not parsed.${unparsedError ? 'Error: ' + unparsedError : ''}`);
118118
assert.ok(parsedAst.length, `Script was not parsed.${parsedError ? 'Error: ' + parsedError : ''}`);
119119
});
120+
it(`Verify generateFlatAST doesn't throw an exception for invalid code`, () => {
121+
const code = `return a;`;
122+
let result;
123+
const expectedResult = [];
124+
try {
125+
result = generateFlatAST(code, {alernateSourceTypeOnFailure: false});
126+
} catch (e) {
127+
result = e.message;
128+
}
129+
assert.deepStrictEqual(result, expectedResult);
130+
});
120131
});

0 commit comments

Comments
 (0)