diff --git a/package-lock.json b/package-lock.json index e7eac5b177..6b899bfac7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "packages/ts/*" ], "devDependencies": { + "@rollup/plugin-commonjs": "^23.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "@web/dev-server-esbuild": "^0.2.14", "@web/dev-server-import-maps": "^0.0.6", @@ -2815,6 +2816,90 @@ "node": ">=6" } }, + "node_modules/@rollup/plugin-commonjs": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", + "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^4.2.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.26.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "node_modules/@rollup/plugin-commonjs/node_modules/glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@rollup/plugin-commonjs/node_modules/minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@rollup/plugin-node-resolve": { "version": "13.3.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz", @@ -5026,6 +5111,12 @@ "node": "^12.20.0 || >=14" } }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, "node_modules/compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -9902,6 +9993,15 @@ "node": ">=0.10.0" } }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "dependencies": { + "@types/estree": "*" + } + }, "node_modules/is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -11236,6 +11336,18 @@ "node": ">=10" } }, + "node_modules/magic-string": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -14494,6 +14606,12 @@ "node": ">= 8" } }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, "node_modules/spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", @@ -18898,6 +19016,69 @@ "lit-html": "^1.0.0" } }, + "@rollup/plugin-commonjs": { + "version": "23.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-23.0.0.tgz", + "integrity": "sha512-JbrTRyDNtLQj/rhl7RFUuYXwQ2fac+33oLDAu2k++WD95zweyo28UAomLVA0JMGx4vmCa7Nw4T6k/1F6lelExg==", + "dev": true, + "requires": { + "@rollup/pluginutils": "^4.2.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.26.4" + }, + "dependencies": { + "@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dev": true, + "requires": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + } + }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true + }, + "glob": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.0.3.tgz", + "integrity": "sha512-ull455NHSHI/Y1FqGaaYFaLGkNMMJbavMrEGFXG/PGrg6y7sutWHUHrz6gy6WEBH6akM1M414dWKCNs+IhKdiQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", + "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "@rollup/plugin-node-resolve": { "version": "13.3.0", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.3.0.tgz", @@ -20641,6 +20822,12 @@ "integrity": "sha512-5EEkTNyHNGFPD2H+c/dXXfQZYa/scCKasxWcXJaWnNJ99pnQN9Vnmqow+p+PlFPE63Q6mThaZws1T+HxfpgtPw==", "dev": true }, + "commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "dev": true + }, "compare-func": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", @@ -24211,6 +24398,15 @@ "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true }, + "is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dev": true, + "requires": { + "@types/estree": "*" + } + }, "is-regex": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", @@ -25263,6 +25459,15 @@ "yallist": "^4.0.0" } }, + "magic-string": { + "version": "0.26.7", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.26.7.tgz", + "integrity": "sha512-hX9XH3ziStPoPhJxLq1syWuZMxbDvGNbVchfrdCtanC7D13888bMFow61x8axrx+GfHLtVeAx2kxL7tTGRl+Ow==", + "dev": true, + "requires": { + "sourcemap-codec": "^1.4.8" + } + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -27735,6 +27940,12 @@ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true }, + "sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "dev": true + }, "spawn-command": { "version": "0.0.2-1", "resolved": "https://registry.npmjs.org/spawn-command/-/spawn-command-0.0.2-1.tgz", diff --git a/package.json b/package.json index d36efcd6b1..0c8ea08a23 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "author": "Vaadin Ltd", "license": "Apache-2.0", "devDependencies": { + "@rollup/plugin-commonjs": "^23.0.0", "@rollup/plugin-node-resolve": "^13.0.4", "@web/dev-server-esbuild": "^0.2.14", "@web/dev-server-import-maps": "^0.0.6", diff --git a/wdsCommonjsFixes.js b/wdsCommonjsFixes.js new file mode 100644 index 0000000000..929588df2d --- /dev/null +++ b/wdsCommonjsFixes.js @@ -0,0 +1,109 @@ +// From https://github.com/modernweb-dev/web/issues/1700 -> https://gist.github.com/lucaelin/ffa48cba2253e9ad662b71e38444a135 +import { fromRollup } from '@web/dev-server-rollup'; + + +// patch the modules load hook to clear the plugins resolveExclusions whenever a new build starts +function fixLoadSkipSelf(module) { + const originalLoad = module.load; + module.load = function(...args) { + module.resolveExclusions = new Set(); + return originalLoad.call(this, ...args); + } +} + +// patch the modules resolveId hook to skip files that are in the modules exclusion set +function fixResolveIdSkipSelf(module) { + const originalResolveId = module.resolveId; + module.resolveId = function (...args) { + // skip running resolveId, if this file is already in the exclusion set + if (module.resolveExclusions.has(args[0])) { + return undefined; + } + + // fixing the resolve from the plugins this context needs to be done every time resolveId is called, because the context is recreated every time + fixResolveSkipSelf(this, module) + + const resolveReturn = originalResolveId.call(this, ...args); + return resolveReturn; + }; + +} + +// patch the adapters resolve function to add the file to the modules exclusion list if skipSelf is set +function fixResolveSkipSelf(pluginContext, module) { + // skip res + + const originalResolve = pluginContext.resolve; + pluginContext.resolve = function(...args) { + // add the file to the modules set of excluded files + if (args[2].skipSelf) { + //console.log('saving skipSelf for', args[0]); + module.resolveExclusions.add(args[0]); + } + return originalResolve.call(this, ...args); + }; + return false; +} + +// patch the modules options hook to extract injected plugins, then patch the module to move the resolveId hook back into it +function fixOptionsHookPluginInjection(module) { + // we wrap the modules options call into our own function to process its return value and find the injected plugin + const optionsHook = module.options; + module.options = function(...args) { + const optionsReturn = optionsHook.call(this, ...args); + + // we find the injected plugin + const injectedPlugins = optionsReturn.plugins; + if (injectedPlugins.length > 1) throw new Error('Multiple injected plugins detected. This wont work!') + const [injectedResolvePlugin] = injectedPlugins; + //console.log('injected plugins', injectedPlugins); + + // now we move the injected plugins resolveId hook back into the original module + if (module.resolveId) throw new Error('Existing resolveId detected. This wont work!'); + module.resolveId = function (...args) { + const resolveReturn = injectedResolvePlugin.resolveId.call(this, ...args); + return resolveReturn; + }; + + // we return what was originally returned by the options call to allow a fixed version of wds to process it + return optionsReturn; + } +} + +// patch the plugin to deal with issues from the adapter +function preparePluginForAdapter(moduleFn) { + return function(...args) { + // instantiate the module + const module = moduleFn(...args); + //console.log('module', module); + + // fix plugin injection + fixOptionsHookPluginInjection(module); + + // wait for buildStart because plugin injection above might take some time (options hook is called prior to buildStart) + const originalBuildStart = module.buildStart; + module.buildStart = function(...args) { + fixLoadSkipSelf(module); + fixResolveIdSkipSelf(module); + return originalBuildStart.call(this, ...args); + } + + return module; + } +} + +export function fromRollupWithFix(rollupPlugin) { + return fromRollup(preparePluginForAdapter(rollupPlugin)); +} + +export function fixExportNamedExports() { + return { + name: 'fix-commonjs-module', + transform(context) { + // this fixes the missing export named exports + if (context.url.endsWith(encodeURIComponent('?commonjs-module'))) { + return `var exports = {}; var __module = {exports}; export {__module, exports}`; + } + }, + } +} \ No newline at end of file diff --git a/web-test-runner.config.js b/web-test-runner.config.js index 85e1ae0c77..aa06cd7a06 100644 --- a/web-test-runner.config.js +++ b/web-test-runner.config.js @@ -4,6 +4,11 @@ import { readdir } from 'fs/promises'; import { URL } from 'url'; import { importMapsPlugin } from '@web/dev-server-import-maps'; import { puppeteerLauncher } from '@web/test-runner-puppeteer'; +import { fromRollup } from '@web/dev-server-rollup'; +import rollupCommonjs from '@rollup/plugin-commonjs'; +import {fromRollupWithFix, fixExportNamedExports} from './wdsCommonjsFixes.js'; + +const commonjs = fromRollupWithFix(rollupCommonjs); // One of the packages in the `packages` dir const cwd = process.cwd(); @@ -44,6 +49,8 @@ export default { }, }, }), + commonjs(), + fixExportNamedExports(), ], browsers: [ puppeteerLauncher({