diff --git a/package-lock.json b/package-lock.json index c1cf5c56c..df3c73470 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,11 +17,11 @@ "@babel/code-frame": "^7.26.2", "@types/jest": "^29.5.14", "@types/semver": "^7.5.8", - "@typescript-eslint/eslint-plugin": "^8.26.1", - "@typescript-eslint/parser": "^8.26.1", + "@typescript-eslint/eslint-plugin": "^8.28.0", + "@typescript-eslint/parser": "^8.28.0", "c8": "^10.1.3", "cross-env": "^7.0.3", - "eslint": "^9.22.0", + "eslint": "^9.23.0", "eslint-config-prettier": "10.1.1", "esm-utils": "^4.3.0", "jest": "^29.7.0", @@ -660,9 +660,9 @@ } }, "node_modules/@eslint/config-helpers": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.1.0.tgz", - "integrity": "sha512-kLrdPDJE1ckPo94kmPPf9Hfd0DU0Jw6oKYrhe+pwSC0iTUInmTa+w6fw8sGgcfkFJGNdWOUeOaDM4quW4a7OkA==", + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.2.0.tgz", + "integrity": "sha512-yJLLmLexii32mGrhW29qvU3QBVTu0GUmEf/J4XsBtVhp4JkIUFN/BjWqTF63yRvGApIDpZm5fa97LtYtINmfeQ==", "dev": true, "license": "Apache-2.0", "engines": { @@ -683,9 +683,9 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.0.tgz", - "integrity": "sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "license": "MIT", "dependencies": { @@ -707,9 +707,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.22.0.tgz", - "integrity": "sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==", + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.23.0.tgz", + "integrity": "sha512-35MJ8vCPU0ZMxo7zfev2pypqTwWTofFZO6m4KAtdoFhRpLJUpHTZZ+KB3C7Hb1d7bULYwO4lJXGCi5Se+8OMbw==", "dev": true, "license": "MIT", "engines": { @@ -1905,17 +1905,17 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.26.1.tgz", - "integrity": "sha512-2X3mwqsj9Bd3Ciz508ZUtoQQYpOhU/kWoUqIf49H8Z0+Vbh6UF/y0OEYp0Q0axOGzaBGs7QxRwq0knSQ8khQNA==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.28.0.tgz", + "integrity": "sha512-lvFK3TCGAHsItNdWZ/1FkvpzCxTHUVuFrdnOGLMa0GGCFIbCgQWVk3CzCGdA7kM3qGVc+dfW9tr0Z/sHnGDFyg==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "8.26.1", - "@typescript-eslint/type-utils": "8.26.1", - "@typescript-eslint/utils": "8.26.1", - "@typescript-eslint/visitor-keys": "8.26.1", + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/type-utils": "8.28.0", + "@typescript-eslint/utils": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -1935,16 +1935,16 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.26.1.tgz", - "integrity": "sha512-w6HZUV4NWxqd8BdeFf81t07d7/YV9s7TCWrQQbG5uhuvGUAW+fq1usZ1Hmz9UPNLniFnD8GLSsDpjP0hm1S4lQ==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.28.0.tgz", + "integrity": "sha512-LPcw1yHD3ToaDEoljFEfQ9j2xShY367h7FZ1sq5NJT9I3yj4LHer1Xd1yRSOdYy9BpsrxU7R+eoDokChYM53lQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "8.26.1", - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/typescript-estree": "8.26.1", - "@typescript-eslint/visitor-keys": "8.26.1", + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/typescript-estree": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", "debug": "^4.3.4" }, "engines": { @@ -1960,14 +1960,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.26.1.tgz", - "integrity": "sha512-6EIvbE5cNER8sqBu6V7+KeMZIC1664d2Yjt+B9EWUXrsyWpxx4lEZrmvxgSKRC6gX+efDL/UY9OpPZ267io3mg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.28.0.tgz", + "integrity": "sha512-u2oITX3BJwzWCapoZ/pXw6BCOl8rJP4Ij/3wPoGvY8XwvXflOzd1kLrDUUUAIEdJSFh+ASwdTHqtan9xSg8buw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/visitor-keys": "8.26.1" + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -1978,14 +1978,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.26.1.tgz", - "integrity": "sha512-Kcj/TagJLwoY/5w9JGEFV0dclQdyqw9+VMndxOJKtoFSjfZhLXhYjzsQEeyza03rwHx2vFEGvrJWJBXKleRvZg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.28.0.tgz", + "integrity": "sha512-oRoXu2v0Rsy/VoOGhtWrOKDiIehvI+YNrDk5Oqj40Mwm0Yt01FC/Q7nFqg088d3yAsR1ZcZFVfPCTTFCe/KPwg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "8.26.1", - "@typescript-eslint/utils": "8.26.1", + "@typescript-eslint/typescript-estree": "8.28.0", + "@typescript-eslint/utils": "8.28.0", "debug": "^4.3.4", "ts-api-utils": "^2.0.1" }, @@ -2002,9 +2002,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.26.1.tgz", - "integrity": "sha512-n4THUQW27VmQMx+3P+B0Yptl7ydfceUj4ON/AQILAASwgYdZ/2dhfymRMh5egRUrvK5lSmaOm77Ry+lmXPOgBQ==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.28.0.tgz", + "integrity": "sha512-bn4WS1bkKEjx7HqiwG2JNB3YJdC1q6Ue7GyGlwPHyt0TnVq6TtD/hiOdTZt71sq0s7UzqBFXD8t8o2e63tXgwA==", "dev": true, "license": "MIT", "engines": { @@ -2016,14 +2016,14 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.26.1.tgz", - "integrity": "sha512-yUwPpUHDgdrv1QJ7YQal3cMVBGWfnuCdKbXw1yyjArax3353rEJP1ZA+4F8nOlQ3RfS2hUN/wze3nlY+ZOhvoA==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.28.0.tgz", + "integrity": "sha512-H74nHEeBGeklctAVUvmDkxB1mk+PAZ9FiOMPFncdqeRBXxk1lWSYraHw8V12b7aa6Sg9HOBNbGdSHobBPuQSuA==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/visitor-keys": "8.26.1", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/visitor-keys": "8.28.0", "debug": "^4.3.4", "fast-glob": "^3.3.2", "is-glob": "^4.0.3", @@ -2069,16 +2069,16 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.26.1.tgz", - "integrity": "sha512-V4Urxa/XtSUroUrnI7q6yUTD3hDtfJ2jzVfeT3VK0ciizfK2q/zGC0iDh1lFMUZR8cImRrep6/q0xd/1ZGPQpg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.28.0.tgz", + "integrity": "sha512-OELa9hbTYciYITqgurT1u/SzpQVtDLmQMFzy/N8pQE+tefOyCWT79jHsav294aTqV1q1u+VzqDGbuujvRYaeSQ==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "8.26.1", - "@typescript-eslint/types": "8.26.1", - "@typescript-eslint/typescript-estree": "8.26.1" + "@typescript-eslint/scope-manager": "8.28.0", + "@typescript-eslint/types": "8.28.0", + "@typescript-eslint/typescript-estree": "8.28.0" }, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2093,13 +2093,13 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.26.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.26.1.tgz", - "integrity": "sha512-AjOC3zfnxd6S4Eiy3jwktJPclqhFHNyd8L6Gycf9WUPoKZpgM5PjkxY1X7uSy61xVpiJDhhk7XT2NVsN3ALTWg==", + "version": "8.28.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.28.0.tgz", + "integrity": "sha512-hbn8SZ8w4u2pRwgQ1GlUrPKE+t2XvcCW5tTRF7j6SMYIuYG37XuzIW44JCZPa36evi0Oy2SnM664BlIaAuQcvg==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "8.26.1", + "@typescript-eslint/types": "8.28.0", "eslint-visitor-keys": "^4.2.0" }, "engines": { @@ -3403,19 +3403,19 @@ } }, "node_modules/eslint": { - "version": "9.22.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.22.0.tgz", - "integrity": "sha512-9V/QURhsRN40xuHXWjV64yvrzMjcz7ZyNoF2jJFmy9j/SLk0u1OLSZgXi28MrXjymnjEGSR80WCdab3RGMDveQ==", + "version": "9.23.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.23.0.tgz", + "integrity": "sha512-jV7AbNoFPAY1EkFYpLq5bslU9NLNO8xnEeQXwErNibVryjk67wHVmddTBilc5srIttJDBrB0eMHKZBFbSIABCw==", "dev": true, "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", "@eslint/config-array": "^0.19.2", - "@eslint/config-helpers": "^0.1.0", + "@eslint/config-helpers": "^0.2.0", "@eslint/core": "^0.12.0", - "@eslint/eslintrc": "^3.3.0", - "@eslint/js": "9.22.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.23.0", "@eslint/plugin-kit": "^0.2.7", "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", diff --git a/package.json b/package.json index 30fa31669..f995dafa1 100644 --- a/package.json +++ b/package.json @@ -86,11 +86,11 @@ "@babel/code-frame": "^7.26.2", "@types/jest": "^29.5.14", "@types/semver": "^7.5.8", - "@typescript-eslint/eslint-plugin": "^8.26.1", - "@typescript-eslint/parser": "^8.26.1", + "@typescript-eslint/eslint-plugin": "^8.28.0", + "@typescript-eslint/parser": "^8.28.0", "c8": "^10.1.3", "cross-env": "^7.0.3", - "eslint": "^9.22.0", + "eslint": "^9.23.0", "eslint-config-prettier": "10.1.1", "esm-utils": "^4.3.0", "jest": "^29.7.0", diff --git a/test.config.js b/test.config.js index 232223744..0e367e7c2 100644 --- a/test.config.js +++ b/test.config.js @@ -4,7 +4,10 @@ import createEsmUtils from 'esm-utils'; const { __dirname } = createEsmUtils(import.meta); export default { - entry: './tests/integration/test-app.js', + entry: { + test: './tests/integration/test-app.js', + 'create-parser': './src/slang-utils/create-parser.js' + }, mode: 'production', bail: true, @@ -13,14 +16,25 @@ export default { externals: { 'node:fs/promises': 'import node:fs/promises' }, - experiments: { - asyncWebAssembly: true, - topLevelAwait: true, - outputModule: true + resolve: { + extensions: ['.ts', '.js'], + extensionAlias: { '.js': ['.js', '.ts'] } + }, + + module: { + rules: [ + { + test: /\.ts$/, + use: 'ts-loader', + exclude: /node_modules/ + } + ] }, + experiments: { outputModule: true }, + output: { - filename: 'test.js', + filename: '[name].js', path: path.resolve(__dirname, 'dist'), library: { type: 'module' } }, diff --git a/tests/config/get-create-parser.js b/tests/config/get-create-parser.js new file mode 100644 index 000000000..5859a59db --- /dev/null +++ b/tests/config/get-create-parser.js @@ -0,0 +1,16 @@ +function getCreateParserInternal() { + const entry = process.env.TEST_STANDALONE + ? "../../dist/create-parser.js" + : "../../src/slang-utils/create-parser.js"; + + return import(entry).then((module) => module.createParser); +} + +let promise; +function getCreateParser() { + promise = promise ?? getCreateParserInternal(); + + return promise; +} + +export default getCreateParser; diff --git a/tests/config/run-format-test.js b/tests/config/run-format-test.js index 4720028e8..d47b9bb71 100644 --- a/tests/config/run-format-test.js +++ b/tests/config/run-format-test.js @@ -1,10 +1,9 @@ import fs from "node:fs"; import path from "node:path"; import url from "node:url"; - import createEsmUtils from "esm-utils"; - import getPrettier from "./get-prettier.js"; +import getCreateParser from "./get-create-parser.js"; import getPlugins from "./get-plugins.js"; import compileContract from "./utils/compile-contract.js"; import consistentEndOfLine from "./utils/consistent-end-of-line.js"; @@ -65,6 +64,22 @@ const testsWithAstChanges = new Map( }), ); +const antlrMismatchTests = new Map( + [ + // Better placement of comments in Slang. + "BasicIterator/BasicIterator.sol", + "Comments/Comments.sol", + "IndexOf/IndexOf.sol", + // Syntax for `pragma solidity 0.5.0 - 0.6.0;` not supported by ANTLR + "Pragma/Pragma.sol", + ].map((fixture) => { + const [file, compareBytecode = () => true] = Array.isArray(fixture) + ? fixture + : [fixture]; + return [path.join(__dirname, "../format/", file), compareBytecode]; + }), +); + const isUnstable = (filename, options) => { const testFunction = unstableTests.get(filename); @@ -85,6 +100,16 @@ const isAstUnstable = (filename, options) => { return testFunction(options); }; +const isAntlrMismatch = (filename, options) => { + const testFunction = antlrMismatchTests.get(filename); + + if (!testFunction) { + return false; + } + + return testFunction(options); +}; + const shouldCompareBytecode = (filename, options) => { const testFunction = testsWithAstChanges.get(filename); @@ -119,6 +144,12 @@ function runFormatTest(fixtures, parsers, options) { let { importMeta, snippets = [] } = fixtures.importMeta ? fixtures : { importMeta: fixtures }; + + const filename = path.basename(new URL(importMeta.url).pathname); + if (filename !== "format.test.js") { + throw new Error(`Format test should run in file named 'format.test.js'.`); + } + const dirname = path.dirname(url.fileURLToPath(importMeta.url)); // `IS_PARSER_INFERENCE_TESTS` mean to test `inferParser` on `standalone` @@ -290,6 +321,26 @@ async function runTest({ return; } + if ( + formatOptions.parser === "slang-solidity" && + !isAntlrMismatch(filename, formatOptions) + ) { + // Compare with ANTLR's format + const prettier = await getPrettier(); + const createParser = await getCreateParser(); + const { formatted: antlrOutput } = await prettier.formatWithCursor(code, { + ...formatOptions, + // Since Slang forces us to decide on a compiler version, we need to do the + // same for ANTLR unless it was already given as an option. + compiler: + formatOptions.compiler || + createParser(code, formatOptions)[0].languageVersion, + parser: "solidity-parse", + plugins: await getPlugins(), + }); + expect(antlrOutput).toEqual(formatResult.output); + } + const isUnstableTest = isUnstable(filename, formatOptions); if ( (formatResult.changed || isUnstableTest) && diff --git a/tests/config/utils/create-snapshot.js b/tests/config/utils/create-snapshot.js index 1a898837f..7b0a79ef0 100644 --- a/tests/config/utils/create-snapshot.js +++ b/tests/config/utils/create-snapshot.js @@ -1,5 +1,4 @@ import { wrap as raw } from "jest-snapshot-serializer-raw"; - import visualizeEndOfLine from "./visualize-end-of-line.js"; import visualizeRange from "./visualize-range.js"; diff --git a/webpack.config.js b/webpack.config.js index f2ab486ce..523278d43 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,12 +4,10 @@ import webpack from 'webpack'; const { __dirname } = createEsmUtils(import.meta); -const globalObject = ` - typeof globalThis !== 'undefined' ? globalThis +const globalObject = `typeof globalThis !== 'undefined' ? globalThis : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self - : this || {} -`; + : this || {}`; // This is the production and development configuration. // It is focused on developer experience, fast rebuilds, and a minimal bundle. @@ -29,10 +27,8 @@ export default (webpackEnv) => { // TODO: investigate a cleaner way to populate the global variable // prettierPlugins in a browser. new webpack.BannerPlugin({ - banner: ` -var root = ${globalObject}; -root["prettierPlugins"] = root["prettierPlugins"] || {}, root["prettierPlugins"]["solidity"] = __webpack_exports__default; -`, + banner: `var root = ${globalObject}; +root["prettierPlugins"] = root["prettierPlugins"] || {}, root["prettierPlugins"]["solidity"] = __webpack_exports__default;`, footer: true, raw: true }) @@ -46,12 +42,6 @@ root["prettierPlugins"] = root["prettierPlugins"] || {}, root["prettierPlugins"] extensionAlias: { '.js': ['.js', '.ts'] } }, - experiments: { - asyncWebAssembly: true, - topLevelAwait: true, - outputModule: true - }, - module: { rules: [ { @@ -62,6 +52,8 @@ root["prettierPlugins"] = root["prettierPlugins"] || {}, root["prettierPlugins"] ] }, + experiments: { outputModule: true }, + optimization: { minimize: isEnvProduction }, target: ['browserslist'], output: {