Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect rendered exports when generating chunk hashes #2695

Merged
merged 7 commits into from Feb 17, 2019
5 changes: 4 additions & 1 deletion src/Chunk.ts
Expand Up @@ -667,6 +667,7 @@ export default class Chunk {
if (!this.renderedSource) return '';
const hash = sha256();
hash.update(this.renderedSource.toString());
hash.update(Object.keys(this.exportNames).join(','));
return (this.renderedHash = hash.digest('hex'));
}

Expand Down Expand Up @@ -705,7 +706,9 @@ export default class Chunk {
private computeContentHashWithDependencies(addons: Addons, options: OutputOptions): string {
const hash = sha256();

hash.update(addons.hash);
hash.update(
[addons.intro, addons.outro, addons.banner, addons.footer].map(addon => addon || '').join(':')
);
hash.update(options.format);
this.visitDependencies(dep => {
if (dep instanceof ExternalModule) hash.update(':' + dep.renderPath);
Expand Down
5 changes: 1 addition & 4 deletions src/utils/addons.ts
Expand Up @@ -7,7 +7,6 @@ export interface Addons {
outro?: string;
banner?: string;
footer?: string;
hash: Uint8Array;
}

function evalIfFn(strOrFn: string | (() => string | Promise<string>)): string | Promise<string> {
Expand Down Expand Up @@ -38,9 +37,7 @@ export function createAddons(graph: Graph, options: OutputOptions): Promise<Addo
if (banner.length) banner += '\n';
if (footer.length) footer = '\n' + footer;

const hash = new Uint8Array(4);

return { intro, outro, banner, footer, hash };
return { intro, outro, banner, footer };
})
.catch(
(err): any => {
Expand Down
@@ -0,0 +1,5 @@
define(['./chunk-main2-0a527b43-amd.js'], function (main2) { 'use strict';

main2.log(main2.dep);

});

This file was deleted.

This file was deleted.

@@ -0,0 +1,7 @@
define(['./chunk-main2-0a527b43-amd.js'], function (main2) { 'use strict';



return main2.log;

});
@@ -0,0 +1,5 @@
'use strict';

var main2 = require('./chunk-main2-328c93f2-cjs.js');

main2.log(main2.dep);

This file was deleted.

This file was deleted.

@@ -0,0 +1,7 @@
'use strict';

var main2 = require('./chunk-main2-328c93f2-cjs.js');



module.exports = main2.log;

This file was deleted.

@@ -0,0 +1,3 @@
import { a as log, b as dep } from './chunk-main2-d7d48284-esm.js';

log(dep);

This file was deleted.

@@ -0,0 +1 @@
export { a as default } from './chunk-main2-d7d48284-esm.js';
@@ -1,4 +1,4 @@
System.register(['./chunk-main2-bd8b7ffb-system.js'], function (exports, module) {
System.register(['./chunk-main2-d134c6d9-system.js'], function (exports, module) {
'use strict';
var log, dep;
return {
Expand Down
@@ -1,4 +1,4 @@
System.register(['./chunk-main2-bd8b7ffb-system.js'], function (exports, module) {
System.register(['./chunk-main2-d134c6d9-system.js'], function (exports, module) {
'use strict';
return {
setters: [function (module) {
Expand Down
Expand Up @@ -17,13 +17,13 @@ module.exports = {
assert.equal(
code,
'\n' +
`${color}//→ entry1-a47394dc.js:${standard}\n` +
`${color}//→ entry1-d8c4343d.js:${standard}\n` +
"console.log('main1');\n" +
'\n' +
`${color}//→ Entry 2-d6c85f3f.js:${standard}\n` +
`${color}//→ Entry 2-99f48ca0.js:${standard}\n` +
"console.log('main2');\n" +
'\n' +
`${color}//→ main3-22d8845f.js:${standard}\n` +
`${color}//→ main3-a6240449.js:${standard}\n` +
"console.log('main3');\n"
);
}
Expand Down
6 changes: 3 additions & 3 deletions test/cli/samples/code-splitting-named-inputs/_config.js
Expand Up @@ -17,13 +17,13 @@ module.exports = {
assert.equal(
code,
'\n' +
`${color}//→ entry1-a47394dc.js:${standard}\n` +
`${color}//→ entry1-d8c4343d.js:${standard}\n` +
"console.log('main1');\n" +
'\n' +
`${color}//→ Entry 2-d6c85f3f.js:${standard}\n` +
`${color}//→ Entry 2-99f48ca0.js:${standard}\n` +
"console.log('main2');\n" +
'\n' +
`${color}//→ main3-22d8845f.js:${standard}\n` +
`${color}//→ main3-a6240449.js:${standard}\n` +
"console.log('main3');\n"
);
}
Expand Down
47 changes: 47 additions & 0 deletions test/file-hashes/index.js
@@ -0,0 +1,47 @@
const path = require('path');
const rollup = require('../../dist/rollup');
const { extend, runTestSuiteWithSamples } = require('../utils.js');
const assert = require('assert');

runTestSuiteWithSamples('file hashes', path.resolve(__dirname, 'samples'), (dir, config) => {
(config.skip ? describe.skip : config.solo ? describe.only : describe)(
path.basename(dir) + ': ' + config.description,
() => {
it(`generates correct hashes`, () => {
process.chdir(dir);
return Promise.all(
[config.options1, config.options2].map(options =>
rollup
.rollup(options)
.then(bundle =>
bundle.generate(
extend(
{ format: 'esm', chunkFileNames: '[hash]', entryFileNames: '[hash]' },
options.output
)
)
)
)
).then(([generated1, generated2]) => {
const fileContentsByHash = new Map();
addAndCheckFileContentsByHash(fileContentsByHash, generated1);
addAndCheckFileContentsByHash(fileContentsByHash, generated2);
});
});
}
);
});

function addAndCheckFileContentsByHash(fileContentsByHash, generated) {
for (const chunk of generated.output) {
const hash = chunk.fileName;
if (fileContentsByHash.has(hash)) {
assert.equal(
fileContentsByHash.get(hash),
chunk.code,
'Two chunks contained different code even though the hashes were the same.'
);
}
fileContentsByHash.set(hash, chunk.code);
}
}
15 changes: 15 additions & 0 deletions test/file-hashes/samples/banner/_config.js
@@ -0,0 +1,15 @@
module.exports = {
description: 'creates different hashes if the banner differs',
options1: {
input: 'main',
output: {
banner: 'console.log(1);'
}
},
options2: {
input: 'main',
output: {
banner: 'console.log(2);'
}
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/banner/main.js
@@ -0,0 +1 @@
console.log('main');
9 changes: 9 additions & 0 deletions test/file-hashes/samples/content/_config.js
@@ -0,0 +1,9 @@
module.exports = {
description: 'creates different hashes if the content differs',
options1: {
input: { main: 'main1', dep: 'dep1' }
},
options2: {
input: { main: 'main2', dep: 'dep2' }
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/content/dep1.js
@@ -0,0 +1 @@
console.log('dep');
1 change: 1 addition & 0 deletions test/file-hashes/samples/content/dep2.js
@@ -0,0 +1 @@
console.log('dep');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/content/main1.js
@@ -0,0 +1,3 @@
import './dep1';

console.log('main1');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/content/main2.js
@@ -0,0 +1,3 @@
import './dep2';

console.log('main2');
9 changes: 9 additions & 0 deletions test/file-hashes/samples/dependency-content/_config.js
@@ -0,0 +1,9 @@
module.exports = {
description: 'creates different hashes if the content of dependencies differs',
options1: {
input: { main: 'main1', dep: 'dep1' }
},
options2: {
input: { main: 'main2', dep: 'dep2' }
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/dependency-content/dep1.js
@@ -0,0 +1 @@
console.log('dep1');
1 change: 1 addition & 0 deletions test/file-hashes/samples/dependency-content/dep2.js
@@ -0,0 +1 @@
console.log('dep2');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/dependency-content/main1.js
@@ -0,0 +1,3 @@
import './dep1';

console.log('main');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/dependency-content/main2.js
@@ -0,0 +1,3 @@
import './dep2';

console.log('main');
9 changes: 9 additions & 0 deletions test/file-hashes/samples/exports/_config.js
@@ -0,0 +1,9 @@
module.exports = {
description: 'creates different hashes if the generated exports differ',
options1: {
input: ['main1', 'other']
},
options2: {
input: ['main2', 'other']
}
};
2 changes: 2 additions & 0 deletions test/file-hashes/samples/exports/dep.js
@@ -0,0 +1,2 @@
export const mightNotBeImported = 42;
console.log(mightNotBeImported);
3 changes: 3 additions & 0 deletions test/file-hashes/samples/exports/main1.js
@@ -0,0 +1,3 @@
import {mightNotBeImported} from './dep';

console.log('main1', mightNotBeImported);
3 changes: 3 additions & 0 deletions test/file-hashes/samples/exports/main2.js
@@ -0,0 +1,3 @@
import './dep';

console.log('main2');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/exports/other.js
@@ -0,0 +1,3 @@
import './dep';

console.log('other');
11 changes: 11 additions & 0 deletions test/file-hashes/samples/external-dependency-names/_config.js
@@ -0,0 +1,11 @@
module.exports = {
description: 'creates different hashes if the names of external dependencies differ',
options1: {
input: { mainA: 'main1a', mainB: 'main1b' },
external: ['external', 'external1']
},
options2: {
input: { mainA: 'main2a', mainB: 'main2b' },
external: ['external', 'external2']
}
};
3 changes: 3 additions & 0 deletions test/file-hashes/samples/external-dependency-names/main1a.js
@@ -0,0 +1,3 @@
import 'external';

console.log('main');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/external-dependency-names/main1b.js
@@ -0,0 +1,3 @@
import 'external1';

console.log('main');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/external-dependency-names/main2a.js
@@ -0,0 +1,3 @@
import 'external';

console.log('main');
3 changes: 3 additions & 0 deletions test/file-hashes/samples/external-dependency-names/main2b.js
@@ -0,0 +1,3 @@
import 'external2';

console.log('main');
15 changes: 15 additions & 0 deletions test/file-hashes/samples/footer/_config.js
@@ -0,0 +1,15 @@
module.exports = {
description: 'creates different hashes if the footer differs',
options1: {
input: 'main',
output: {
footer: 'console.log(1);'
}
},
options2: {
input: 'main',
output: {
footer: 'console.log(2);'
}
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/footer/main.js
@@ -0,0 +1 @@
console.log('main');
15 changes: 15 additions & 0 deletions test/file-hashes/samples/format/_config.js
@@ -0,0 +1,15 @@
module.exports = {
description: 'creates different hashes if the format differs',
options1: {
input: 'main',
output: {
format: 'esm'
}
},
options2: {
input: 'main',
output: {
format: 'cjs'
}
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/format/main.js
@@ -0,0 +1 @@
export const x = 1;
15 changes: 15 additions & 0 deletions test/file-hashes/samples/intro/_config.js
@@ -0,0 +1,15 @@
module.exports = {
description: 'creates different hashes if the intro differs',
options1: {
input: 'main',
output: {
intro: 'console.log(1);'
}
},
options2: {
input: 'main',
output: {
intro: 'console.log(2);'
}
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/intro/main.js
@@ -0,0 +1 @@
console.log('main');
15 changes: 15 additions & 0 deletions test/file-hashes/samples/outro/_config.js
@@ -0,0 +1,15 @@
module.exports = {
description: 'creates different hashes if the outro differs',
options1: {
input: 'main',
output: {
outro: 'console.log(1);'
}
},
options2: {
input: 'main',
output: {
outro: 'console.log(2);'
}
}
};
1 change: 1 addition & 0 deletions test/file-hashes/samples/outro/main.js
@@ -0,0 +1 @@
console.log('main');