diff --git a/config/entryPoints.js b/config/entryPoints.js index 327cf08cbb8..4c1a5cf1396 100644 --- a/config/entryPoints.js +++ b/config/entryPoints.js @@ -47,21 +47,63 @@ const path = require("path").posix; exports.check = function (id, parentId) { const resolved = path.resolve(path.dirname(parentId), id); - const resolvedParts = resolved.split(path.sep); - const distIndex = resolvedParts.lastIndexOf("dist"); + const importedParts = partsAfterDist(resolved); - if (distIndex >= 0) { - let node = lookupTrie; - - for (let i = distIndex + 1; - node && i < resolvedParts.length; - ++i) { - const dir = resolvedParts[i]; - node = node && node.dirs && node.dirs[dir]; + if (importedParts) { + const entryPointIndex = lengthOfLongestEntryPoint(importedParts); + if (entryPointIndex === importedParts.length) { + return true; } - return Boolean(node && node.isEntry); + if (entryPointIndex >= 0) { + const parentParts = partsAfterDist(parentId); + const parentEntryPointIndex = lengthOfLongestEntryPoint(parentParts); + const sameEntryPoint = + entryPointIndex === parentEntryPointIndex && + arraysEqualUpTo(importedParts, parentParts, entryPointIndex); + + // If the imported ID and the parent ID have the same longest entry + // point prefix, then this import is safely confined within that + // entry point. Returning false lets Rollup know this import is not + // external, and can be bundled into the CJS bundle that we build + // for this shared entry point. + if (sameEntryPoint) { + return false; + } + + console.warn(`Risky cross-entry-point nested import of ${id} in ${ + partsAfterDist(parentId).join("/") + }`); + } } return false; }; + +function partsAfterDist(id) { + const parts = id.split(path.sep); + const distIndex = parts.lastIndexOf("dist"); + if (distIndex >= 0) { + return parts.slice(distIndex + 1); + } +} + +function lengthOfLongestEntryPoint(parts) { + let node = lookupTrie; + let longest = -1; + for (let i = 0; node && i < parts.length; ++i) { + if (node.isEntry) longest = i; + node = node.dirs && node.dirs[parts[i]]; + } + if (node && node.isEntry) { + return parts.length; + } + return longest; +} + +function arraysEqualUpTo(a, b, end) { + for (let i = 0; i < end; ++i) { + if (a[i] !== b[i]) return false; + } + return true; +}