Skip to content

Commit e309de1

Browse files
try to optimize
1 parent d385c36 commit e309de1

4 files changed

Lines changed: 177 additions & 159 deletions

File tree

src/generators/api-links/utils/checkIndirectReferences.mjs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,25 @@
1-
import { visit } from 'estree-util-visit';
1+
'use strict';
22

33
import { getLineNumber } from './getLineNumber.mjs';
44

5+
/**
6+
*
7+
*/
8+
function walkTopLevelStatements(program, callback) {
9+
const body = program.body;
10+
if (!body) {
11+
return;
12+
}
13+
14+
for (let i = 0; i < body.length; i++) {
15+
const node = body[i];
16+
callback(node);
17+
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
18+
callback(node.declaration);
19+
}
20+
}
21+
}
22+
523
/**
624
* @param {import('@oxc-project/types').Program} program
725
* @param {import('../types.d.ts').ProgramExports} exports
@@ -12,7 +30,7 @@ export function checkIndirectReferences(program, exports, nameToLineNumberMap) {
1230
return;
1331
}
1432

15-
visit(program, node => {
33+
walkTopLevelStatements(program, node => {
1634
if (node.type !== 'FunctionDeclaration') {
1735
return;
1836
}
@@ -22,7 +40,8 @@ export function checkIndirectReferences(program, exports, nameToLineNumberMap) {
2240
if (name in exports.indirects) {
2341
nameToLineNumberMap[exports.indirects[name]] = getLineNumber(
2442
program.sourceText,
25-
node.range[0]
43+
node.range[0],
44+
program
2645
);
2746
}
2847
});

src/generators/api-links/utils/extractExports.mjs

Lines changed: 57 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
'use strict';
22

3-
import { visit } from 'estree-util-visit';
4-
53
import { getLineNumber } from './getLineNumber.mjs';
64
import { CONSTRUCTOR_EXPRESSION } from '../constants.mjs';
75

86
/**
9-
* @see https://github.com/estree/estree/blob/master/es5.md#assignmentexpression
10-
*
117
* @param {import('@oxc-project/types').ExpressionStatement} node
128
* @param {string} basename
139
* @param {Record<string, number>} nameToLineNumberMap
1410
* @param {string} sourceText
11+
* @param {import('@oxc-project/types').Program} program
1512
* @returns {import('../types').ProgramExports | undefined}
1613
*/
17-
function handleExpression(node, basename, nameToLineNumberMap, sourceText) {
14+
function handleExpression(
15+
node,
16+
basename,
17+
nameToLineNumberMap,
18+
sourceText,
19+
program
20+
) {
1821
const { expression } = node;
1922

2023
if (expression.type !== 'AssignmentExpression') {
2124
return;
2225
}
2326

24-
// `a=b`, lhs=`a` and rhs=`b`
2527
let { left: lhs, right: rhs } = expression;
2628

2729
if (lhs.type !== 'MemberExpression') {
@@ -32,114 +34,73 @@ function handleExpression(node, basename, nameToLineNumberMap, sourceText) {
3234
lhs = lhs.object;
3335
}
3436

35-
/**
36-
* @type {import('../types').ProgramExports}
37-
*/
3837
const exports = {
3938
ctors: [],
4039
identifiers: [],
4140
indirects: {},
4241
};
4342

4443
if (lhs.object.name === 'exports') {
45-
// This is an assignment to a property in `module.exports` or `exports`
46-
// (i.e. `module.exports.asd = ...` or `exports.asd = ...`)
47-
4844
switch (rhs.type) {
49-
/** @see https://github.com/estree/estree/blob/master/es5.md#functionexpression */
5045
case 'FunctionExpression': {
51-
// module.exports.something = () => {}
5246
nameToLineNumberMap[`${basename}.${lhs.property.name}`] = getLineNumber(
5347
sourceText,
54-
node.range[0]
48+
node.range[0],
49+
program
5550
);
56-
5751
break;
5852
}
59-
/** @see https://github.com/estree/estree/blob/master/es5.md#identifier */
6053
case 'Identifier': {
61-
// Save this for later in case it's referenced
62-
// exports.Buffer = Buffer -> indirect mapping
6354
exports.indirects[rhs.name] = `${basename}.${lhs.property.name}`;
64-
6555
break;
6656
}
6757
default: {
6858
if (lhs.property.name !== undefined) {
6959
exports.identifiers.push(lhs.property.name);
7060
}
71-
7261
break;
7362
}
7463
}
7564
} else if (lhs.object.name === 'module' && lhs.property.name === 'exports') {
76-
// This is an assignment to `module.exports` as a whole
77-
// (i.e. `module.exports = {}`)
78-
79-
// We need to move right until we find the value of the assignment.
80-
// (if `a=b`, we want `b`)
8165
while (rhs.type === 'AssignmentExpression') {
8266
rhs = rhs.right;
8367
}
8468

8569
switch (rhs.type) {
86-
/** @see https://github.com/estree/estree/blob/master/es5.md#newexpression */
8770
case 'NewExpression': {
88-
// module.exports = new Asd()
8971
exports.ctors.push(rhs.callee.name);
9072
break;
9173
}
92-
/** @see https://github.com/estree/estree/blob/master/es5.md#objectexpression */
9374
case 'ObjectExpression': {
94-
// module.exports = {}
95-
// we need to go through all of the properties and register them
9675
rhs.properties.forEach(({ value }) => {
76+
if (!value) {
77+
return;
78+
}
9779
switch (value.type) {
9880
case 'Identifier': {
9981
exports.identifiers.push(value.name);
100-
10182
if (CONSTRUCTOR_EXPRESSION.test(value.name[0])) {
10283
exports.ctors.push(value.name);
10384
}
104-
10585
break;
10686
}
10787
case 'CallExpression': {
108-
if (value.callee.name !== 'deprecate') {
109-
break;
88+
if (value.callee.name === 'deprecate' && value.arguments[0]) {
89+
exports.identifiers.push(value.arguments[0].name);
11090
}
111-
112-
// Handle exports wrapped in the `deprecate` function
113-
// Ex/ https://github.com/nodejs/node/blob/e96072ad57348ce423a8dd7639dcc3d1c34e847d/lib/buffer.js#L1334
114-
115-
exports.identifiers.push(value.arguments[0].name);
116-
11791
break;
11892
}
119-
default: {
120-
// Not relevant
121-
}
12293
}
12394
});
124-
12595
break;
12696
}
127-
/** @see https://github.com/estree/estree/blob/master/es5.md#identifier */
12897
case 'Identifier': {
129-
// Something else, let's save it for when we're searching for
130-
// declarations
131-
13298
if (rhs.name !== undefined) {
13399
exports.identifiers.push(rhs.name);
134100
if (CONSTRUCTOR_EXPRESSION.test(rhs.name[0])) {
135101
exports.ctors.push(rhs.name);
136102
}
137103
}
138-
139-
break;
140-
}
141-
default: {
142-
// Not relevant
143104
break;
144105
}
145106
}
@@ -149,23 +110,20 @@ function handleExpression(node, basename, nameToLineNumberMap, sourceText) {
149110
}
150111

151112
/**
152-
* @see https://github.com/estree/estree/blob/master/es5.md#variabledeclaration
153-
*
154113
* @param {import('@oxc-project/types').VariableDeclaration} node
155114
* @param {string} basename
156115
* @param {Record<string, number>} nameToLineNumberMap
157116
* @param {string} sourceText
117+
* @param {import('@oxc-project/types').Program} program
158118
* @returns {import('../types').ProgramExports | undefined}
159119
*/
160120
function handleVariableDeclaration(
161121
node,
162122
basename,
163123
nameToLineNumberMap,
164-
sourceText
124+
sourceText,
125+
program
165126
) {
166-
/**
167-
* @type {import('../types').ProgramExports}
168-
*/
169127
const exports = {
170128
ctors: [],
171129
identifiers: [],
@@ -177,14 +135,10 @@ function handleVariableDeclaration(
177135
const id = declarator.id;
178136

179137
while (lhs && lhs.type === 'AssignmentExpression') {
180-
// Move left until we get to what we're assigning to
181-
// (if `a=b`, we want `a`)
182138
lhs = lhs.left;
183139
}
184140

185141
if (!lhs || lhs.type !== 'MemberExpression') {
186-
// Doesn't exist or we're not writing to an object
187-
// (aka it's just a regular variable like `const a = 123`)
188142
return;
189143
}
190144

@@ -194,9 +148,9 @@ function handleVariableDeclaration(
194148
case 'exports': {
195149
nameToLineNumberMap[`${basename}.${lhs.property.name}`] = getLineNumber(
196150
sourceText,
197-
range[0]
151+
range[0],
152+
program
198153
);
199-
200154
break;
201155
}
202156
case 'module': {
@@ -205,12 +159,11 @@ function handleVariableDeclaration(
205159
}
206160

207161
exports.ctors.push(id.name);
208-
nameToLineNumberMap[id.name] = getLineNumber(sourceText, range[0]);
209-
210-
break;
211-
}
212-
default: {
213-
// Not relevant to us
162+
nameToLineNumberMap[id.name] = getLineNumber(
163+
sourceText,
164+
range[0],
165+
program
166+
);
214167
break;
215168
}
216169
}
@@ -220,22 +173,32 @@ function handleVariableDeclaration(
220173
}
221174

222175
/**
223-
* We need to find what a source file exports so we know what to include in
224-
* the final result. We can do this by going through every statement in the
225-
* program looking for assignments to `module.exports`.
226-
*
227-
* Noteworthy that exports can happen throughout the program so we need to
228-
* go through the entire thing.
229-
*
176+
* Iterates top-level program statements efficiently without deep AST traversal.
177+
* @param {import('@oxc-project/types').Program} program
178+
* @param {function(import('@oxc-project/types').Node): void} callback
179+
*/
180+
function walkTopLevelStatements(program, callback) {
181+
const body = program.body;
182+
if (!body) {
183+
return;
184+
}
185+
186+
for (let i = 0; i < body.length; i++) {
187+
const node = body[i];
188+
callback(node);
189+
if (node.type === 'ExportNamedDeclaration' && node.declaration) {
190+
callback(node.declaration);
191+
}
192+
}
193+
}
194+
195+
/**
230196
* @param {import('@oxc-project/types').Program} program
231197
* @param {string} basename
232198
* @param {Record<string, number>} nameToLineNumberMap
233199
* @returns {import('../types').ProgramExports}
234200
*/
235201
export function extractExports(program, basename, nameToLineNumberMap) {
236-
/**
237-
* @type {import('../types').ProgramExports}
238-
*/
239202
const exports = {
240203
ctors: [],
241204
identifiers: [],
@@ -244,27 +207,33 @@ export function extractExports(program, basename, nameToLineNumberMap) {
244207

245208
const TYPE_TO_HANDLER_MAP = {
246209
/**
247-
* @param {import('@oxc-project/types').Node} node
210+
*
248211
*/
249212
ExpressionStatement: node =>
250-
handleExpression(node, basename, nameToLineNumberMap, program.sourceText),
213+
handleExpression(
214+
node,
215+
basename,
216+
nameToLineNumberMap,
217+
program.sourceText,
218+
program
219+
),
251220

252221
/**
253-
* @param {import('@oxc-project/types').Node} node
222+
*
254223
*/
255224
VariableDeclaration: node =>
256225
handleVariableDeclaration(
257226
node,
258227
basename,
259228
nameToLineNumberMap,
260-
program.sourceText
229+
program.sourceText,
230+
program
261231
),
262232
};
263233

264-
visit(program, node => {
234+
walkTopLevelStatements(program, node => {
265235
if (node.type in TYPE_TO_HANDLER_MAP) {
266236
const handler = TYPE_TO_HANDLER_MAP[node.type];
267-
268237
const output = handler(node);
269238

270239
if (output) {

0 commit comments

Comments
 (0)