@@ -3606,4 +3606,216 @@ describe("SourceCode", () => {
36063606 assert . isNull ( problem . ruleId ) ;
36073607 } ) ;
36083608 } ) ;
3609+
3610+ describe ( "finalize()" , ( ) => {
3611+ it ( "should remove ECMAScript globals from global scope's `implicit`" , ( ) => {
3612+ const code = "Array = 1; Foo = 1; Promise = 1; Array; Foo; Promise" ;
3613+ const ast = espree . parse ( code , DEFAULT_CONFIG ) ;
3614+ const scopeManager = eslintScope . analyze ( ast , {
3615+ ignoreEval : true ,
3616+ ecmaVersion : 6 ,
3617+ } ) ;
3618+ const sourceCode = new SourceCode ( {
3619+ text : code ,
3620+ ast,
3621+ scopeManager,
3622+ } ) ;
3623+
3624+ sourceCode . applyLanguageOptions ( {
3625+ ecmaVersion : 2015 ,
3626+ } ) ;
3627+
3628+ sourceCode . finalize ( ) ;
3629+
3630+ const globalScope = sourceCode . scopeManager . scopes [ 0 ] ;
3631+ const { implicit } = globalScope ;
3632+
3633+ assert . deepStrictEqual (
3634+ [ ...implicit . set ] . map ( ( [ name ] ) => name ) ,
3635+ [ "Foo" ] ,
3636+ ) ;
3637+ assert . deepStrictEqual (
3638+ implicit . variables . map ( ( { name } ) => name ) ,
3639+ [ "Foo" ] ,
3640+ ) ;
3641+ assert . deepStrictEqual (
3642+ implicit . left . map ( reference => reference . identifier . name ) ,
3643+ [ "Foo" , "Foo" ] ,
3644+ ) ;
3645+ } ) ;
3646+
3647+ it ( "should remove custom globals from global scope's `implicit`" , ( ) => {
3648+ const code = "Bar = 1; Foo = 1; Baz = 1; Bar; Foo; Baz" ;
3649+ const ast = espree . parse ( code , DEFAULT_CONFIG ) ;
3650+ const scopeManager = eslintScope . analyze ( ast , {
3651+ ignoreEval : true ,
3652+ ecmaVersion : 6 ,
3653+ } ) ;
3654+ const sourceCode = new SourceCode ( {
3655+ text : code ,
3656+ ast,
3657+ scopeManager,
3658+ } ) ;
3659+
3660+ sourceCode . applyLanguageOptions ( {
3661+ ecmaVersion : 2015 ,
3662+ globals : {
3663+ Bar : "writable" ,
3664+ Baz : "readonly" ,
3665+ } ,
3666+ } ) ;
3667+
3668+ sourceCode . finalize ( ) ;
3669+
3670+ const globalScope = sourceCode . scopeManager . scopes [ 0 ] ;
3671+ const { implicit } = globalScope ;
3672+
3673+ assert . deepStrictEqual (
3674+ [ ...implicit . set ] . map ( ( [ name ] ) => name ) ,
3675+ [ "Foo" ] ,
3676+ ) ;
3677+ assert . deepStrictEqual (
3678+ implicit . variables . map ( ( { name } ) => name ) ,
3679+ [ "Foo" ] ,
3680+ ) ;
3681+ assert . deepStrictEqual (
3682+ implicit . left . map ( reference => reference . identifier . name ) ,
3683+ [ "Foo" , "Foo" ] ,
3684+ ) ;
3685+ } ) ;
3686+
3687+ it ( "should remove commonjs globals from global scope's `implicit`" , ( ) => {
3688+ const code =
3689+ "exports = {}; Foo = 1; require = () => {}; exports; Foo; require" ;
3690+ const ast = espree . parse ( code , DEFAULT_CONFIG ) ;
3691+ const scopeManager = eslintScope . analyze ( ast , {
3692+ ignoreEval : true ,
3693+ nodejsScope : true ,
3694+ ecmaVersion : 6 ,
3695+ } ) ;
3696+ const sourceCode = new SourceCode ( {
3697+ text : code ,
3698+ ast,
3699+ scopeManager,
3700+ } ) ;
3701+
3702+ sourceCode . applyLanguageOptions ( {
3703+ ecmaVersion : 2015 ,
3704+ sourceType : "commonjs" ,
3705+ } ) ;
3706+
3707+ sourceCode . finalize ( ) ;
3708+
3709+ const globalScope = sourceCode . scopeManager . scopes [ 0 ] ;
3710+ const { implicit } = globalScope ;
3711+
3712+ assert . deepStrictEqual (
3713+ [ ...implicit . set ] . map ( ( [ name ] ) => name ) ,
3714+ [ "Foo" ] ,
3715+ ) ;
3716+ assert . deepStrictEqual (
3717+ implicit . variables . map ( ( { name } ) => name ) ,
3718+ [ "Foo" ] ,
3719+ ) ;
3720+ assert . deepStrictEqual (
3721+ implicit . left . map ( reference => reference . identifier . name ) ,
3722+ [ "Foo" , "Foo" ] ,
3723+ ) ;
3724+ } ) ;
3725+
3726+ it ( "should remove inline globals from global scope's `implicit`" , ( ) => {
3727+ const code =
3728+ "/* globals Bar: writable, Baz: readonly */ Bar = 1; Foo = 1; Baz = 1; Bar; Foo; Baz" ;
3729+ const ast = espree . parse ( code , DEFAULT_CONFIG ) ;
3730+ const scopeManager = eslintScope . analyze ( ast , {
3731+ ignoreEval : true ,
3732+ ecmaVersion : 6 ,
3733+ } ) ;
3734+ const sourceCode = new SourceCode ( {
3735+ text : code ,
3736+ ast,
3737+ scopeManager,
3738+ } ) ;
3739+
3740+ sourceCode . applyInlineConfig ( ) ;
3741+ sourceCode . finalize ( ) ;
3742+
3743+ const globalScope = sourceCode . scopeManager . scopes [ 0 ] ;
3744+ const { implicit } = globalScope ;
3745+
3746+ assert . deepStrictEqual (
3747+ [ ...implicit . set ] . map ( ( [ name ] ) => name ) ,
3748+ [ "Foo" ] ,
3749+ ) ;
3750+ assert . deepStrictEqual (
3751+ implicit . variables . map ( ( { name } ) => name ) ,
3752+ [ "Foo" ] ,
3753+ ) ;
3754+ assert . deepStrictEqual (
3755+ implicit . left . map ( reference => reference . identifier . name ) ,
3756+ [ "Foo" , "Foo" ] ,
3757+ ) ;
3758+ } ) ;
3759+
3760+ it ( "should not crash if global scope doesn't have `implicit` property" , ( ) => {
3761+ const code = "Array = 1; Foo = 1; Promise = 1; Array; Foo; Promise" ;
3762+ const ast = espree . parse ( code , DEFAULT_CONFIG ) ;
3763+ const scopeManager = eslintScope . analyze ( ast , {
3764+ ignoreEval : true ,
3765+ ecmaVersion : 6 ,
3766+ } ) ;
3767+
3768+ const globalScope = scopeManager . scopes [ 0 ] ;
3769+ delete globalScope . implicit ;
3770+
3771+ const sourceCode = new SourceCode ( {
3772+ text : code ,
3773+ ast,
3774+ scopeManager,
3775+ } ) ;
3776+
3777+ sourceCode . applyLanguageOptions ( {
3778+ ecmaVersion : 2015 ,
3779+ } ) ;
3780+
3781+ // should not throw
3782+ sourceCode . finalize ( ) ;
3783+ } ) ;
3784+
3785+ it ( "should not crash if global scope doesn't have `implicit.left` property" , ( ) => {
3786+ const code = "Array = 1; Foo = 1; Promise = 1; Array; Foo; Promise" ;
3787+ const ast = espree . parse ( code , DEFAULT_CONFIG ) ;
3788+ const scopeManager = eslintScope . analyze ( ast , {
3789+ ignoreEval : true ,
3790+ ecmaVersion : 6 ,
3791+ } ) ;
3792+
3793+ const globalScope = scopeManager . scopes [ 0 ] ;
3794+ delete globalScope . implicit . left ;
3795+
3796+ const sourceCode = new SourceCode ( {
3797+ text : code ,
3798+ ast,
3799+ scopeManager,
3800+ } ) ;
3801+
3802+ sourceCode . applyLanguageOptions ( {
3803+ ecmaVersion : 2015 ,
3804+ } ) ;
3805+
3806+ // should not throw
3807+ sourceCode . finalize ( ) ;
3808+
3809+ const { implicit } = globalScope ;
3810+
3811+ assert . deepStrictEqual (
3812+ [ ...implicit . set ] . map ( ( [ name ] ) => name ) ,
3813+ [ "Foo" ] ,
3814+ ) ;
3815+ assert . deepStrictEqual (
3816+ implicit . variables . map ( ( { name } ) => name ) ,
3817+ [ "Foo" ] ,
3818+ ) ;
3819+ } ) ;
3820+ } ) ;
36093821} ) ;
0 commit comments