Skip to content

Commit

Permalink
Fix integrity calculation, fixes #126
Browse files Browse the repository at this point in the history
  • Loading branch information
karolyi committed Jul 28, 2024
1 parent 4596d47 commit 87151dc
Showing 1 changed file with 66 additions and 56 deletions.
122 changes: 66 additions & 56 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@
/** @typedef {import("lodash.assign")} assign */
/** @typedef {import("lodash.get")} get */
/** @typedef {import("webpack").Compiler} Compiler */
/** @typedef {import("webpack").AssetEmittedInfo} AssetEmittedInfo */
/** @typedef {import("webpack").Stats} Stats */
/** @typedef {import("webpack").compilation.Compilation} Compilation */
/** @typedef {import("webpack").compilation.ContextModuleFactory} ContextModuleFactory */
/** @typedef {import("webpack").ChunkData} ChunkData */
/** @typedef {import("../typings").Contents} Contents */
/** @typedef {import("../typings").Options} Options */
/** @typedef {Contents['assets']} ContentsAssets */
/** @typedef {ContentsAssets[keyof ContentsAssets]} ContentsAssetsValue */

const path = require('path');
const fs = require('fs');
Expand All @@ -26,11 +29,6 @@ function getAssetPath(compilation, name) {
return path.join(compilation.getPath(compilation.compiler.outputPath), name.split('?')[0]);
}

function getSource(compilation, name) {
const path = getAssetPath(compilation, name);
return fs.readFileSync(path, { encoding: 'utf-8' });
}

/**
* Merges the provided objects, ensuring that the resulting object has its properties in sorted order.
* @template T
Expand Down Expand Up @@ -61,6 +59,8 @@ class BundleTrackerPlugin {
chunks: {},
};
this.name = 'BundleTrackerPlugin';
/** @type {Contents} */
this._iter_output = { status: 'compile', assets: {}, chunks: {} }

this.outputChunkDir = '';
this.outputTrackerFile = '';
Expand All @@ -84,7 +84,10 @@ class BundleTrackerPlugin {
integrityHashes: ['sha256', 'sha384', 'sha512'],
});

if (this.options.filename?.includes('/')) {
if (
typeof this.options.filename === 'string' &&
this.options.filename.includes('/')
) {
throw Error(
"The `filename` shouldn't include a `/`. Please use the `path` parameter to " +
"build the directory path and use `filename` only for the file's name itself.\n" +
Expand All @@ -102,15 +105,14 @@ class BundleTrackerPlugin {
return this;
}
/**
* Write bundle tracker stats file
*
* @param {Compiler} compiler
* @param {Partial<Contents>} contents
* Write bundle tracker stats file, merging the existing content with
* the output from the latest compilation results, back to the
* `this.contents` variable.
*/
_writeOutput(compiler, contents) {
assign(this.contents, contents, {
assets: mergeObjects(this.contents.assets, contents.assets),
chunks: mergeObjects(this.contents.chunks, contents.chunks),
_writeOutput() {
assign(this.contents, this._iter_output, {
assets: mergeObjects(this.contents.assets, this._iter_output.assets),
chunks: mergeObjects(this.contents.chunks, this._iter_output.chunks),
});

if (this.options.publicPath) {
Expand Down Expand Up @@ -143,8 +145,45 @@ class BundleTrackerPlugin {
* @param {Compiler} compiler
*/
_handleCompile(compiler) {
this._writeOutput(compiler, { status: 'compile' });
this._iter_output = { status: 'compile', assets: {}, chunks: {} }
this._writeOutput();
}

/**
* Handle compile hook
* @param {string} compiledFile
* @param {AssetEmittedInfo} compiledDetails
*/
_handleAssetEmitted(compiledFile, compiledDetails) {
/** @type {ContentsAssetsValue} */
const thisFile = {
name: compiledFile,
path: compiledDetails.targetPath
}
if (this.options.integrity === true) {
thisFile.integrity = this._computeIntegrity(compiledDetails.content);
}
if (this.options.publicPath) {
if (this.options.publicPath === 'auto') {
thisFile.publicPath = 'auto';
} else {
thisFile.publicPath = this.options.publicPath + compiledFile;
}
}
if (this.options.relativePath === true) {
thisFile.path = path.relative(this.outputChunkDir, thisFile.path);
}
/** @type {Compilation} */
const compilation = compiledDetails.compilation
// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
if (compilation.assetsInfo) {
// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
thisFile.sourceFilename =
compilation.assetsInfo.get(compiledFile).sourceFilename;
}
this._iter_output.assets[compiledFile] = thisFile
}

/**
* Handle compile hook
* @param {Compiler} compiler
Expand All @@ -159,68 +198,39 @@ class BundleTrackerPlugin {
return compilation.children.find(child => findError(child));
};
const error = findError(stats.compilation);
this._writeOutput(compiler, {
this._iter_output = {
status: 'error',
error: get(error, 'name', 'unknown-error'),
message: stripAnsi(error['message']),
});
assets: {}, chunks: {}
}
this._writeOutput();

return;
}

/** @type {Contents} */
const output = { status: 'done', assets: {}, chunks: {} };
each(stats.compilation.assets, (file, assetName) => {
const fileInfo = {
name: assetName,
path: getAssetPath(stats.compilation, assetName),
};

if (this.options.integrity === true) {
fileInfo.integrity = this._computeIntegrity(getSource(stats.compilation, assetName));
}

if (this.options.publicPath) {
if (this.options.publicPath === 'auto') {
fileInfo.publicPath = 'auto';
} else {
fileInfo.publicPath = this.options.publicPath + assetName;
}
}

if (this.options.relativePath === true) {
fileInfo.path = path.relative(this.outputChunkDir, fileInfo.path);
}

// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
if (stats.compilation.assetsInfo) {
// @ts-ignore: TS2339: Property 'assetsInfo' does not exist on type 'Compilation'.
fileInfo.sourceFilename = stats.compilation.assetsInfo.get(assetName).sourceFilename;
}

output.assets[assetName] = fileInfo;
});
each(stats.compilation.chunkGroups, chunkGroup => {
if (!chunkGroup.isInitial()) return;

output.chunks[chunkGroup.name] = chunkGroup.getFiles();
this._iter_output.chunks[chunkGroup.name] = chunkGroup.getFiles();
});

if (this.options.logTime === true) {
output.startTime = stats.startTime;
output.endTime = stats.endTime;
this._iter_output.startTime = stats.startTime;
this._iter_output.endTime = stats.endTime;
}

this._writeOutput(compiler, output);
this._iter_output.status = 'done'
this._writeOutput();
}

/**
* Method called by webpack to apply plugin hook
* @param {Compiler} compiler
*/
apply(compiler) {
this._setParamsFromCompiler(compiler);

// In order of hook calls:
compiler.hooks.compile.tap(this.name, this._handleCompile.bind(this, compiler));
compiler.hooks.assetEmitted.tap(this.name, this._handleAssetEmitted.bind(this));
compiler.hooks.done.tap(this.name, this._handleDone.bind(this, compiler));
}
}
Expand Down

0 comments on commit 87151dc

Please sign in to comment.