From 551b01d2e0761f6114047f4ad9fd35e3e23af91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Sat, 2 Feb 2019 17:05:53 +0100 Subject: [PATCH 1/3] fix: scope sharing should not be influenced by globalReturn: true The 'node' environment sets parserOptions.ecmaFeatures.globalReturn to 'true'. Because of this, the JS code is considered as wrapped in a function, so declared variables are not in the global scope. To keep the configuration simple, scope sharing is only activated by parserOptions.sourceType = 'module', so setting globalReturn to true should still consider variables declared in the script body to be exported to the following scopes. Partially fixes #100 --- src/__tests__/plugin.js | 25 +++++++++++++++++++++++-- src/index.js | 31 ++++++++++++++++++++++--------- 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/__tests__/plugin.js b/src/__tests__/plugin.js index 9be8154..0c39349 100644 --- a/src/__tests__/plugin.js +++ b/src/__tests__/plugin.js @@ -596,7 +596,7 @@ it("should report correct eol-last message position", () => { }) describe("scope sharing", () => { - it("should share the global scope between script tags", () => { + it("should export global variables between script scopes", () => { const messages = execute("scope-sharing.html", { rules: { "no-console": "off", @@ -627,7 +627,7 @@ describe("scope sharing", () => { ) }) - it("should share the global scope between script tags", () => { + it("should mark variable as used when the variable is used in another tag", () => { const messages = execute("scope-sharing.html", { rules: { "no-console": "off", @@ -658,6 +658,27 @@ describe("scope sharing", () => { ) }) + it("should not be influenced by the ECMA feature 'globalReturn'", () => { + const messages = execute("scope-sharing.html", { + rules: { + "no-console": "off", + "no-undef": "error", + "no-unused-vars": "error", + }, + globals: { + console: false, + }, + env: { es6: true }, + parserOptions: { + ecmaFeatures: { + globalReturn: true, + }, + }, + }) + + expect(messages.length).toBe(8) + }) + it("should not share the global scope if sourceType is 'module'", () => { const messages = execute("scope-sharing.html", { rules: { diff --git a/src/index.js b/src/index.js index 64fc71f..22d93f3 100644 --- a/src/index.js +++ b/src/index.js @@ -197,12 +197,13 @@ function patch(Linter) { ) } - if (config.parserOptions && config.parserOptions.sourceType === "module") { + const parserOptions = config.parserOptions || {} + if (parserOptions.sourceType === "module") { for (const codePart of extractResult.code) { verifyCodePart(codePart) } } else { - verifyWithSharedScopes(extractResult.code, verifyCodePart) + verifyWithSharedScopes(extractResult.code, verifyCodePart, parserOptions) } messages.sort((ma, mb) => ma.line - mb.line || ma.column - mb.column) @@ -211,21 +212,33 @@ function patch(Linter) { } } -function verifyWithSharedScopes(codeParts, verifyCodePart) { +function verifyWithSharedScopes(codeParts, verifyCodePart, parserOptions) { // First pass: collect needed globals and declared globals for each script tags. const firstPassValues = [] for (const codePart of codeParts) { verifyCodePart(codePart, { prepare(context) { + const globalScope = context.getScope() + // See https://github.com/eslint/eslint/blob/4b267a5c8a42477bb2384f33b20083ff17ad578c/lib/rules/no-redeclare.js#L67-L78 + let scopeForDeclaredGlobals + if ( + parserOptions.ecmaFeatures && + parserOptions.ecmaFeatures.globalReturn + ) { + scopeForDeclaredGlobals = globalScope.childScopes[0] + } else { + scopeForDeclaredGlobals = globalScope + } + firstPassValues.push({ codePart, - exportedGlobals: context - .getScope() - .through.map(node => node.identifier.name), - declaredGlobals: context - .getScope() - .variables.map(variable => variable.name), + exportedGlobals: globalScope.through.map( + node => node.identifier.name + ), + declaredGlobals: scopeForDeclaredGlobals.variables.map( + variable => variable.name + ), }) }, ignoreRules: true, From 609869f7fdf2492916fa7eccf26bbd6650b90cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Sat, 2 Feb 2019 17:28:46 +0100 Subject: [PATCH 2/3] chore: update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 370fcba..a92e741 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +2019-02-02 v5.0.3 +* Fix support for `parserOptions.ecmaFeatures.globalReturn: true` while sharing scope between multiple script tags + 2019-02-02 v5.0.2 * Fix support for the --report-unused-disabled-directives option #111 From 402442a7e77c96758978ef28e8e8be0943ee368c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Zugmeyer?= Date: Sat, 2 Feb 2019 17:29:44 +0100 Subject: [PATCH 3/3] 5.0.3 --- npm-shrinkwrap.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 448e2f2..a56d5a5 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-html", - "version": "5.0.2", + "version": "5.0.3", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cec2f3a..775d343 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "eslint-plugin-html", - "version": "5.0.2", + "version": "5.0.3", "description": "A ESLint plugin to lint and fix inline scripts contained in HTML files.", "license": "ISC", "repository": {