@@ -345,7 +345,17 @@ abstract class ExportDeclaration extends Stmt, @export_declaration {
345345
346346 /** Holds if this export declaration exports variable `v` under the name `name`. */
347347 overlay [ global]
348- abstract predicate exportsAs ( LexicalName v , string name ) ;
348+ final predicate exportsAs ( LexicalName v , string name ) {
349+ this .exportsDirectlyAs ( v , name )
350+ or
351+ this .( ReExportDeclaration ) .reExportsAs ( v , name )
352+ }
353+
354+ /**
355+ * Holds if this export declaration exports variable `v` under the name `name`,
356+ * not counting re-exports.
357+ */
358+ predicate exportsDirectlyAs ( LexicalName v , string name ) { none ( ) }
349359
350360 /**
351361 * Gets the data flow node corresponding to the value this declaration exports
@@ -369,7 +379,17 @@ abstract class ExportDeclaration extends Stmt, @export_declaration {
369379 * to module `a` or possibly to some other module from which `a` re-exports.
370380 */
371381 overlay [ global]
372- abstract DataFlow:: Node getSourceNode ( string name ) ;
382+ final DataFlow:: Node getSourceNode ( string name ) {
383+ result = this .getDirectSourceNode ( name )
384+ or
385+ result = this .( ReExportDeclaration ) .getReExportedSourceNode ( name )
386+ }
387+
388+ /**
389+ * Gets the data flow node corresponding to the value this declaration exports
390+ * under the name `name`, not including sources that come from a re-export.
391+ */
392+ DataFlow:: Node getDirectSourceNode ( string name ) { none ( ) }
373393
374394 /** Holds if is declared with the `type` keyword, so only types are exported. */
375395 predicate isTypeOnly ( ) { has_type_keyword ( this ) }
@@ -421,20 +441,20 @@ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declarati
421441 override ConstantString getImportedPath ( ) { result = this .getChildExpr ( 0 ) }
422442
423443 overlay [ global]
424- override predicate exportsAs ( LexicalName v , string name ) {
444+ override predicate reExportsAs ( LexicalName v , string name ) {
425445 this .getReExportedES2015Module ( ) .exportsAs ( v , name ) and
426- not isShadowedFromBulkExport ( this , name )
446+ not isShadowedFromBulkExport ( this . getEnclosingModule ( ) , name )
427447 }
428448
429449 overlay [ global]
430- override DataFlow:: Node getSourceNode ( string name ) {
450+ override DataFlow:: Node getReExportedSourceNode ( string name ) {
431451 result = this .getReExportedES2015Module ( ) .getAnExport ( ) .getSourceNode ( name )
432452 }
433453}
434454
435455/**
436- * Holds if the given bulk export `reExport ` should not re-export `name` because there is an explicit export
437- * of that name in the same module .
456+ * Holds if bulk re-exports in `mod ` should not re-export `name` because there is an explicit export
457+ * of that name in `mod` .
438458 *
439459 * At compile time, shadowing works across declaration spaces.
440460 * For instance, directly exporting an interface `X` will block a variable `X` from being re-exported:
@@ -446,8 +466,8 @@ class BulkReExportDeclaration extends ReExportDeclaration, @export_all_declarati
446466 * but we ignore this subtlety.
447467 */
448468overlay [ global]
449- private predicate isShadowedFromBulkExport ( BulkReExportDeclaration reExport , string name ) {
450- exists ( ExportNamedDeclaration other | other .getTopLevel ( ) = reExport . getEnclosingModule ( ) |
469+ private predicate isShadowedFromBulkExport ( Module mod , string name ) {
470+ exists ( ExportNamedDeclaration other | other .getTopLevel ( ) = mod |
451471 other .getAnExportedDecl ( ) .getName ( ) = name
452472 or
453473 other .getASpecifier ( ) .getExportedName ( ) = name
@@ -468,8 +488,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar
468488 /** Gets the operand statement or expression that is exported by this declaration. */
469489 ExprOrStmt getOperand ( ) { result = this .getChild ( 0 ) }
470490
471- overlay [ global]
472- override predicate exportsAs ( LexicalName v , string name ) {
491+ override predicate exportsDirectlyAs ( LexicalName v , string name ) {
473492 name = "default" and v = this .getADecl ( ) .getVariable ( )
474493 }
475494
@@ -481,8 +500,7 @@ class ExportDefaultDeclaration extends ExportDeclaration, @export_default_declar
481500 )
482501 }
483502
484- overlay [ global]
485- override DataFlow:: Node getSourceNode ( string name ) {
503+ override DataFlow:: Node getDirectSourceNode ( string name ) {
486504 name = "default" and result = DataFlow:: valueNode ( this .getOperand ( ) )
487505 }
488506}
@@ -524,21 +542,20 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio
524542 /** Gets the variable declaration, if any, exported by this named export. */
525543 VarDecl getADecl ( ) { result = this .getAnExportedDecl ( ) }
526544
527- overlay [ global]
528- override predicate exportsAs ( LexicalName v , string name ) {
529- exists ( LexicalDecl vd | vd = this .getAnExportedDecl ( ) |
530- name = vd .getName ( ) and v = vd .getALexicalName ( )
531- )
532- or
533- exists ( ExportSpecifier spec | spec = this .getASpecifier ( ) and name = spec .getExportedName ( ) |
534- v = spec .getLocal ( ) .( LexicalAccess ) .getALexicalName ( )
545+ override predicate exportsDirectlyAs ( LexicalName v , string name ) {
546+ (
547+ exists ( LexicalDecl vd | vd = this .getAnExportedDecl ( ) |
548+ name = vd .getName ( ) and v = vd .getALexicalName ( )
549+ )
535550 or
536- this .( ReExportDeclaration ) .getReExportedES2015Module ( ) .exportsAs ( v , spec .getLocalName ( ) )
537- )
551+ exists ( ExportSpecifier spec | spec = this .getASpecifier ( ) and name = spec .getExportedName ( ) |
552+ v = spec .getLocal ( ) .( LexicalAccess ) .getALexicalName ( )
553+ )
554+ ) and
555+ not ( this .isTypeOnly ( ) and v instanceof Variable )
538556 }
539557
540- overlay [ global]
541- override DataFlow:: Node getSourceNode ( string name ) {
558+ override DataFlow:: Node getDirectSourceNode ( string name ) {
542559 exists ( VarDef d | d .getTarget ( ) = this .getADecl ( ) |
543560 name = d .getTarget ( ) .( VarDecl ) .getName ( ) and
544561 result = DataFlow:: valueNode ( d .getSource ( ) )
@@ -554,12 +571,11 @@ class ExportNamedDeclaration extends ExportDeclaration, @export_named_declaratio
554571 exists ( ExportSpecifier spec | spec = this .getASpecifier ( ) and name = spec .getExportedName ( ) |
555572 not exists ( this .getImportedPath ( ) ) and result = DataFlow:: valueNode ( spec .getLocal ( ) )
556573 or
557- exists ( ReExportDeclaration red | red = this |
558- result = red .getReExportedES2015Module ( ) .getAnExport ( ) .getSourceNode ( spec .getLocalName ( ) )
559- or
560- spec instanceof ExportNamespaceSpecifier and
561- result = DataFlow:: valueNode ( spec )
562- )
574+ // For `export * as B from ".."`, we use the ExportNamespaceSpecifier as a representative for the
575+ // object that gets exposed as `B`.
576+ this instanceof ReExportDeclaration and
577+ spec instanceof ExportNamespaceSpecifier and
578+ result = DataFlow:: valueNode ( spec )
563579 )
564580 }
565581
@@ -587,19 +603,6 @@ private class ExportNamespaceStep extends PreCallGraphStep {
587603 }
588604}
589605
590- /**
591- * An export declaration with the `type` modifier.
592- */
593- private class TypeOnlyExportDeclaration extends ExportNamedDeclaration {
594- TypeOnlyExportDeclaration ( ) { this .isTypeOnly ( ) }
595-
596- overlay [ global]
597- override predicate exportsAs ( LexicalName v , string name ) {
598- super .exportsAs ( v , name ) and
599- not v instanceof Variable
600- }
601- }
602-
603606/**
604607 * An export specifier in an export declaration.
605608 *
@@ -777,6 +780,20 @@ abstract class ReExportDeclaration extends ExportDeclaration {
777780 Stages:: Imports:: ref ( ) and
778781 result .getFile ( ) = ImportPathResolver:: resolveExpr ( this .getImportedPath ( ) )
779782 }
783+
784+ /**
785+ * Holds if this re-export declaration ultimately re-exports `v` (from another module)
786+ * under the given `name`.
787+ */
788+ overlay [ global]
789+ abstract predicate reExportsAs ( LexicalName v , string name ) ;
790+
791+ /**
792+ * Gets the data flow node (from another module) corresponding to the value that is re-exported
793+ * under the name `name`.
794+ */
795+ overlay [ global]
796+ abstract DataFlow:: Node getReExportedSourceNode ( string name ) ;
780797}
781798
782799/** A literal path expression appearing in a re-export declaration. */
@@ -803,6 +820,21 @@ class SelectiveReExportDeclaration extends ReExportDeclaration, ExportNamedDecla
803820 override ConstantString getImportedPath ( ) {
804821 result = ExportNamedDeclaration .super .getImportedPath ( )
805822 }
823+
824+ overlay [ global]
825+ override predicate reExportsAs ( LexicalName v , string name ) {
826+ exists ( ExportSpecifier spec | spec = this .getASpecifier ( ) and name = spec .getExportedName ( ) |
827+ this .getReExportedES2015Module ( ) .exportsAs ( v , spec .getLocalName ( ) )
828+ ) and
829+ not ( this .isTypeOnly ( ) and v instanceof Variable )
830+ }
831+
832+ overlay [ global]
833+ override DataFlow:: Node getReExportedSourceNode ( string name ) {
834+ exists ( ExportSpecifier spec | spec = this .getASpecifier ( ) and name = spec .getExportedName ( ) |
835+ result = this .getReExportedES2015Module ( ) .getAnExport ( ) .getSourceNode ( spec .getLocalName ( ) )
836+ )
837+ }
806838}
807839
808840/**
@@ -819,16 +851,4 @@ class SelectiveReExportDeclaration extends ReExportDeclaration, ExportNamedDecla
819851 */
820852class OriginalExportDeclaration extends ExportDeclaration {
821853 OriginalExportDeclaration ( ) { not this instanceof ReExportDeclaration }
822-
823- overlay [ global]
824- override predicate exportsAs ( LexicalName v , string name ) {
825- this .( ExportDefaultDeclaration ) .exportsAs ( v , name ) or
826- this .( ExportNamedDeclaration ) .exportsAs ( v , name )
827- }
828-
829- overlay [ global]
830- override DataFlow:: Node getSourceNode ( string name ) {
831- result = this .( ExportDefaultDeclaration ) .getSourceNode ( name ) or
832- result = this .( ExportNamedDeclaration ) .getSourceNode ( name )
833- }
834854}
0 commit comments