Skip to content

Commit

Permalink
Merge branch 'master' into gh-3062-do-not-hoist-transitive-imports
Browse files Browse the repository at this point in the history
  • Loading branch information
lukastaegert committed Jan 27, 2020
2 parents 5f72e5f + 7fc24ab commit 8b300ed
Show file tree
Hide file tree
Showing 384 changed files with 4,498 additions and 3,476 deletions.
197 changes: 149 additions & 48 deletions src/utils/chunkColouring.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,74 +2,175 @@ import ExternalModule from '../ExternalModule';
import Module from '../Module';
import { randomUint8Array, Uint8ArrayXor } from './entryHashing';

type DependentModuleMap = Map<Module, Set<Module>>;

export function assignChunkColouringHashes(
entryModules: Module[],
manualChunkModules: Record<string, Module[]>
) {
let currentEntry: Module, currentEntryHash: Uint8Array;
let modulesVisitedForCurrentEntry: Set<string>;
const handledEntryPoints: Set<string> = new Set();
const dynamicImports: Module[] = [];
const { dependentEntryPointsByModule, dynamicImportersByModule } = analyzeModuleGraph(
entryModules
);
const dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap = getDynamicDependentEntryPoints(
dependentEntryPointsByModule,
dynamicImportersByModule
);

const addCurrentEntryColourToModule = (module: Module) => {
if (currentEntry.manualChunkAlias) {
module.manualChunkAlias = currentEntry.manualChunkAlias;
module.entryPointsHash = currentEntryHash;
} else {
Uint8ArrayXor(module.entryPointsHash, currentEntryHash);
}
if (manualChunkModules) {
for (const chunkName of Object.keys(manualChunkModules)) {
const entryHash = randomUint8Array(10);

for (const dependency of module.dependencies) {
if (
dependency instanceof ExternalModule ||
modulesVisitedForCurrentEntry.has(dependency.id)
) {
continue;
}
modulesVisitedForCurrentEntry.add(dependency.id);
if (!handledEntryPoints.has(dependency.id) && !dependency.manualChunkAlias) {
addCurrentEntryColourToModule(dependency);
for (const entry of manualChunkModules[chunkName]) {
addColourToModuleDependencies(
entry,
entryHash,
null,
dependentEntryPointsByModule,
dynamicDependentEntryPointsByDynamicEntry
);
}
}
}

for (const { resolution } of module.dynamicImports) {
if (
resolution instanceof Module &&
resolution.dynamicallyImportedBy.length > 0 &&
!resolution.manualChunkAlias
) {
dynamicImports.push(resolution);
}
for (const entry of entryModules) {
if (!entry.manualChunkAlias) {
const entryHash = randomUint8Array(10);
addColourToModuleDependencies(
entry,
entryHash,
null,
dependentEntryPointsByModule,
dynamicDependentEntryPointsByDynamicEntry
);
}
};
}

if (manualChunkModules) {
for (const chunkName of Object.keys(manualChunkModules)) {
currentEntryHash = randomUint8Array(10);
for (const entry of dynamicImportersByModule.keys()) {
if (!entry.manualChunkAlias) {
const entryHash = randomUint8Array(10);
addColourToModuleDependencies(
entry,
entryHash,
dynamicDependentEntryPointsByDynamicEntry.get(entry)!,
dependentEntryPointsByModule,
dynamicDependentEntryPointsByDynamicEntry
);
}
}
}

for (currentEntry of manualChunkModules[chunkName]) {
modulesVisitedForCurrentEntry = new Set(currentEntry.id);
addCurrentEntryColourToModule(currentEntry);
function analyzeModuleGraph(
entryModules: Module[]
): {
dependentEntryPointsByModule: DependentModuleMap;
dynamicImportersByModule: DependentModuleMap;
} {
const dynamicImportersByModule: DependentModuleMap = new Map();
const dependentEntryPointsByModule: DependentModuleMap = new Map();
const entriesToHandle = new Set(entryModules);
for (const currentEntry of entriesToHandle) {
const modulesToHandle = new Set<Module>([currentEntry]);
for (const module of modulesToHandle) {
getDependentModules(dependentEntryPointsByModule, module).add(currentEntry);
for (const dependency of module.dependencies) {
if (!(dependency instanceof ExternalModule)) {
modulesToHandle.add(dependency);
}
}
for (const { resolution } of module.dynamicImports) {
if (
resolution instanceof Module &&
resolution.dynamicallyImportedBy.length > 0 &&
!resolution.manualChunkAlias
) {
getDependentModules(dynamicImportersByModule, resolution).add(module);
entriesToHandle.add(resolution);
}
}
}
}
return { dependentEntryPointsByModule, dynamicImportersByModule };
}

for (currentEntry of entryModules) {
handledEntryPoints.add(currentEntry.id);
currentEntryHash = randomUint8Array(10);
modulesVisitedForCurrentEntry = new Set(currentEntry.id);
if (!currentEntry.manualChunkAlias) {
addCurrentEntryColourToModule(currentEntry);
function getDependentModules(moduleMap: DependentModuleMap, module: Module): Set<Module> {
const dependentModules = moduleMap.get(module) || new Set();
moduleMap.set(module, dependentModules);
return dependentModules;
}

function getDynamicDependentEntryPoints(
dependentEntryPointsByModule: DependentModuleMap,
dynamicImportersByModule: DependentModuleMap
): DependentModuleMap {
const dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap = new Map();
for (const [dynamicEntry, importers] of dynamicImportersByModule.entries()) {
const dynamicDependentEntryPoints = getDependentModules(
dynamicDependentEntryPointsByDynamicEntry,
dynamicEntry
);
for (const importer of importers) {
for (const entryPoint of dependentEntryPointsByModule.get(importer)!) {
dynamicDependentEntryPoints.add(entryPoint);
}
}
}
return dynamicDependentEntryPointsByDynamicEntry;
}

for (currentEntry of dynamicImports) {
if (handledEntryPoints.has(currentEntry.id)) {
function addColourToModuleDependencies(
entry: Module,
colour: Uint8Array,
dynamicDependentEntryPoints: Set<Module> | null,
dependentEntryPointsByModule: DependentModuleMap,
dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap
) {
const manualChunkAlias = entry.manualChunkAlias;
const modulesToHandle = new Set([entry]);
for (const module of modulesToHandle) {
if (manualChunkAlias) {
module.manualChunkAlias = manualChunkAlias;
module.entryPointsHash = colour;
} else if (
dynamicDependentEntryPoints &&
areEntryPointsContainedOrDynamicallyDependent(
dynamicDependentEntryPoints,
dependentEntryPointsByModule.get(module)!,
dynamicDependentEntryPointsByDynamicEntry
)
) {
continue;
} else {
Uint8ArrayXor(module.entryPointsHash, colour);
}
for (const dependency of module.dependencies) {
if (!(dependency instanceof ExternalModule || dependency.manualChunkAlias)) {
modulesToHandle.add(dependency);
}
}
}
}

function areEntryPointsContainedOrDynamicallyDependent(
entryPoints: Set<Module>,
superSet: Set<Module>,
dynamicDependentEntryPointsByDynamicEntry: DependentModuleMap
): boolean {
for (const module of entryPoints) {
if (!superSet.has(module)) {
const dynamicDependentEntryPoints = dynamicDependentEntryPointsByDynamicEntry.get(module);
if (
!(
dynamicDependentEntryPoints &&
areEntryPointsContainedOrDynamicallyDependent(
dynamicDependentEntryPoints,
superSet,
dynamicDependentEntryPointsByDynamicEntry
)
)
) {
return false;
}
}
handledEntryPoints.add(currentEntry.id);
currentEntryHash = randomUint8Array(10);
modulesVisitedForCurrentEntry = new Set(currentEntry.id);
addCurrentEntryColourToModule(currentEntry);
}
return true;
}
21 changes: 7 additions & 14 deletions src/utils/entryHashing.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const CHAR_CODE_A = 97;
const CHAR_CODE_0 = 48;

function intToHex(num: number) {
function intToHex(num: number): string {
if (num < 10) return String.fromCharCode(CHAR_CODE_0 + num);
else return String.fromCharCode(CHAR_CODE_A + (num - 10));
}

export function Uint8ArrayToHexString(buffer: Uint8Array) {
export function Uint8ArrayToHexString(buffer: Uint8Array): string {
let str = '';
// hex conversion - 2 chars per 8 bit component
for (let i = 0; i < buffer.length; i++) {
Expand All @@ -18,24 +18,17 @@ export function Uint8ArrayToHexString(buffer: Uint8Array) {
return str;
}

export function Uint8ArrayXor(to: Uint8Array, from: Uint8Array) {
for (let i = 0; i < to.length; i++) to[i] = to[i] ^ from[i];
return to;
}

export function randomUint8Array(len: number) {
export function randomUint8Array(len: number): Uint8Array {
const buffer = new Uint8Array(len);
for (let i = 0; i < buffer.length; i++) buffer[i] = Math.random() * (2 << 8);
return buffer;
}

export function Uint8ArrayEqual(bufferA: Uint8Array, bufferB: Uint8Array) {
for (let i = 0; i < bufferA.length; i++) {
if (bufferA[i] !== bufferB[i]) return false;
}
return true;
export function Uint8ArrayXor(to: Uint8Array, from: Uint8Array): Uint8Array {
for (let i = 0; i < to.length; i++) to[i] = to[i] ^ from[i];
return to;
}

export function randomHexString(len: number) {
export function randomHexString(len: number): string {
return Uint8ArrayToHexString(randomUint8Array(Math.floor(len / 2)));
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
define(['exports'], function (exports) { 'use strict';

class C {
fn (num) {
console.log(num - p$1);
}
}

var p = 43;

new C().fn(p);

class C$1 {
fn (num) {
console.log(num - p);
}
}

var p$1 = 42;

new C$1().fn(p$1);

exports.p = p;
exports.p$1 = p$1;

});
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
define(['exports', './main2'], function (exports, main2) { 'use strict';
define(['exports', './generated-main1'], function (exports, main2) { 'use strict';

class C {
fn (num) {
console.log(num - main2.p);
}
}

var p = 42;

new C().fn(p);
exports.p = main2.p$1;

exports.p = p;

Object.defineProperty(exports, '__esModule', { value: true });
Object.defineProperty(exports, '__esModule', { value: true });

});
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
define(['exports', './main1'], function (exports, main1) { 'use strict';
define(['exports', './generated-main1'], function (exports, main2) { 'use strict';

class C {
fn (num) {
console.log(num - main1.p);
}
}

var p = 43;

new C().fn(p);
exports.p = main2.p;

exports.p = p;

Object.defineProperty(exports, '__esModule', { value: true });
Object.defineProperty(exports, '__esModule', { value: true });

});
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
'use strict';

class C {
fn (num) {
console.log(num - p$1);
}
}

var p = 43;

new C().fn(p);

class C$1 {
fn (num) {
console.log(num - p);
}
}

var p$1 = 42;

new C$1().fn(p$1);

exports.p = p;
exports.p$1 = p$1;
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,8 @@

Object.defineProperty(exports, '__esModule', { value: true });

var main2 = require('./main2.js');
var main2 = require('./generated-main1.js');

class C {
fn (num) {
console.log(num - main2.p);
}
}

var p = 42;

new C().fn(p);

exports.p = p;
exports.p = main2.p$1;

0 comments on commit 8b300ed

Please sign in to comment.