mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-10-05 02:43:32 +00:00
fix(exports): recognize imported and expression-local receivers
This commit is contained in:
parent
a1c7706886
commit
677b56053d
2 changed files with 37 additions and 2 deletions
|
|
@ -57,18 +57,33 @@ function bindsReceiver(node: SyntaxNode | null, name: string): boolean {
|
|||
if (node.type === 'assignment_pattern')
|
||||
return bindsReceiver(node.childForFieldName('left'), name);
|
||||
if (node.type === 'pair_pattern') return bindsReceiver(node.childForFieldName('value'), name);
|
||||
if (node.type === 'import_specifier') {
|
||||
return bindsReceiver(node.childForFieldName('alias') ?? node.childForFieldName('name'), name);
|
||||
}
|
||||
if (node.type === 'required_parameter' || node.type === 'optional_parameter') {
|
||||
return bindsReceiver(node.childForFieldName('pattern'), name);
|
||||
}
|
||||
return (
|
||||
['formal_parameters', 'object_pattern', 'array_pattern', 'rest_pattern'].includes(node.type) &&
|
||||
node.namedChildren.some((child) => bindsReceiver(child, name))
|
||||
[
|
||||
'formal_parameters',
|
||||
'object_pattern',
|
||||
'array_pattern',
|
||||
'rest_pattern',
|
||||
'import_clause',
|
||||
'named_imports',
|
||||
'namespace_import',
|
||||
].includes(node.type) && node.namedChildren.some((child) => bindsReceiver(child, name))
|
||||
);
|
||||
}
|
||||
|
||||
/** A locally bound `module`/`exports` is not Node's export receiver. */
|
||||
function isExportReceiverShadowed(node: SyntaxNode, name: string): boolean {
|
||||
for (let scope = node.parent; scope !== null; scope = scope.parent) {
|
||||
if (
|
||||
['function_expression', 'generator_function', 'class'].includes(scope.type) &&
|
||||
scope.childForFieldName('name')?.text === name
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
bindsReceiver(scope.childForFieldName('parameters'), name) ||
|
||||
bindsReceiver(scope.childForFieldName('parameter'), name)
|
||||
|
|
@ -81,6 +96,13 @@ function isExportReceiverShadowed(node: SyntaxNode, name: string): boolean {
|
|||
? statement.childForFieldName('declaration')
|
||||
: statement;
|
||||
if (declaration === null) continue;
|
||||
if (
|
||||
declaration.type === 'import_statement' &&
|
||||
declaration.namedChildren.some(
|
||||
(child) => child.type === 'import_clause' && bindsReceiver(child, name),
|
||||
)
|
||||
)
|
||||
return true;
|
||||
if (
|
||||
declaration.type === 'lexical_declaration' ||
|
||||
declaration.type === 'variable_declaration'
|
||||
|
|
|
|||
|
|
@ -174,6 +174,10 @@ describe('@declaration.is-exported (JavaScript emitter)', () => {
|
|||
'function wrapper() { { module.exports = {}; let module; } }',
|
||||
'function wrapper({ receiver: module }) { module.exports = {}; }',
|
||||
'const module = {}; module.exports = { alpha() {} };',
|
||||
"import module from './other'; module.exports = {};",
|
||||
"import { receiver as exports } from './other'; exports.alpha = 1;",
|
||||
"import * as module from './other'; module.exports = {};",
|
||||
'const wrapper = function module() { module.exports = {}; };',
|
||||
])('ignores a shadowed CommonJS receiver: %s', (source) => {
|
||||
for (const [emit, file] of [
|
||||
[emitJsScopeCaptures, 'x.js'],
|
||||
|
|
@ -198,6 +202,15 @@ describe('@declaration.is-exported (JavaScript emitter)', () => {
|
|||
expect(v.hidden).toBeUndefined();
|
||||
});
|
||||
|
||||
it('an imported source name does not shadow a different local alias', () => {
|
||||
const v = verdicts(
|
||||
emitJsScopeCaptures,
|
||||
"import { module as other } from './other'; module.exports = {}; function hidden() {}",
|
||||
'x.js',
|
||||
);
|
||||
expect(v.hidden).toBeUndefined();
|
||||
});
|
||||
|
||||
it.each(["module['exports']", 'module["exports"]'])(
|
||||
'recognizes %s object methods and properties as exports',
|
||||
(target) => {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue