Skip to content

Commit

Permalink
Add dynamic imports to getModuleInfo, resolves #3232
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Mar 20, 2020
1 parent fc29fa6 commit 2e6edae
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 35 deletions.
9 changes: 7 additions & 2 deletions browser/fs.ts
@@ -1,5 +1,10 @@
const nope = (method: string) => (..._args: any[]): any => {
throw new Error(`Cannot use fs.${method} inside browser`);
const nope = (method: string) => (..._args: any[]): never => {
throw Object.assign(
new Error(
`Cannot access the file system (via "fs.${method}") when using the browser build of Rollup. Make sure you supply a plugin with custom resolveId and load hooks to Rollup.`
),
{ code: 'NO_FS_IN_BROWSER', url: 'https://rollupjs.org/guide/en/#a-simple-example' }
);
};

export const lstatSync = nope('lstatSync');
Expand Down
3 changes: 2 additions & 1 deletion docs/05-plugin-development.md
Expand Up @@ -496,7 +496,8 @@ Returns additional information about the module in question in the form
id: string, // the id of the module, for convenience
isEntry: boolean, // is this a user- or plugin-defined entry point
isExternal: boolean, // for external modules that are not included in the graph
importedIds: string[], // the module ids imported by this module
importedIds: string[], // the module ids statically imported by this module
dynamicallyImportedIds: string[], // the module ids imported by this module via dynamic import()
hasModuleSideEffects: boolean // are imports of this module included if nothing is imported from it
}
```
Expand Down
5 changes: 1 addition & 4 deletions src/Chunk.ts
Expand Up @@ -706,10 +706,7 @@ export default class Chunk {
}
const renderedResolution =
resolution instanceof Module
? `'${this.getRelativePath(
(resolution.facadeChunk || resolution.chunk!).id!,
stripKnownJsExtensions
)}'`
? `'${this.getRelativePath(resolution.facadeChunk!.id!, stripKnownJsExtensions)}'`
: resolution instanceof ExternalModule
? `'${
resolution.renormalizeRenderPath
Expand Down
1 change: 1 addition & 0 deletions src/rollup/types.d.ts
Expand Up @@ -164,6 +164,7 @@ export interface PluginContext extends MinimalPluginContext {
getModuleInfo: (
moduleId: string
) => {
dynamicallyImportedIds: string[];
hasModuleSideEffects: boolean;
id: string;
importedIds: string[];
Expand Down
19 changes: 14 additions & 5 deletions src/utils/PluginContext.ts
Expand Up @@ -127,14 +127,23 @@ export function getPluginContexts(
if (foundModule == null) {
throw new Error(`Unable to find module ${moduleId}`);
}

const importedIds: string[] = [];
const dynamicallyImportedIds: string[] = [];
if (foundModule instanceof Module) {
for (const source of foundModule.sources) {
importedIds.push(foundModule.resolvedIds[source].id);
}
for (const { resolution } of foundModule.dynamicImports) {
if (resolution instanceof Module || resolution instanceof ExternalModule) {
dynamicallyImportedIds.push(resolution.id);
}
}
}
return {
dynamicallyImportedIds,
hasModuleSideEffects: foundModule.moduleSideEffects,
id: foundModule.id,
importedIds:
foundModule instanceof ExternalModule
? []
: Array.from(foundModule.sources).map(id => foundModule.resolvedIds[id].id),
importedIds,
isEntry: foundModule instanceof Module && foundModule.isEntryPoint,
isExternal: foundModule instanceof ExternalModule
};
Expand Down
9 changes: 0 additions & 9 deletions src/utils/resolveId.ts
@@ -1,4 +1,3 @@
import { error } from './error';
import { lstatSync, readdirSync, realpathSync } from './fs';
import { basename, dirname, isAbsolute, resolve } from './path';
import { PluginDriver } from './PluginDriver';
Expand All @@ -13,14 +12,6 @@ export async function resolveId(
const pluginResult = await pluginDriver.hookFirst('resolveId', [source, importer], null, skip);
if (pluginResult != null) return pluginResult;

if (typeof process === 'undefined') {
return error({
code: 'MISSING_PROCESS',
message: `It looks like you're using Rollup in a non-Node.js environment. This means you must supply a plugin with custom resolveId and load functions`,
url: 'https://rollupjs.org/guide/en/#a-simple-example'
});
}

