From e88edfd3b0a50ae24e34c3060c23323a6a947dd4 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 22 Jan 2022 07:21:37 +0100 Subject: [PATCH] Add hasDefaultExport to ModuleInfo (#4356) * Add hasDefaultExport to ModuleInfo * Improve example * Make export information available after loading, detect reexports * Manually fix vulnerability --- docs/05-plugin-development.md | 56 +++++++++++++------ package-lock.json | 39 +++++++------ package.json | 6 +- src/ExternalModule.ts | 1 + src/Module.ts | 7 +++ src/rollup/types.d.ts | 1 + .../_config.js | 2 + .../implicitly-dependent-entry/_config.js | 2 + .../multiple-dependencies/_config.js | 3 + .../single-dependency/_config.js | 2 + .../deprecated/manual-chunks-info/_config.js | 4 ++ .../samples/has-default-export/_config.js | 45 +++++++++++++++ .../samples/has-default-export/direct.js | 1 + .../samples/has-default-export/indirect.js | 2 + .../samples/has-default-export/main.js | 9 +++ .../samples/has-default-export/other.js | 2 + .../samples/has-default-export/reexport1.js | 1 + .../samples/has-default-export/reexport2.js | 1 + .../samples/manual-chunks-info/_config.js | 4 ++ .../samples/module-parsed-hook/_config.js | 2 + .../plugin-module-information/_config.js | 5 ++ .../samples/preload-module/_config.js | 2 + 22 files changed, 158 insertions(+), 39 deletions(-) create mode 100644 test/function/samples/has-default-export/_config.js create mode 100644 test/function/samples/has-default-export/direct.js create mode 100644 test/function/samples/has-default-export/indirect.js create mode 100644 test/function/samples/has-default-export/main.js create mode 100644 test/function/samples/has-default-export/other.js create mode 100644 test/function/samples/has-default-export/reexport1.js create mode 100644 test/function/samples/has-default-export/reexport2.js diff --git a/docs/05-plugin-development.md b/docs/05-plugin-development.md index 068abb62045..4b6615e0349 100644 --- a/docs/05-plugin-development.md +++ b/docs/05-plugin-development.md @@ -164,27 +164,42 @@ The `importer` is the fully resolved id of the importing module. When resolving For those cases, the `isEntry` option will tell you if we are resolving a user defined entry point, an emitted chunk, or if the `isEntry` parameter was provided for the [`this.resolve`](guide/en/#thisresolve) context function. -You can use this for instance as a mechanism to define custom proxy modules for entry points. The following plugin will only expose the default export from entry points while still keeping named exports available for internal usage: +You can use this for instance as a mechanism to define custom proxy modules for entry points. The following plugin will proxy all entry points to inject a polyfill import. ```js -function onlyDefaultForEntriesPlugin() { +function injectPolyfillPlugin() { return { - name: 'only-default-for-entries', + name: 'inject-polyfill', async resolveId(source, importer, options) { if (options.isEntry) { // We need to skip this plugin to avoid an infinite loop const resolution = await this.resolve(source, importer, { skipSelf: true, ...options }); - // If it cannot be resolved, return `null` so that Rollup displays an error - if (!resolution) return null; + // If it cannot be resolved or is external, just return it so that + // Rollup can display an error + if (!resolution || resolution.external) return resolution; + // In the load hook of the proxy, we want to use this.load to find out + // if the entry has a default export. In the load hook, however, we no + // longer have the full "resolution" object that may contain meta-data + // from other plugins that is only added on first load. Therefore we + // trigger loading here without waiting for it. + this.load(resolution); return `${resolution.id}?entry-proxy`; } return null; }, - load(id) { + async load(id) { if (id.endsWith('?entry-proxy')) { - const importee = id.slice(0, -'?entry-proxy'.length); - // Note that this will throw if there is no default export - return `export {default} from '${importee}';`; + const entryId = id.slice(0, -'?entry-proxy'.length); + // We need to load and parse the original entry first because we need + // to know if it has a default export + const { hasDefaultExport } = await this.load({ id: entryId }); + let code = `import 'polyfill';export * from ${JSON.stringify(entryId)};`; + // Namespace reexports do not reexport default, so we need special + // handling here + if (hasDefaultExport) { + code += `export { default } from ${JSON.stringify(entryId)};`; + } + return code; } return null; } @@ -673,6 +688,7 @@ type ModuleInfo = { id: string; // the id of the module, for convenience code: string | null; // the source code of the module, `null` if external or not yet available ast: ESTree.Program; // the parsed abstract syntax tree if available + hasDefaultExport: boolean | null; // is there a default export, `null` if external or not yet available isEntry: boolean; // is this a user- or plugin-defined entry point isExternal: boolean; // for external modules that are referenced but not included in the graph isIncluded: boolean | null; // is the module included after tree-shaking, `null` if external or not yet available @@ -718,7 +734,7 @@ This allows you to inspect the final content of modules before deciding how to r The returned promise will resolve once the module has been fully transformed and parsed but before any imports have been resolved. That means that the resulting `ModuleInfo` will have empty `importedIds`, `dynamicallyImportedIds`, `importedIdResolutions` and `dynamicallyImportedIdResolutions`. This helps to avoid deadlock situations when awaiting `this.load` in a `resolveId` hook. If you are interested in `importedIds` and `dynamicallyImportedIds`, you should implement a `moduleParsed` hook. -Note that with regard to the `moduleSideEffects`, `syntheticNamedExports` and `meta` options, the same restrictions apply as for the `resolveId` hook: Their values only have an effect if the module has not been loaded yet. Thus, it is very important to use `this.resolve` first to find out if any plugins want to set special values for these options in their `resolveId` hook, and pass these options on to `this.load` if appropriate. The example below showcases how this can be handled to add a proxy module for modules containing a special code comment: +Note that with regard to the `moduleSideEffects`, `syntheticNamedExports` and `meta` options, the same restrictions apply as for the `resolveId` hook: Their values only have an effect if the module has not been loaded yet. Thus, it is very important to use `this.resolve` first to find out if any plugins want to set special values for these options in their `resolveId` hook, and pass these options on to `this.load` if appropriate. The example below showcases how this can be handled to add a proxy module for modules containing a special code comment. Note the special handling for re-exporting the default export: ```js export default function addProxyPlugin() { @@ -744,7 +760,16 @@ export default function addProxyPlugin() { load(id) { if (id.endsWith('?proxy')) { const importee = id.slice(0, -'?proxy'.length); - return `console.log('proxy for ${importee}'); export * from ${JSON.stringify(importee)};`; + // Note that namespace reexports do not reexport default exports + let code = `console.log('proxy for ${importee}'); export * from ${JSON.stringify( + importee + )};`; + // We know that while resolving the proxy, importee was already fully + // loaded and parsed, so we can rely on hasDefaultExport + if (this.getModuleInfo(importee).hasDefaultExport) { + code += `export { default } from ${JSON.stringify(importee)};`; + } + return code; } return null; } @@ -1142,7 +1167,7 @@ function parentPlugin() { } } // ...plugin hooks - } + }; } function dependentPlugin() { @@ -1151,20 +1176,19 @@ function dependentPlugin() { name: 'dependent', buildStart({ plugins }) { const parentName = 'parent'; - const parentPlugin = options.plugins - .find(plugin => plugin.name === parentName); + const parentPlugin = options.plugins.find(plugin => plugin.name === parentName); if (!parentPlugin) { // or handle this silently if it is optional throw new Error(`This plugin depends on the "${parentName}" plugin.`); } // now you can access the API methods in subsequent hooks parentApi = parentPlugin.api; - } + }, transform(code, id) { if (thereIsAReasonToDoSomething(id)) { parentApi.doSomething(id); } } - } + }; } ``` diff --git a/package-lock.json b/package-lock.json index 20c6852f923..01c288d2117 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1117,9 +1117,9 @@ "dev": true }, "caniuse-lite": { - "version": "1.0.30001300", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001300.tgz", - "integrity": "sha512-cVjiJHWGcNlJi8TZVKNMnvMid3Z3TTdDHmLDzlOdIiZq138Exvo0G+G0wTdVYolxKb4AYwC+38pxodiInVtJSA==", + "version": "1.0.30001301", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001301.tgz", + "integrity": "sha512-csfD/GpHMqgEL3V3uIgosvh+SVIQvCh43SNu9HRbP1lnxkKm1kjDG4f32PP571JplkLjfS+mg2p1gxR7MYrrIA==", "dev": true }, "chalk": { @@ -1370,9 +1370,9 @@ } }, "electron-to-chromium": { - "version": "1.4.49", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.49.tgz", - "integrity": "sha512-k/0t1TRfonHIp8TJKfjBu2cKj8MqYTiEpOhci+q7CVEE5xnCQnx1pTa+V8b/sdhe4S3PR4p4iceEQWhGrKQORQ==", + "version": "1.4.51", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.51.tgz", + "integrity": "sha512-JNEmcYl3mk1tGQmy0EvL5eik/CKSBuzAyGP0QFdG6LIgxQe3II0BL1m2zKc2MZMf3uGqHWE1TFddJML0RpjSHQ==", "dev": true }, "emoji-regex": { @@ -3098,7 +3098,7 @@ "log-symbols": "4.1.0", "minimatch": "3.0.4", "ms": "2.1.3", - "nanoid": "3.1.25", + "nanoid": "^3.1.31", "serialize-javascript": "6.0.0", "strip-json-comments": "3.1.1", "supports-color": "8.1.1", @@ -3247,10 +3247,9 @@ "dev": true }, "nanoid": { - "version": "3.1.25", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.1.25.tgz", - "integrity": "sha512-rdwtIXaXCLFAQbnfqDRnI6jaRHp9fTcYBjtFKE8eezcZ7LuLjhUaQGNeMXf1HmRoCH32CLz6XwX0TtxEOS/A3Q==", - "dev": true + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz", + "integrity": "sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA==" }, "natural-compare": { "version": "1.4.0", @@ -3931,9 +3930,9 @@ "dev": true }, "resolve": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.0.tgz", - "integrity": "sha512-3wCbTpk5WJlyE4mSOtDLhqQmGFi0/TD9VPwmiolnk8U0wRgMEktqCXd3vy5buTO3tljvalNvKrjHEfrd2WpEKA==", + "version": "1.21.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.21.1.tgz", + "integrity": "sha512-lfEImVbnolPuaSZuLQ52cAxPBHeI77sPwCOWRdy12UG/CNa8an7oBHH1R+Fp1/mUqSJi4c8TIP6FOIPSZAUrEQ==", "dev": true, "requires": { "is-core-module": "^2.8.0", @@ -3979,9 +3978,9 @@ } }, "rollup": { - "version": "2.64.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.64.0.tgz", - "integrity": "sha512-+c+lbw1lexBKSMb1yxGDVfJ+vchJH3qLbmavR+awDinTDA2C5Ug9u7lkOzj62SCu0PKUExsW36tpgW7Fmpn3yQ==", + "version": "2.65.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.65.0.tgz", + "integrity": "sha512-ohZVYrhtVMTqqeqH26sngfMiyGDg6gCUReOsoflXvYpzUkDHp8sVG8F9FQxjs72OfnLWpXP2nNNqQ9I0vkRovA==", "dev": true, "requires": { "fsevents": "~2.3.2" @@ -4450,9 +4449,9 @@ "dev": true }, "systemjs": { - "version": "6.11.0", - "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.11.0.tgz", - "integrity": "sha512-7YPIY44j+BoY+E6cGBSw0oCU8SNTTIHKZgftcBdwWkDzs/M86Fdlr21FrzAyph7Zo8r3CFGscyFe4rrBtixrBg==", + "version": "6.12.1", + "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.12.1.tgz", + "integrity": "sha512-hqTN6kW+pN6/qro6G9OZ7ceDQOcYno020zBQKpZQLsJhYTDMCMNfXi/Y8duF5iW+4WWZr42ry0MMkcRGpbwG2A==", "dev": true }, "terser": { diff --git a/package.json b/package.json index a2f9057fd46..2a6c131309e 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,7 @@ "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^13.1.3", "@rollup/plugin-replace": "^3.0.1", - "@rollup/plugin-typescript": "^8.2.5", + "@rollup/plugin-typescript": "^8.3.0", "@rollup/pluginutils": "^4.1.2", "@types/node": "^10.17.60", "@types/signal-exit": "^3.0.1", @@ -100,7 +100,7 @@ "pretty-bytes": "^5.6.0", "pretty-ms": "^7.0.1", "requirejs": "^2.3.6", - "rollup": "^2.64.0", + "rollup": "^2.65.0", "rollup-plugin-license": "^2.6.1", "rollup-plugin-string": "^3.0.0", "rollup-plugin-terser": "^7.0.2", @@ -111,7 +111,7 @@ "source-map": "^0.7.3", "source-map-support": "^0.5.21", "sourcemap-codec": "^1.4.8", - "systemjs": "^6.11.0", + "systemjs": "^6.12.1", "terser": "^5.10.0", "tslib": "^2.3.1", "typescript": "^4.5.5", diff --git a/src/ExternalModule.ts b/src/ExternalModule.ts index efd5420de5f..80e60e26fe1 100644 --- a/src/ExternalModule.ts +++ b/src/ExternalModule.ts @@ -46,6 +46,7 @@ export default class ExternalModule { get dynamicImporters() { return dynamicImporters.sort(); }, + hasDefaultExport: null, hasModuleSideEffects, id, implicitlyLoadedAfterOneOf: EMPTY_ARRAY, diff --git a/src/Module.ts b/src/Module.ts index fe458e638b0..93db11d47d6 100644 --- a/src/Module.ts +++ b/src/Module.ts @@ -277,6 +277,13 @@ export default class Module { get dynamicImporters() { return module.dynamicImporters.sort(); }, + get hasDefaultExport() { + // This information is only valid after parsing + if (!module.ast) { + return null; + } + return 'default' in module.exports || 'default' in module.reexportDescriptions; + }, hasModuleSideEffects, id, get implicitlyLoadedAfterOneOf() { diff --git a/src/rollup/types.d.ts b/src/rollup/types.d.ts index cf2ffa4117e..93f1c37e1b0 100644 --- a/src/rollup/types.d.ts +++ b/src/rollup/types.d.ts @@ -162,6 +162,7 @@ interface ModuleInfo { dynamicImporters: readonly string[]; dynamicallyImportedIdResolutions: readonly ResolvedId[]; dynamicallyImportedIds: readonly string[]; + hasDefaultExport: boolean | null; hasModuleSideEffects: boolean | 'no-treeshake'; id: string; implicitlyLoadedAfterOneOf: readonly string[]; diff --git a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js index 661bf005fac..0651fc7ad26 100644 --- a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-emitted-entry/_config.js @@ -73,6 +73,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN, implicitlyLoadedAfterOneOf: [], @@ -143,6 +144,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_DEP, implicitlyLoadedAfterOneOf: [], diff --git a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js index 7856f608a24..e25d1c64c4d 100644 --- a/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/implicitly-dependent-entry/_config.js @@ -69,6 +69,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN, implicitlyLoadedAfterOneOf: [], @@ -139,6 +140,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_DEP, implicitlyLoadedAfterOneOf: [], diff --git a/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js b/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js index c0d26c83d4b..8802c21bf44 100644 --- a/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/multiple-dependencies/_config.js @@ -117,6 +117,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN1, implicitlyLoadedAfterOneOf: [], @@ -236,6 +237,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN2, implicitlyLoadedAfterOneOf: [], @@ -354,6 +356,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_DEP, implicitlyLoadedAfterOneOf: [ID_MAIN1, ID_MAIN2], diff --git a/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js b/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js index 699ba45512e..14c405191ee 100644 --- a/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js +++ b/test/chunking-form/samples/implicit-dependencies/single-dependency/_config.js @@ -68,6 +68,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN, implicitlyLoadedAfterOneOf: [], @@ -138,6 +139,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_DEP, implicitlyLoadedAfterOneOf: [ID_MAIN], diff --git a/test/function/samples/deprecated/manual-chunks-info/_config.js b/test/function/samples/deprecated/manual-chunks-info/_config.js index c3d75ad7977..7749e615892 100644 --- a/test/function/samples/deprecated/manual-chunks-info/_config.js +++ b/test/function/samples/deprecated/manual-chunks-info/_config.js @@ -111,6 +111,7 @@ module.exports = { ], dynamicallyImportedIds: [getId('dynamic')], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: getId('main'), implicitlyLoadedAfterOneOf: [], @@ -145,6 +146,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [getId('dynamic')], + hasDefaultExport: null, hasModuleSideEffects: true, id: 'external', implicitlyLoadedAfterOneOf: [], @@ -177,6 +179,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: true, hasModuleSideEffects: true, id: getId('lib'), implicitlyLoadedAfterOneOf: [], @@ -260,6 +263,7 @@ module.exports = { ], dynamicallyImportedIds: ['external'], dynamicImporters: [getId('main')], + hasDefaultExport: false, hasModuleSideEffects: true, id: getId('dynamic'), implicitlyLoadedAfterOneOf: [], diff --git a/test/function/samples/has-default-export/_config.js b/test/function/samples/has-default-export/_config.js new file mode 100644 index 00000000000..daea5948706 --- /dev/null +++ b/test/function/samples/has-default-export/_config.js @@ -0,0 +1,45 @@ +const assert = require('assert'); +const path = require('path'); + +module.exports = { + description: 'reports if a module has a default export', + options: { + plugins: [ + { + async buildStart() { + const ID_MAIN = path.join(__dirname, 'main.js'); + const loadMain = this.load({ id: ID_MAIN }); + assert.strictEqual(this.getModuleInfo(ID_MAIN).hasDefaultExport, null); + assert.strictEqual((await loadMain).hasDefaultExport, false); + + assert.strictEqual( + (await this.load({ id: path.join(__dirname, 'direct.js') })).hasDefaultExport, + true, + 'direct' + ); + assert.strictEqual( + (await this.load({ id: path.join(__dirname, 'indirect.js') })).hasDefaultExport, + true, + 'indirect' + ); + assert.strictEqual( + (await this.load({ id: path.join(__dirname, 'reexport1.js') })).hasDefaultExport, + true, + 'reexport' + ); + assert.strictEqual( + (await this.load({ id: path.join(__dirname, 'reexport2.js') })).hasDefaultExport, + true, + 'renamed reexport' + ); + }, + load(id) { + assert.strictEqual(this.getModuleInfo(id).hasDefaultExport, null, `load ${id}`); + }, + transform(code, id) { + assert.strictEqual(this.getModuleInfo(id).hasDefaultExport, null, `transform ${id}`); + } + } + ] + } +}; diff --git a/test/function/samples/has-default-export/direct.js b/test/function/samples/has-default-export/direct.js new file mode 100644 index 00000000000..f2f6d5c381b --- /dev/null +++ b/test/function/samples/has-default-export/direct.js @@ -0,0 +1 @@ +export default 'direct'; diff --git a/test/function/samples/has-default-export/indirect.js b/test/function/samples/has-default-export/indirect.js new file mode 100644 index 00000000000..28786796a99 --- /dev/null +++ b/test/function/samples/has-default-export/indirect.js @@ -0,0 +1,2 @@ +const indirect = 'indirect'; +export { indirect as default }; diff --git a/test/function/samples/has-default-export/main.js b/test/function/samples/has-default-export/main.js new file mode 100644 index 00000000000..28d6ee09c9c --- /dev/null +++ b/test/function/samples/has-default-export/main.js @@ -0,0 +1,9 @@ +import direct from './direct.js'; +import indirect from './indirect.js'; +import reexport1 from './reexport1.js'; +import reexport2 from './reexport2.js'; + +assert.strictEqual(direct, 'direct'); +assert.strictEqual(indirect, 'indirect'); +assert.strictEqual(reexport1, 'default'); +assert.strictEqual(reexport2, 'foo'); diff --git a/test/function/samples/has-default-export/other.js b/test/function/samples/has-default-export/other.js new file mode 100644 index 00000000000..a99ac05aa02 --- /dev/null +++ b/test/function/samples/has-default-export/other.js @@ -0,0 +1,2 @@ +export default 'default'; +export const foo = 'foo'; diff --git a/test/function/samples/has-default-export/reexport1.js b/test/function/samples/has-default-export/reexport1.js new file mode 100644 index 00000000000..b98cf73cdb9 --- /dev/null +++ b/test/function/samples/has-default-export/reexport1.js @@ -0,0 +1 @@ +export { default } from './other.js'; diff --git a/test/function/samples/has-default-export/reexport2.js b/test/function/samples/has-default-export/reexport2.js new file mode 100644 index 00000000000..08facccd528 --- /dev/null +++ b/test/function/samples/has-default-export/reexport2.js @@ -0,0 +1 @@ +export { foo as default } from './other.js'; diff --git a/test/function/samples/manual-chunks-info/_config.js b/test/function/samples/manual-chunks-info/_config.js index 4780bfcae47..b30f082d6e0 100644 --- a/test/function/samples/manual-chunks-info/_config.js +++ b/test/function/samples/manual-chunks-info/_config.js @@ -110,6 +110,7 @@ module.exports = { ], dynamicallyImportedIds: [getId('dynamic')], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: getId('main'), implicitlyLoadedAfterOneOf: [], @@ -144,6 +145,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [getId('dynamic')], + hasDefaultExport: null, hasModuleSideEffects: true, id: 'external', implicitlyLoadedAfterOneOf: [], @@ -176,6 +178,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: true, hasModuleSideEffects: true, id: getId('lib'), implicitlyLoadedAfterOneOf: [], @@ -259,6 +262,7 @@ module.exports = { ], dynamicallyImportedIds: ['external'], dynamicImporters: [getId('main')], + hasDefaultExport: false, hasModuleSideEffects: true, id: getId('dynamic'), implicitlyLoadedAfterOneOf: [], diff --git a/test/function/samples/module-parsed-hook/_config.js b/test/function/samples/module-parsed-hook/_config.js index c1505d17f54..75e093d2e4d 100644 --- a/test/function/samples/module-parsed-hook/_config.js +++ b/test/function/samples/module-parsed-hook/_config.js @@ -51,6 +51,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN, implicitlyLoadedAfterOneOf: [], @@ -107,6 +108,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_DEP, implicitlyLoadedAfterOneOf: [], diff --git a/test/function/samples/plugin-module-information/_config.js b/test/function/samples/plugin-module-information/_config.js index 67a5202770d..f5ad0b6e12a 100644 --- a/test/function/samples/plugin-module-information/_config.js +++ b/test/function/samples/plugin-module-information/_config.js @@ -18,6 +18,7 @@ module.exports = { ast: null, code: null, dynamicImporters: [], + hasDefaultExport: null, dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], hasModuleSideEffects: true, @@ -183,6 +184,7 @@ module.exports = { ], dynamicallyImportedIds: [ID_NESTED, ID_PATH], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_MAIN, implicitlyLoadedAfterOneOf: [], @@ -270,6 +272,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_FOO, implicitlyLoadedAfterOneOf: [], @@ -297,6 +300,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [ID_MAIN], + hasDefaultExport: null, hasModuleSideEffects: true, id: ID_PATH, implicitlyLoadedAfterOneOf: [], @@ -379,6 +383,7 @@ module.exports = { dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], dynamicImporters: [ID_MAIN], + hasDefaultExport: false, hasModuleSideEffects: true, id: ID_NESTED, implicitlyLoadedAfterOneOf: [], diff --git a/test/function/samples/preload-module/_config.js b/test/function/samples/preload-module/_config.js index 15ce55e3c24..51ec568846e 100644 --- a/test/function/samples/preload-module/_config.js +++ b/test/function/samples/preload-module/_config.js @@ -33,6 +33,7 @@ module.exports = { assert.deepStrictEqual(moduleInfo, { code: "import './dep';\nassert.ok(true);\n", dynamicImporters: [], + hasDefaultExport: false, dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], hasModuleSideEffects: true, @@ -73,6 +74,7 @@ module.exports = { assert.deepStrictEqual(moduleInfo, { code: 'assert.ok(true);\n', dynamicImporters: [], + hasDefaultExport: false, dynamicallyImportedIdResolutions: [], dynamicallyImportedIds: [], hasModuleSideEffects: true,