hard-source-webpack-plugin
hard-source-webpack-plugin copied to clipboard
archetype=Asset freezing bug, stores non-JSON string into cache
I'm seeing a bug using this plugin with webpack 3 --watch.
When freezing an asset (for example, from emitFile) the value to be frozen is a string, so a non-JSON string is stored into cache. When cache attempts to retrieve and parse this value as JSON, it throws an error.
Detailed breakdown of the flow through code:
store()...
https://github.com/mzgoddard/hard-source-webpack-plugin/blob/master/index.js#L1561-L1565
...calls freeze():
https://github.com/mzgoddard/hard-source-webpack-plugin/blob/master/index.js#L1519-L1529
...which triggers '_hardSourceFreezeAsset', which is tapped here:
https://github.com/mzgoddard/hard-source-webpack-plugin/blob/master/lib/hard-asset-plugin.js#L9
It calls asset.source() which returns a string according to the docs:
https://github.com/webpack/webpack-sources#source-1
Back in store(), the result of calling freeze() (a string) is passed to cache.set()
This cached value is a string of the asset's source code.
Later, when we try to retrieve that cached value via cache.get(), it attempts to JSON.parse the string, but the string is not valid JSON, so I see an error:
https://github.com/mzgoddard/hard-source-webpack-plugin/blob/master/index.js#L1409-L1410
I think this a logic error but I'm not sure what the intended behavior is because the codebase doesn't have any sort of type annotations. Can someone help me debug and write a PR to fix this behavior?
I'm using this as a workaround, but I'm not 100% sure it's working:
class HardSourceFixBug {
apply(compiler) {
compiler.plugin('_hardSourceAfterFreezeAsset', (frozen, item, extra) => {
if(typeof frozen === 'string') {
console.log('WRAPPING string in FROZEN WRAPPER');
return {___frozenString: true, ___frozenStringValue: frozen};
}
return frozen;
});
compiler.plugin('_hardSourceBeforeThawAsset', (thawed, asset, extra) => {
if (!thawed) {
thawed = asset;
if(thawed && thawed.___frozenString) {
thawed = thawed.___frozenStringValue;
}
if (thawed.type === 'buffer') {
thawed = new Buffer(thawed);
}
if (!(thawed instanceof RawSource)) {
thawed = new RawSource(thawed);
}
}
return thawed;
});
}
}