// external modules (non-entry modules that start with neither '.' or '/')
// are skipped at this stage.
if (importer !== undefined && !isAbsolute(source) && source[0] !== '.') return null;
Expand Down
20 changes: 11 additions & 9 deletions test/function/index.js
Expand Up @@ -3,8 +3,7 @@ const assert = require('assert');
const rollup = require('../../dist/rollup');
const { compareError, compareWarnings, extend, runTestSuiteWithSamples } = require('../utils.js');

function requireWithContext(code, context) {
const module = { exports: {} };
function requireWithContext(code, context, module) {
const contextWithExports = Object.assign({}, context, { module, exports: module.exports });
const contextKeys = Object.keys(contextWithExports);
const contextValues = contextKeys.map(key => contextWithExports[key]);
Expand All @@ -19,14 +18,20 @@ function requireWithContext(code, context) {
}

function runCodeSplitTest(codeMap, entryId, configContext) {
const exportsMap = Object.create(null);

const requireFromOutputVia = importer => importee => {
const outputId = path.posix.join(path.posix.dirname(importer), importee);
if (outputId in exportsMap) {
return exportsMap[outputId];
}
const code = codeMap[outputId];
if (typeof code !== 'undefined') {
return requireWithContext(
return (exportsMap[outputId] = requireWithContext(
code,
Object.assign({ require: requireFromOutputVia(outputId) }, context)
);
Object.assign({ require: requireFromOutputVia(outputId) }, context),
(exportsMap[outputId] = { exports: {} })
));
} else {
return require(importee);
}
Expand All @@ -35,10 +40,7 @@ function runCodeSplitTest(codeMap, entryId, configContext) {
const context = Object.assign({ assert }, configContext);
let exports;
try {
exports = requireWithContext(
codeMap[entryId],
Object.assign({ require: requireFromOutputVia(entryId) }, context)
);
exports = requireFromOutputVia(entryId)(entryId);
} catch (error) {
return { error, exports: error.exports };
}
Expand Down
7 changes: 6 additions & 1 deletion test/function/samples/plugin-module-information/_config.js
Expand Up @@ -15,6 +15,7 @@ module.exports = {
plugins: {
load(id) {
assert.deepStrictEqual(this.getModuleInfo(id), {
dynamicallyImportedIds: [],
hasModuleSideEffects: true,
id,
importedIds: [],
Expand All @@ -26,27 +27,31 @@ module.exports = {
rendered = true;
assert.deepStrictEqual(Array.from(this.moduleIds), [ID_MAIN, ID_FOO, ID_NESTED, ID_PATH]);
assert.deepStrictEqual(this.getModuleInfo(ID_MAIN), {
dynamicallyImportedIds: [ID_NESTED],
hasModuleSideEffects: true,
id: ID_MAIN,
importedIds: [ID_FOO, ID_NESTED],
importedIds: [ID_FOO],
isEntry: true,
isExternal: false
});
assert.deepStrictEqual(this.getModuleInfo(ID_FOO), {
dynamicallyImportedIds: [],
hasModuleSideEffects: true,
id: ID_FOO,
importedIds: [ID_PATH],
isEntry: false,
isExternal: false
});
assert.deepStrictEqual(this.getModuleInfo(ID_NESTED), {
dynamicallyImportedIds: [],
hasModuleSideEffects: true,
id: ID_NESTED,
importedIds: [ID_FOO],
isEntry: false,
isExternal: false
});
assert.deepStrictEqual(this.getModuleInfo(ID_PATH), {
dynamicallyImportedIds: [],
hasModuleSideEffects: true,
id: ID_PATH,
importedIds: [],
Expand Down
6 changes: 2 additions & 4 deletions test/function/samples/plugin-module-information/main.js
@@ -1,4 +1,2 @@
export {foo} from './foo.js';
import { nested } from './nested/nested';

export {nested};
export { foo } from './foo.js';
export const nested = import('./nested/nested');

0 comments on commit 2e6edae

Please sign in to comment.