diff --git a/lib/lbt/analyzer/FioriElementsAnalyzer.js b/lib/lbt/analyzer/FioriElementsAnalyzer.js index e4cf9ebb6..bfa8b52d5 100644 --- a/lib/lbt/analyzer/FioriElementsAnalyzer.js +++ b/lib/lbt/analyzer/FioriElementsAnalyzer.js @@ -60,8 +60,7 @@ const ModuleName = require("../utils/ModuleName"); const SapUiDefine = require("../calls/SapUiDefine"); -const esprima = require("esprima"); -const {Syntax} = esprima; +const {parseJS, Syntax} = require("../utils/parseJS"); const {getValue, isMethodCall, isString} = require("../utils/ASTUtils"); const log = require("@ui5/logger").getLogger("lbt:analyzer:FioriElementAnalyzer"); @@ -147,7 +146,7 @@ class FioriElementsAnalyzer { // console.log("analyzing template component %s", moduleName); const resource = await this._pool.findResource(moduleName); const code = await resource.buffer(); - const ast = esprima.parseScript(code.toString()); + const ast = parseJS(code); const defaultTemplateName = this._analyzeAST(moduleName, ast); const templateName = (pageConfig.component && pageConfig.component.settings && pageConfig.component.settings.templateName) || defaultTemplateName; diff --git a/lib/lbt/analyzer/JSModuleAnalyzer.js b/lib/lbt/analyzer/JSModuleAnalyzer.js index e6dc31957..defd87eb4 100644 --- a/lib/lbt/analyzer/JSModuleAnalyzer.js +++ b/lib/lbt/analyzer/JSModuleAnalyzer.js @@ -1,7 +1,6 @@ "use strict"; -const esprima = require("esprima"); -const {Syntax} = esprima; +const {Syntax} = require("../utils/parseJS"); const escope = require("escope"); const ModuleName = require("../utils/ModuleName"); const {Format: ModuleFormat} = require("../resources/ModuleInfo"); diff --git a/lib/lbt/analyzer/SmartTemplateAnalyzer.js b/lib/lbt/analyzer/SmartTemplateAnalyzer.js index 90c7d4a90..edfd64527 100644 --- a/lib/lbt/analyzer/SmartTemplateAnalyzer.js +++ b/lib/lbt/analyzer/SmartTemplateAnalyzer.js @@ -27,8 +27,7 @@ const ModuleName = require("../utils/ModuleName"); const SapUiDefine = require("../calls/SapUiDefine"); -const esprima = require("esprima"); -const {Syntax} = esprima; +const {parseJS, Syntax} = require("../utils/parseJS"); const {getValue, isMethodCall, isString} = require("../utils/ASTUtils"); const log = require("@ui5/logger").getLogger("lbt:analyzer:SmartTemplateAnalyzer"); @@ -109,7 +108,7 @@ class TemplateComponentAnalyzer { try { const resource = await this._pool.findResource(moduleName); const code = await resource.buffer(); - const ast = esprima.parseScript(code.toString()); + const ast = parseJS(code); const defaultTemplateName = this._analyzeAST(moduleName, ast); const templateName = (pageConfig.component && pageConfig.component.settings && pageConfig.component.settings.templateName) || defaultTemplateName; diff --git a/lib/lbt/analyzer/XMLCompositeAnalyzer.js b/lib/lbt/analyzer/XMLCompositeAnalyzer.js index 868da94d6..4fd79d295 100644 --- a/lib/lbt/analyzer/XMLCompositeAnalyzer.js +++ b/lib/lbt/analyzer/XMLCompositeAnalyzer.js @@ -1,7 +1,6 @@ "use strict"; -const esprima = require("esprima"); -const {Syntax} = esprima; +const {Syntax} = require("../utils/parseJS"); const SapUiDefine = require("../calls/SapUiDefine"); const {getValue, isMethodCall, isString} = require("../utils/ASTUtils"); const ModuleName = require("../utils/ModuleName"); diff --git a/lib/lbt/analyzer/analyzeLibraryJS.js b/lib/lbt/analyzer/analyzeLibraryJS.js index 8c0e2ab7d..95c761163 100644 --- a/lib/lbt/analyzer/analyzeLibraryJS.js +++ b/lib/lbt/analyzer/analyzeLibraryJS.js @@ -1,6 +1,5 @@ "use strict"; -const esprima = require("esprima"); -const {Syntax} = esprima; +const {parseJS, Syntax} = require("../utils/parseJS"); const {getPropertyKey, isMethodCall, isIdentifier, getStringArray} = require("../utils/ASTUtils"); const VisitorKeys = require("estraverse").VisitorKeys; @@ -63,7 +62,7 @@ async function analyze(resource) { } const code = await resource.getBuffer(); - visit( esprima.parseScript(code.toString()) ); + visit( parseJS(code) ); return libInfo; } diff --git a/lib/lbt/bundle/Builder.js b/lib/lbt/bundle/Builder.js index 2c79ed53b..9e090e953 100644 --- a/lib/lbt/bundle/Builder.js +++ b/lib/lbt/bundle/Builder.js @@ -4,8 +4,7 @@ const terser = require("terser"); const {pd} = require("pretty-data"); -const esprima = require("esprima"); -const {Syntax} = esprima; +const {parseJS, Syntax} = require("../utils/parseJS"); // const MOZ_SourceMap = require("source-map"); const {isMethodCall} = require("../utils/ASTUtils"); @@ -508,7 +507,7 @@ function rewriteDefine(targetBundleFormat, code, moduleName) { let ast; const codeStr = code.toString(); try { - ast = esprima.parseScript(codeStr, {range: true}); + ast = parseJS(codeStr, {range: true}); } catch (e) { log.error("error while parsing %s: %s", moduleName, e.message); return; diff --git a/lib/lbt/calls/SapUiDefine.js b/lib/lbt/calls/SapUiDefine.js index 7387a4504..f9e70e9b7 100644 --- a/lib/lbt/calls/SapUiDefine.js +++ b/lib/lbt/calls/SapUiDefine.js @@ -1,6 +1,6 @@ "use strict"; -const {Syntax} = require("esprima"); +const {Syntax} = require("../utils/parseJS"); const ModuleName = require("../utils/ModuleName"); const {isString, isBoolean} = require("../utils/ASTUtils"); diff --git a/lib/lbt/resources/ResourcePool.js b/lib/lbt/resources/ResourcePool.js index 67f4630c5..39dc95f17 100644 --- a/lib/lbt/resources/ResourcePool.js +++ b/lib/lbt/resources/ResourcePool.js @@ -4,7 +4,7 @@ const fs = require("fs"); const path = require("path"); */ -const esprima = require("esprima"); +const {parseJS} = require("../utils/parseJS"); const ComponentAnalyzer = require("../analyzer/ComponentAnalyzer"); const SmartTemplateAnalyzer = require("../analyzer/SmartTemplateAnalyzer"); const FioriElementsAnalyzer = require("../analyzer/FioriElementsAnalyzer"); @@ -67,7 +67,7 @@ async function determineDependencyInfo(resource, rawInfo, pool) { const promises = []; let ast; try { - ast = esprima.parseScript(code.toString(), {comment: true}); + ast = parseJS(code, {comment: true}); } catch (err) { log.error("failed to parse %s: %s", resource.name, err.message); } diff --git a/lib/lbt/utils/ASTUtils.js b/lib/lbt/utils/ASTUtils.js index dc8ec8dee..13d747536 100644 --- a/lib/lbt/utils/ASTUtils.js +++ b/lib/lbt/utils/ASTUtils.js @@ -1,6 +1,6 @@ "use strict"; -const {Syntax} = require("esprima"); +const {Syntax} = require("../utils/parseJS"); /** * Checks whether the given node is a string literal. diff --git a/lib/lbt/utils/parseJS.js b/lib/lbt/utils/parseJS.js new file mode 100644 index 000000000..c5772e3bf --- /dev/null +++ b/lib/lbt/utils/parseJS.js @@ -0,0 +1,28 @@ +"use strict"; + +const espree = require("espree"); +const {Syntax} = espree; + +const defaultOptions = { + comment: false, + ecmaVersion: 2020, + range: false, + sourceType: "script", +}; + +const allowedOptions = Object.keys(defaultOptions); + +function parseJS(code, options = {}) { + const firstUnsupportedOption = + Object.keys(options).find((name) => !allowedOptions.includes(name)); + if (firstUnsupportedOption != null) { + throw new TypeError(`Option ${firstUnsupportedOption} is not one of ${allowedOptions})`); + } + + return espree.parse(code, Object.assign({}, defaultOptions, options)); +} + +module.exports = { + parseJS, + Syntax +}; diff --git a/package-lock.json b/package-lock.json index 946917344..01f1b4233 100644 --- a/package-lock.json +++ b/package-lock.json @@ -385,6 +385,29 @@ "strip-json-comments": "^3.1.1" }, "dependencies": { + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + } + }, "globals": { "version": "13.9.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", @@ -674,8 +697,7 @@ "acorn-jsx": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.1.tgz", - "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==", - "dev": true + "integrity": "sha512-K0Ptm/47OKfQRpNQ2J/oIN/3QYiK6FwW+eJbILhsdxh2WTLdl+30o8aGdTbm5JbffpFFAg/g+zi1E+jvJha5ng==" }, "acorn-walk": { "version": "8.1.0", @@ -2407,6 +2429,12 @@ "@babel/highlight": "^7.10.4" } }, + "acorn": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", + "dev": true + }, "ansi-regex": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", @@ -2419,6 +2447,25 @@ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true }, + "espree": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", + "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", + "dev": true, + "requires": { + "acorn": "^7.4.0", + "acorn-jsx": "^5.3.1", + "eslint-visitor-keys": "^1.3.0" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", + "dev": true + } + } + }, "globals": { "version": "13.9.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.9.0.tgz", @@ -2516,34 +2563,32 @@ "dev": true }, "espree": { - "version": "7.3.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz", - "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==", - "dev": true, + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", + "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==", "requires": { - "acorn": "^7.4.0", - "acorn-jsx": "^5.3.1", - "eslint-visitor-keys": "^1.3.0" + "acorn": "^7.1.1", + "acorn-jsx": "^5.2.0", + "eslint-visitor-keys": "^1.1.0" }, "dependencies": { "acorn": { "version": "7.4.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz", - "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==", - "dev": true + "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==" }, "eslint-visitor-keys": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz", - "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", - "dev": true + "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==" } } }, "esprima": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==" + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true }, "esquery": { "version": "1.4.0", diff --git a/package.json b/package.json index d683bea1c..9d41868cd 100644 --- a/package.json +++ b/package.json @@ -109,7 +109,7 @@ "cheerio": "1.0.0-rc.9", "escape-unicode": "^0.2.0", "escope": "^3.6.0", - "esprima": "^4.0.1", + "espree": "^6.2.1", "estraverse": "5.1.0", "globby": "^11.0.3", "graceful-fs": "^4.2.6", diff --git a/test/lib/lbt/analyzer/FioriElementsAnalyzer.js b/test/lib/lbt/analyzer/FioriElementsAnalyzer.js index 5c810cdf8..c8fba2b36 100644 --- a/test/lib/lbt/analyzer/FioriElementsAnalyzer.js +++ b/test/lib/lbt/analyzer/FioriElementsAnalyzer.js @@ -1,7 +1,7 @@ const test = require("ava"); const FioriElementsAnalyzer = require("../../../../lib/lbt/analyzer/FioriElementsAnalyzer"); const sinon = require("sinon"); -const esprima = require("esprima"); +const parseJS = require("../../../../lib/lbt/utils/parseJS"); test("analyze: with Component.js", async (t) => { const emptyPool = {}; @@ -143,7 +143,7 @@ test.serial("_analyzeTemplateComponent: Manifest with TemplateAssembler code", a const analyzer = new FioriElementsAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns("mytpl"); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", {}, moduleInfo); @@ -177,7 +177,7 @@ test.serial("_analyzeTemplateComponent: no default template name", async (t) => const analyzer = new FioriElementsAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns(""); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", {}, moduleInfo); @@ -206,7 +206,7 @@ test.serial("_analyzeTemplateComponent: with template name from pageConfig", asy const analyzer = new FioriElementsAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns(""); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", { component: { @@ -239,7 +239,7 @@ test("_analyzeAST: get template name from ast", async (t) => { "manifest": "json" } });});`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const analyzer = new FioriElementsAnalyzer(); @@ -269,7 +269,7 @@ test("_analyzeAST: no template name from ast", async (t) => { "manifest": "json" } });});`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const analyzer = new FioriElementsAnalyzer(); @@ -297,7 +297,7 @@ test("_analyzeTemplateClassDefinition: get template name from metadata", async ( "manifest": "json" } };`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const expression = ast.body[0].declarations[0].init; const analyzer = new FioriElementsAnalyzer(); @@ -319,7 +319,7 @@ test("_analyzeTemplateClassDefinition: no string template name from metadata", a "manifest": "json" } };`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const expression = ast.body[0].declarations[0].init; const analyzer = new FioriElementsAnalyzer(); diff --git a/test/lib/lbt/analyzer/JSModuleAnalyzer.js b/test/lib/lbt/analyzer/JSModuleAnalyzer.js index 5015b5024..1a4152226 100644 --- a/test/lib/lbt/analyzer/JSModuleAnalyzer.js +++ b/test/lib/lbt/analyzer/JSModuleAnalyzer.js @@ -1,7 +1,7 @@ const test = require("ava"); const fs = require("fs"); const path = require("path"); -const esprima = require("esprima"); +const {parseJS} = require("../../../../lib/lbt/utils/parseJS"); const ModuleInfo = require("../../../../lib/lbt/resources/ModuleInfo"); const JSModuleAnalyzer = require("../../../../lib/lbt/analyzer/JSModuleAnalyzer"); @@ -51,7 +51,7 @@ function analyze(file, name) { } function analyzeString(content, name) { - const ast = esprima.parseScript(content, {comment: true}); + const ast = parseJS(content, {comment: true}); const info = new ModuleInfo(name); new JSModuleAnalyzer().analyze(ast, name, info); return info; @@ -594,7 +594,7 @@ test("Toplevel define", (t) => { }); test("Invalid ui5 bundle comment", (t) => { - const content = `/@ui5-bundles sap/ui/thirdparty/xxx.js + const content = `//@ui5-bundles sap/ui/thirdparty/xxx.js if(!('xxx'in Node.prototype)){} //@ui5-bundle-raw-includes sap/ui/thirdparty/aaa.js (function(g,f){g.AAA=f();}(this,(function(){}))); diff --git a/test/lib/lbt/analyzer/SmartTemplateAnalyzer.js b/test/lib/lbt/analyzer/SmartTemplateAnalyzer.js index 1c8195c0c..7f6dc8b1f 100644 --- a/test/lib/lbt/analyzer/SmartTemplateAnalyzer.js +++ b/test/lib/lbt/analyzer/SmartTemplateAnalyzer.js @@ -2,7 +2,7 @@ const test = require("ava"); const SmartTemplateAnalyzer = require("../../../../lib/lbt/analyzer/SmartTemplateAnalyzer"); const ModuleInfo = require("../../../../lib/lbt/resources/ModuleInfo"); const sinon = require("sinon"); -const esprima = require("esprima"); +const parseJS = require("../../../../lib/lbt/utils/parseJS"); test("analyze: with Component.js", async (t) => { @@ -210,7 +210,7 @@ test.serial("_analyzeTemplateComponent: Manifest with TemplateAssembler code", a const analyzer = new SmartTemplateAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns("mytpl"); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", {}, moduleInfo); @@ -247,7 +247,7 @@ test.serial("_analyzeTemplateComponent: no default template name", async (t) => const analyzer = new SmartTemplateAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns(""); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", {}, moduleInfo); @@ -279,7 +279,7 @@ test.serial("_analyzeTemplateComponent: with template name from pageConfig", asy const analyzer = new SmartTemplateAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns(""); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", { component: { @@ -316,7 +316,7 @@ test.serial("_analyzeTemplateComponent: dependency not found", async (t) => { const analyzer = new SmartTemplateAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns(""); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); const error = await t.throwsAsync(analyzer._analyzeTemplateComponent("pony", { component: { @@ -353,7 +353,7 @@ test.serial("_analyzeTemplateComponent: dependency not found is ignored", async const analyzer = new SmartTemplateAnalyzer(mockPool); const stubAnalyzeAST = sinon.stub(analyzer, "_analyzeAST").returns(""); - const stubParse = sinon.stub(esprima, "parse").returns(""); + const stubParse = sinon.stub(parseJS, "parseJS").returns(""); await analyzer._analyzeTemplateComponent("pony", { component: { @@ -385,7 +385,7 @@ test("_analyzeAST: get template name from ast", async (t) => { "manifest": "json" } });});`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const analyzer = new SmartTemplateAnalyzer(); @@ -416,7 +416,7 @@ test("_analyzeAST: no template name from ast", async (t) => { "manifest": "json" } });});`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const analyzer = new SmartTemplateAnalyzer(); @@ -489,7 +489,7 @@ test("_analyzeTemplateClassDefinition: get template name from metadata", async ( "manifest": "json" } };`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const expression = ast.body[0].declarations[0].init; const analyzer = new SmartTemplateAnalyzer(); @@ -511,7 +511,7 @@ test("_analyzeTemplateClassDefinition: no string template name from metadata", a "manifest": "json" } };`; - const ast = esprima.parse(code); + const ast = parseJS.parseJS(code); const expression = ast.body[0].declarations[0].init; const analyzer = new SmartTemplateAnalyzer(); diff --git a/test/lib/lbt/analyzer/XMLCompositeAnalyzer.js b/test/lib/lbt/analyzer/XMLCompositeAnalyzer.js index 59a225241..157966a89 100644 --- a/test/lib/lbt/analyzer/XMLCompositeAnalyzer.js +++ b/test/lib/lbt/analyzer/XMLCompositeAnalyzer.js @@ -1,5 +1,5 @@ const test = require("ava"); -const esprima = require("esprima"); +const {parseJS} = require("../../../../lib/lbt/utils/parseJS"); const sinon = require("sinon"); const XMLCompositeAnalyzer = require("../../../../lib/lbt/analyzer/XMLCompositeAnalyzer"); const ModuleInfo = require("../../../../lib/lbt/resources/ModuleInfo"); @@ -13,7 +13,7 @@ test("integration: XMLComposite code", async (t) => { return ButtonList; });`; - const ast = esprima.parse(code); + const ast = parseJS(code); const analyzer = new XMLCompositeAnalyzer(); const name = "composites.ButtonList"; @@ -31,7 +31,7 @@ test("analyze: not an XMLComposite module", async (t) => { return {}; });`; - const ast = esprima.parse(code); + const ast = parseJS(code); const moduleInfo = { addDependency: function() {} @@ -55,7 +55,7 @@ test("analyze: XMLComposite VariableDeclaration code", async (t) => { return ButtonList; });`; - const ast = esprima.parse(code); + const ast = parseJS(code); const moduleInfo = { addDependency: function() {} @@ -85,7 +85,7 @@ test("analyze: XMLComposite Expression code", async (t) => { jQuery.sap.test = XMLComposite.extend("composites.ButtonList", {}); });`; - const ast = esprima.parse(code); + const ast = parseJS(code); const moduleInfo = { addDependency: function() {} @@ -109,7 +109,7 @@ test("analyze: XMLComposite Expression code", async (t) => { test("_checkForXMLCClassDefinition: string argument and object expression", async (t) => { const code = `XMLComposite.extend("composites.ButtonList", {})`; - const ast = esprima.parse(code); + const ast = parseJS(code); const analyzer = new XMLCompositeAnalyzer(); const stubAnalyzeXMLCClassDefinition = sinon.stub(analyzer, "_analyzeXMLCClassDefinition").returns("cow"); @@ -123,7 +123,7 @@ test("_checkForXMLCClassDefinition: string argument and object expression", asyn test("_analyzeXMLCClassDefinition: name retrieval", async (t) => { const code = `test({fragment: "cat"})`; - const ast = esprima.parse(code); + const ast = parseJS(code); const analyzer = new XMLCompositeAnalyzer(); const result = analyzer._analyzeXMLCClassDefinition(ast.body[0].expression.arguments[0]); diff --git a/test/lib/lbt/calls/SapUiDefine.js b/test/lib/lbt/calls/SapUiDefine.js index 7a9a9a6e7..ed700de4a 100644 --- a/test/lib/lbt/calls/SapUiDefine.js +++ b/test/lib/lbt/calls/SapUiDefine.js @@ -1,11 +1,10 @@ const test = require("ava"); -const esprima = require("esprima"); -const Syntax = esprima.Syntax; +const {parseJS, Syntax} = require("../../../../lib/lbt/utils/parseJS"); const SapUiDefineCall = require("../../../../lib/lbt/calls/SapUiDefine"); function parse(code) { - const ast = esprima.parseScript(code); + const ast = parseJS(code); return ast.body[0].expression; } diff --git a/test/lib/lbt/utils/ASTUtils.js b/test/lib/lbt/utils/ASTUtils.js index 9eab3837c..6f9d8f8ca 100644 --- a/test/lib/lbt/utils/ASTUtils.js +++ b/test/lib/lbt/utils/ASTUtils.js @@ -1,12 +1,20 @@ const test = require("ava"); -const esprima = require("esprima"); +const {parseJS} = require("../../../../lib/lbt/utils/parseJS"); const ASTUtils = require("../../../../lib/lbt/utils/ASTUtils"); +/* + * remove start/end properties before comparing AST nodes + */ +const cleanse = (node) => { + delete node.start; + delete node.end; + return node; +}; test("isString", (t) => { t.false(ASTUtils.isString(null)); - const literal = esprima.parse("'testValue47'").body[0].expression; + const literal = parseJS("'testValue47'").body[0].expression; t.true(ASTUtils.isString(literal), "is a literal"); t.true(ASTUtils.isString(literal, "testValue47"), "is a literal and its value matches"); @@ -17,10 +25,10 @@ test("isString", (t) => { test("isBoolean", (t) => { t.false(ASTUtils.isString(null)); - const trueLiteral = esprima.parse("true").body[0].expression; - const falseLiteral = esprima.parse("false").body[0].expression; - const stringLiteral = esprima.parse("'some string'").body[0].expression; - const call = esprima.parse("setTimeout()").body[0]; + const trueLiteral = parseJS("true").body[0].expression; + const falseLiteral = parseJS("false").body[0].expression; + const stringLiteral = parseJS("'some string'").body[0].expression; + const call = parseJS("setTimeout()").body[0]; t.true(ASTUtils.isBoolean(trueLiteral), "is a boolean literal"); t.true(ASTUtils.isBoolean(falseLiteral), "is a boolean literal"); @@ -33,12 +41,12 @@ test("isBoolean", (t) => { }); test("isIdentifier", (t) => { - const literal = esprima.parse("'testValue47'").body[0].expression; + const literal = parseJS("'testValue47'").body[0].expression; t.false(ASTUtils.isIdentifier(literal), "A literal is not an identifier"); - const identifier = esprima.parse("testValue47").body[0].expression; + const identifier = parseJS("testValue47").body[0].expression; t.true(ASTUtils.isIdentifier(identifier, ["*"], "asterisk matches any string")); t.true(ASTUtils.isIdentifier(identifier, ["testValue47"], "value matches")); @@ -52,14 +60,14 @@ test("isIdentifier", (t) => { test("isNamedObject", (t) => { - const identifier = esprima.parse("testValue47").body[0].expression; + const identifier = parseJS("testValue47").body[0].expression; t.true(ASTUtils.isNamedObject(identifier, ["testValue47"], 1), "object with depths 1 is named testValue47"); t.false(ASTUtils.isNamedObject(identifier, ["testValue47"], 2), "object with depths 2 is not named testValue47"); t.false(ASTUtils.isNamedObject(identifier, ["testValue47"], 0), "object with depths 0 is not named testValue47"); - const member = esprima.parse("x.testValue47").body[0].expression; + const member = parseJS("x.testValue47").body[0].expression; t.true(ASTUtils.isNamedObject(member, ["x", "testValue47"], 2), "object with depths 1 is named x and with depths 2 testValue47"); t.false(ASTUtils.isNamedObject(member, ["x", "testValue47"], 1), "object with depths 1 is not named testValue47"); @@ -67,25 +75,25 @@ test("isNamedObject", (t) => { }); test("isMethodCall", (t) => { - const identifier = esprima.parse("testValue47").body[0].expression; + const identifier = parseJS("testValue47").body[0].expression; t.false(ASTUtils.isMethodCall(identifier), "identifier testValue47 is not a method call"); - const methodCall = esprima.parse("testValue47()").body[0].expression; + const methodCall = parseJS("testValue47()").body[0].expression; t.true(ASTUtils.isMethodCall(methodCall, ["testValue47"]), "testValue47 is a method call"); t.false(ASTUtils.isMethodCall(methodCall, ["myOtherValue47"]), "myOtherValue47 is not a method call"); t.false(ASTUtils.isMethodCall(methodCall, ["*"]), "* is not a method call"); }); test("getStringArray", (t) => { - const array = esprima.parse("['a', 5]").body[0].expression; + const array = parseJS("['a', 5]").body[0].expression; const error = t.throws(() => { ASTUtils.getStringArray(array); }, {instanceOf: TypeError}, "array contains a number"); t.deepEqual(error.message, "array element is not a string literal:Literal"); - const stringArray = esprima.parse("['a', 'x']").body[0].expression; + const stringArray = parseJS("['a', 'x']").body[0].expression; t.deepEqual(ASTUtils.getStringArray(stringArray), ["a", "x"], "array contains only strings"); }); @@ -95,39 +103,39 @@ test("getLocation", (t) => { test("getPropertyKey", (t) => { // quoted key - const quotedProperties = esprima.parse("var myVar = {'a':'x'}").body[0].declarations[0].init.properties; + const quotedProperties = parseJS("var myVar = {'a':'x'}").body[0].declarations[0].init.properties; t.deepEqual(ASTUtils.getPropertyKey(quotedProperties[0]), "a", "sole property key is 'a'"); // unquoted key - const unQuotedProperties = esprima.parse("var myVar = {a:'x'}").body[0].declarations[0].init.properties; + const unQuotedProperties = parseJS("var myVar = {a:'x'}").body[0].declarations[0].init.properties; t.deepEqual(ASTUtils.getPropertyKey(unQuotedProperties[0]), "a", "sole property key is 'a'"); // quoted key with dash - const dashedProperties = esprima.parse("var myVar = {'my-var': 47}").body[0].declarations[0].init.properties; + const dashedProperties = parseJS("var myVar = {'my-var': 47}").body[0].declarations[0].init.properties; t.deepEqual(ASTUtils.getPropertyKey(dashedProperties[0]), "my-var", "sole property key is 'my-var'"); }); test("findOwnProperty", (t) => { - const literal = esprima.parse("'x'").body[0].expression; + const literal = cleanse(parseJS("'x'").body[0].expression); // quoted - const object = esprima.parse("var myVar = {'a':'x'}").body[0].declarations[0].init; - t.deepEqual(ASTUtils.findOwnProperty(object, "a"), literal, "object property a's value is literal 'x'"); + const object = parseJS("var myVar = {'a':'x'}").body[0].declarations[0].init; + t.deepEqual(cleanse(ASTUtils.findOwnProperty(object, "a")), literal, "object property a's value is literal 'x'"); // unquoted - const object2 = esprima.parse("var myVar = {a:'x'}").body[0].declarations[0].init; - t.deepEqual(ASTUtils.findOwnProperty(object2, "a"), literal, "object property a's value is literal 'x'"); + const object2 = parseJS("var myVar = {a:'x'}").body[0].declarations[0].init; + t.deepEqual(cleanse(ASTUtils.findOwnProperty(object2, "a")), literal, "object property a's value is literal 'x'"); }); test("getValue", (t) => { t.falsy(ASTUtils.getValue(null, [])); t.falsy(ASTUtils.getValue(null, ["a"])); - const literal = esprima.parse("'x'").body[0].expression; - const object = esprima.parse("var myVar = {'a':'x'}").body[0].declarations[0].init; + const literal = cleanse(parseJS("'x'").body[0].expression); - t.deepEqual(ASTUtils.getValue(object, ["a"]), literal, "object property a's value is literal 'x'"); + const object = parseJS("var myVar = {'a':'x'}").body[0].declarations[0].init; + t.deepEqual(cleanse(ASTUtils.getValue(object, ["a"])), literal, "object property a's value is literal 'x'"); - const object2 = esprima.parse("var myVar = {a:'x'}").body[0].declarations[0].init; - t.deepEqual(ASTUtils.getValue(object2, ["a"]), literal, "object property a's value is literal 'x'"); + const object2 = parseJS("var myVar = {a:'x'}").body[0].declarations[0].init; + t.deepEqual(cleanse(ASTUtils.getValue(object2, ["a"])), literal, "object property a's value is literal 'x'"); });