@parcel/core
Advanced tools
Comparing version 2.0.0-nightly.171 to 2.0.0-nightly.175
@@ -19,2 +19,4 @@ "use strict"; | ||
var _nullthrows = _interopRequireDefault(require("nullthrows")); | ||
var _Graph = _interopRequireDefault(require("./Graph")); | ||
@@ -93,3 +95,5 @@ | ||
static deserialize(opts) { | ||
let res = new AssetGraph(opts); | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
let res = new AssetGraph(opts); // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
res.incompleteNodeIds = opts.incompleteNodeIds; | ||
@@ -102,2 +106,3 @@ res.hash = opts.hash; | ||
serialize() { | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
return _objectSpread({}, super.serialize(), { | ||
@@ -319,3 +324,3 @@ incompleteNodeIds: this.incompleteNodeIds, | ||
if (node.type === 'asset') { | ||
hash.update(node.value.outputHash); | ||
hash.update((0, _nullthrows.default)(node.value.outputHash)); | ||
} else if (node.type === 'dependency' && node.value.target) { | ||
@@ -322,0 +327,0 @@ hash.update(JSON.stringify(node.value.target)); |
@@ -257,3 +257,4 @@ "use strict"; | ||
(0, _dumpGraphToGraphViz.default)(this.assetGraph, 'AssetGraph'); | ||
(0, _dumpGraphToGraphViz.default)(this.assetGraph, 'AssetGraph'); // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
(0, _dumpGraphToGraphViz.default)(this.requestGraph, 'RequestGraph'); | ||
@@ -260,0 +261,0 @@ let changedAssets = this.changedAssets; |
@@ -504,3 +504,3 @@ "use strict"; | ||
this.traverseAssets(bundle, asset => { | ||
hash.update([asset.outputHash, asset.filePath].join(':')); | ||
hash.update([asset.outputHash, asset.filePath, asset.type, asset.uniqueKey].join(':')); | ||
}); | ||
@@ -507,0 +507,0 @@ let hashHex = hash.digest('hex'); |
@@ -9,6 +9,6 @@ "use strict"; | ||
var _v = _interopRequireDefault(require("v8")); | ||
var _stream = require("stream"); | ||
var _crypto = _interopRequireDefault(require("crypto")); | ||
var _sourceMap = _interopRequireDefault(require("@parcel/source-map")); | ||
@@ -18,2 +18,4 @@ | ||
var _nullthrows = _interopRequireDefault(require("nullthrows")); | ||
var _Dependency = require("./Dependency"); | ||
@@ -25,2 +27,10 @@ | ||
var _loadParcelPlugin = _interopRequireDefault(require("./loadParcelPlugin")); | ||
var _PluginOptions = _interopRequireDefault(require("./public/PluginOptions")); | ||
var _Asset = require("./public/Asset"); | ||
var _logger = require("@parcel/logger"); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
@@ -51,6 +61,8 @@ | ||
mapKey: options.mapKey, | ||
astKey: options.astKey, | ||
astGenerator: options.astGenerator, | ||
dependencies: options.dependencies || new Map(), | ||
includedFiles: options.includedFiles || new Map(), | ||
isSource: options.isSource, | ||
outputHash: options.outputHash || '', | ||
outputHash: options.outputHash, | ||
pipeline: options.pipeline, | ||
@@ -62,3 +74,5 @@ env: options.env, | ||
sideEffects: options.sideEffects != null ? options.sideEffects : true, | ||
uniqueKey: uniqueKey | ||
uniqueKey: uniqueKey, | ||
plugin: options.plugin, | ||
configPath: options.configPath | ||
}; | ||
@@ -74,2 +88,3 @@ } | ||
ast, | ||
isASTDirty, | ||
idBase | ||
@@ -87,9 +102,14 @@ }) { | ||
_defineProperty(this, "isASTDirty", void 0); | ||
_defineProperty(this, "idBase", void 0); | ||
_defineProperty(this, "generatingPromise", void 0); | ||
this.value = value; | ||
this.options = options; | ||
this.content = content || ''; | ||
this.content = content; | ||
this.mapBuffer = mapBuffer; | ||
this.ast = ast; | ||
this.isASTDirty = isASTDirty || false; | ||
this.idBase = idBase; | ||
@@ -104,53 +124,107 @@ } | ||
async commit(pipelineKey) { | ||
this.ast = null; | ||
let contentStream = this.getStream(); | ||
if ( // $FlowFixMe | ||
typeof contentStream.bytesRead === 'number' && // If the amount of data read from this stream so far isn't exactly the amount | ||
// of data that is available to be read, then it has been read from. | ||
contentStream.bytesRead !== contentStream.readableLength) { | ||
throw new Error('Stream has already been read. This may happen if a plugin reads from a stream and does not replace it.'); | ||
// If there is a dirty AST, clear out any old content and map as these | ||
// must be regenerated later and shouldn't be committed. | ||
if (this.ast != null && this.isASTDirty) { | ||
this.content = null; | ||
this.mapBuffer = null; | ||
} | ||
let size = 0; | ||
let hash = _crypto.default.createHash('md5'); // Since we can only read from the stream once, compute the content length | ||
let contentKey = this.content == null ? null : this.getCacheKey('content' + pipelineKey); | ||
let mapKey = this.mapBuffer == null ? null : this.getCacheKey('map' + pipelineKey); | ||
let astKey = this.ast == null ? null : this.getCacheKey('ast' + pipelineKey); // Since we can only read from the stream once, compute the content length | ||
// and hash while it's being written to the cache. | ||
let [contentKey, mapKey] = await Promise.all([this.options.cache.setStream(this.getCacheKey('content' + pipelineKey), contentStream.pipe(new _utils.TapStream(buf => { | ||
await Promise.all([contentKey == null ? Promise.resolve() : this.options.cache.setStream(contentKey, this.getStream().pipe(new _utils.TapStream(buf => { | ||
size += buf.length; | ||
hash.update(buf); | ||
}))), this.mapBuffer == null ? Promise.resolve() : this.options.cache.setBlob(this.getCacheKey('map' + pipelineKey), // $FlowFixMe strange that this occurs | ||
this.mapBuffer)]); | ||
}))), this.mapBuffer == null || mapKey == null ? Promise.resolve() : this.options.cache.setBlob(mapKey, this.mapBuffer), astKey == null ? Promise.resolve() : this.options.cache.setBlob(astKey, // $FlowFixMe | ||
_v.default.serialize(this.ast))]); | ||
this.value.contentKey = contentKey; | ||
this.value.mapKey = mapKey; | ||
this.value.stats.size = size; | ||
this.value.outputHash = hash.digest('hex'); | ||
this.value.astKey = astKey; | ||
this.value.outputHash = (0, _utils.md5FromString)([this.value.hash, pipelineKey].join(':')); // TODO: how should we set the size when we only store an AST? | ||
if (this.content != null) { | ||
this.value.stats.size = size; | ||
} | ||
} | ||
async generateFromAST() { | ||
if (this.generatingPromise == null) { | ||
this.generatingPromise = this._generateFromAST(); | ||
} | ||
await this.generatingPromise; | ||
return this.content || ''; | ||
} | ||
async _generateFromAST() { | ||
let ast = await this.getAST(); | ||
if (ast == null) { | ||
throw new Error('Asset has no AST'); | ||
} | ||
let pluginName = (0, _nullthrows.default)(this.value.plugin); | ||
let plugin = await (0, _loadParcelPlugin.default)(this.options.packageManager, pluginName, (0, _nullthrows.default)(this.value.configPath)); | ||
if (!plugin.generate) { | ||
throw new Error(`${pluginName} does not have a generate method`); | ||
} | ||
let { | ||
code, | ||
map | ||
} = await plugin.generate({ | ||
asset: new _Asset.Asset(this), | ||
ast, | ||
options: new _PluginOptions.default(this.options), | ||
logger: new _logger.PluginLogger({ | ||
origin: pluginName | ||
}) | ||
}); | ||
this.content = code; | ||
let mapBuffer = this.mapBuffer = map === null || map === void 0 ? void 0 : map.toBuffer(); // Store the results in the cache so we can avoid generating again next time | ||
await Promise.all([this.options.cache.setStream((0, _nullthrows.default)(this.value.contentKey), this.getStream()), mapBuffer == null ? Promise.resolve() : this.options.cache.setBlob((0, _nullthrows.default)(this.value.mapKey), mapBuffer)]); | ||
} | ||
ensureContent() { | ||
let contentKey = this.value.contentKey; | ||
if (contentKey != null && this.content == null) { | ||
// First try the contentKey, and if it doesn't exist, fall back to generating from AST | ||
this.content = (0, _utils.fallbackStream)(this.options.cache.getStream(contentKey), () => (0, _utils.streamFromPromise)(this.generateFromAST())); | ||
} | ||
} | ||
async getCode() { | ||
if (this.value.contentKey != null) { | ||
this.content = this.options.cache.getStream(this.value.contentKey); | ||
if (this.ast != null && this.isASTDirty) { | ||
throw new Error('Cannot call getCode() on an asset with a dirty AST. For transformers, implement canReuseAST() and check asset.isASTDirty.'); | ||
} | ||
if (typeof this.content === 'string' || this.content instanceof Buffer) { | ||
this.content = this.content.toString(); | ||
} else { | ||
this.content = (await (0, _utils.bufferStream)(this.content)).toString(); | ||
this.ensureContent(); | ||
let content = await this.content; | ||
if (typeof content === 'string' || content instanceof Buffer) { | ||
return content.toString(); | ||
} else if (content != null) { | ||
this.content = (0, _utils.bufferStream)(content); | ||
return (await this.content).toString(); | ||
} | ||
return this.content; | ||
return ''; | ||
} | ||
async getBuffer() { | ||
if (this.value.contentKey != null) { | ||
this.content = this.options.cache.getStream(this.value.contentKey); | ||
} | ||
this.ensureContent(); | ||
let content = await this.content; | ||
if (typeof this.content === 'string' || this.content instanceof Buffer) { | ||
return Buffer.from(this.content); | ||
if (content == null) { | ||
return Buffer.alloc(0); | ||
} else if (typeof content === 'string' || content instanceof Buffer) { | ||
return Buffer.from(content); | ||
} | ||
this.content = await (0, _utils.bufferStream)(this.content); | ||
this.content = (0, _utils.bufferStream)(content); | ||
return this.content; | ||
@@ -160,7 +234,16 @@ } | ||
getStream() { | ||
if (this.value.contentKey != null) { | ||
this.content = this.options.cache.getStream(this.value.contentKey); | ||
this.ensureContent(); | ||
let content = this.content; | ||
if (content instanceof _stream.Readable) { | ||
// Remove content if it's a stream, as it should not be reused. | ||
this.content = null; | ||
return content; | ||
} | ||
return (0, _utils.blobToStream)(this.content); | ||
if (content instanceof Promise) { | ||
return (0, _utils.streamFromPromise)(content); | ||
} | ||
return (0, _utils.blobToStream)(content !== null && content !== void 0 ? content : Buffer.alloc(0)); | ||
} | ||
@@ -170,2 +253,3 @@ | ||
this.content = code; | ||
this.clearAST(); | ||
} | ||
@@ -175,2 +259,3 @@ | ||
this.content = buffer; | ||
this.clearAST(); | ||
} | ||
@@ -180,7 +265,16 @@ | ||
this.content = stream; | ||
this.clearAST(); | ||
} | ||
async getMapBuffer() { | ||
if (!this.mapBuffer && this.value.mapKey != null) { | ||
this.mapBuffer = await this.options.cache.getBlob(this.value.mapKey); | ||
if (this.value.mapKey != null && this.mapBuffer == null) { | ||
try { | ||
this.mapBuffer = await this.options.cache.getBlob(this.value.mapKey); | ||
} catch (err) { | ||
if (err.code === 'ENOENT' && this.value.astKey != null) { | ||
await this.generateFromAST(); | ||
} else { | ||
throw err; | ||
} | ||
} | ||
} | ||
@@ -192,10 +286,10 @@ | ||
async getMap() { | ||
if (!this.mapBuffer) { | ||
await this.getMapBuffer(); | ||
} | ||
var _this$mapBuffer; | ||
if (this.mapBuffer) { | ||
let mapBuffer = (_this$mapBuffer = this.mapBuffer) !== null && _this$mapBuffer !== void 0 ? _this$mapBuffer : await this.getMapBuffer(); | ||
if (mapBuffer) { | ||
// Get sourcemap from flatbuffer | ||
let map = new _sourceMap.default(); | ||
map.addBufferMappings(this.mapBuffer); | ||
map.addBufferMappings(mapBuffer); | ||
return map; | ||
@@ -211,2 +305,30 @@ } | ||
async getAST() { | ||
if (this.value.astKey != null) { | ||
let serializedAst = await this.options.cache.getBlob(this.value.astKey); | ||
if (serializedAst != null) { | ||
// $FlowFixMe | ||
this.ast = _v.default.deserialize(serializedAst); | ||
} | ||
} | ||
return this.ast; | ||
} | ||
setAST(ast) { | ||
this.ast = ast; | ||
this.isASTDirty = true; | ||
this.value.astGenerator = { | ||
type: ast.type, | ||
version: ast.version | ||
}; | ||
} | ||
clearAST() { | ||
this.ast = null; | ||
this.isASTDirty = false; | ||
this.value.astGenerator = null; | ||
} | ||
getCacheKey(key) { | ||
@@ -252,24 +374,10 @@ return (0, _utils.md5FromString)(_constants.PARCEL_VERSION + key + this.value.id + (this.value.hash || '')); | ||
createChildAsset(result) { | ||
createChildAsset(result, plugin, configPath) { | ||
var _ref, _result$content, _result$isIsolated, _result$isInline, _result$isSplittable, _result$isSource, _result$pipeline, _result$sideEffects; | ||
let content = (_ref = (_result$content = result.content) !== null && _result$content !== void 0 ? _result$content : result.code) !== null && _ref !== void 0 ? _ref : ''; | ||
let hash; | ||
let size; | ||
if (content === this.content) { | ||
hash = this.value.hash; | ||
size = this.value.stats.size; | ||
} else if (typeof content === 'string' || content instanceof Buffer) { | ||
hash = (0, _utils.md5FromString)(content); | ||
size = content.length; | ||
} else { | ||
hash = null; | ||
size = NaN; | ||
} | ||
let content = (_ref = (_result$content = result.content) !== null && _result$content !== void 0 ? _result$content : result.code) !== null && _ref !== void 0 ? _ref : null; | ||
let asset = new InternalAsset({ | ||
value: createAsset({ | ||
idBase: this.idBase, | ||
hash, | ||
hash: this.value.hash, | ||
filePath: this.value.filePath, | ||
@@ -288,7 +396,13 @@ type: result.type, | ||
time: 0, | ||
size | ||
size: this.value.stats.size | ||
}, | ||
symbols: new Map([...this.value.symbols, ...(result.symbols || [])]), | ||
sideEffects: (_result$sideEffects = result.sideEffects) !== null && _result$sideEffects !== void 0 ? _result$sideEffects : this.value.sideEffects, | ||
uniqueKey: result.uniqueKey | ||
uniqueKey: result.uniqueKey, | ||
astGenerator: result.ast ? { | ||
type: result.ast.type, | ||
version: result.ast.version | ||
} : null, | ||
plugin, | ||
configPath | ||
}), | ||
@@ -298,2 +412,3 @@ options: this.options, | ||
ast: result.ast, | ||
isASTDirty: result.ast === this.ast ? this.isASTDirty : true, | ||
mapBuffer: result.map ? result.map.toBuffer() : null, | ||
@@ -300,0 +415,0 @@ idBase: this.idBase |
@@ -43,5 +43,4 @@ "use strict"; | ||
return output.parsed; | ||
})); // $FlowFixMe | ||
})); | ||
return Object.assign({}, ...envs); | ||
} |
@@ -80,3 +80,2 @@ "use strict"; | ||
if (pipeline) { | ||
// $FlowFixMe | ||
return pipeline.map(pkg => { | ||
@@ -83,0 +82,0 @@ if (pkg === '...') return pkg; |
@@ -380,6 +380,8 @@ "use strict"; | ||
} = await _classPrivateFieldGet(this, _assetGraphBuilder).build(signal); | ||
(0, _dumpGraphToGraphViz.default)(assetGraph, 'MainAssetGraph'); | ||
(0, _dumpGraphToGraphViz.default)(assetGraph, 'MainAssetGraph'); // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
let bundleGraph = await _classPrivateFieldGet(this, _bundlerRunner).bundle(assetGraph, { | ||
signal | ||
}); | ||
}); // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 (Windows only) | ||
(0, _dumpGraphToGraphViz.default)(bundleGraph._graph, 'BundleGraph'); | ||
@@ -386,0 +388,0 @@ await _classPrivateFieldGet(this, _packagerRunner).writeBundles(bundleGraph); |
@@ -65,6 +65,2 @@ "use strict"; | ||
get ast() { | ||
return _classPrivateFieldGet(this, _asset).ast; | ||
} | ||
get type() { | ||
@@ -118,2 +114,6 @@ return _classPrivateFieldGet(this, _asset).value.type; | ||
get astGenerator() { | ||
return _classPrivateFieldGet(this, _asset).value.astGenerator; | ||
} | ||
getConfig(filePaths, options) { | ||
@@ -151,2 +151,6 @@ return _classPrivateFieldGet(this, _asset).getConfig(filePaths, options); | ||
getAST() { | ||
return _classPrivateFieldGet(this, _asset).getAST(); | ||
} | ||
getMapBuffer() { | ||
@@ -181,6 +185,2 @@ return _classPrivateFieldGet(this, _asset).getMapBuffer(); | ||
get outputHash() { | ||
return _classPrivateFieldGet(this, _asset2).value.outputHash; | ||
} | ||
get stats() { | ||
@@ -217,10 +217,2 @@ return _classPrivateFieldGet(this, _asset2).value.stats; | ||
get ast() { | ||
return _classPrivateFieldGet(this, _asset3).ast; | ||
} | ||
set ast(ast) { | ||
_classPrivateFieldGet(this, _asset3).ast = ast; | ||
} | ||
setMap(map) { | ||
@@ -267,5 +259,9 @@ _classPrivateFieldGet(this, _asset3).setMap(map); | ||
addIncludedFile(file) { | ||
return _classPrivateFieldGet(this, _asset3).addIncludedFile(file); | ||
_classPrivateFieldGet(this, _asset3).addIncludedFile(file); | ||
} | ||
isASTDirty() { | ||
return _classPrivateFieldGet(this, _asset3).isASTDirty; | ||
} | ||
setBuffer(buffer) { | ||
@@ -283,2 +279,6 @@ _classPrivateFieldGet(this, _asset3).setBuffer(buffer); | ||
setAST(ast) { | ||
return _classPrivateFieldGet(this, _asset3).setAST(ast); | ||
} | ||
addURLDependency(url, opts) { | ||
@@ -285,0 +285,0 @@ return this.addDependency(_objectSpread({ |
@@ -133,3 +133,2 @@ "use strict"; | ||
} else if (this.isNode() && this.engines.node != null && minVersions.node) { | ||
// $FlowFixMe | ||
return !_semver.default.intersects(`< ${minVersions.node}`, this.engines.node); | ||
@@ -136,0 +135,0 @@ } |
@@ -62,2 +62,3 @@ "use strict"; | ||
static deserialize(opts) { | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
let deserialized = new RequestGraph(opts); | ||
@@ -67,3 +68,3 @@ deserialized.invalidNodeIds = opts.invalidNodeIds; | ||
deserialized.globNodeIds = opts.globNodeIds; | ||
deserialized.unpredicatableNodeIds = opts.unpredicatableNodeIds; // $FlowFixMe | ||
deserialized.unpredicatableNodeIds = opts.unpredicatableNodeIds; // $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 (Windows only) | ||
@@ -70,0 +71,0 @@ return deserialized; |
@@ -44,6 +44,2 @@ "use strict"; | ||
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } | ||
@@ -234,3 +230,3 @@ | ||
let inputAssets = [initialAsset]; | ||
let resultingAssets; | ||
let resultingAssets = []; | ||
let finalAssets = []; | ||
@@ -253,6 +249,6 @@ | ||
try { | ||
let transformerResults = await runTransformer(pipeline, asset, transformer.plugin, transformer.name, transformer.config); | ||
let transformerResults = await runTransformer(pipeline, asset, transformer.plugin, transformer.name, transformer.config, this.parcelConfig); | ||
for (let result of transformerResults) { | ||
resultingAssets.push(asset.createChildAsset(result)); | ||
resultingAssets.push(asset.createChildAsset(result, transformer.name, this.parcelConfig.filePath)); | ||
} | ||
@@ -267,6 +263,25 @@ } catch (e) { | ||
inputAssets = resultingAssets; | ||
} // Make assets with ASTs generate unless they are js assets and target uses | ||
// scope hoisting. This parallelizes generation and distributes work more | ||
// evenly across workers than if one worker needed to generate all assets in | ||
// a large bundle during packaging. | ||
let generate = pipeline.generate; | ||
if (generate != null) { | ||
await Promise.all(resultingAssets.filter(asset => asset.ast != null && !(asset.value.type === 'js' && asset.value.env.scopeHoist)).map(async asset => { | ||
if (asset.isASTDirty) { | ||
var _output$map; | ||
let output = await generate(asset); | ||
asset.content = output.code; | ||
asset.mapBuffer = (_output$map = output.map) === null || _output$map === void 0 ? void 0 : _output$map.toBuffer(); | ||
} | ||
asset.clearAST(); | ||
})); | ||
} | ||
finalAssets = finalAssets.concat(resultingAssets); | ||
return Promise.all(finalAssets.map(asset => finalize((0, _nullthrows.default)(asset), (0, _nullthrows.default)(pipeline.generate)))); | ||
return finalAssets.concat(resultingAssets); | ||
} | ||
@@ -403,3 +418,3 @@ | ||
async function runTransformer(pipeline, asset, transformer, transformerName, preloadedConfig) { | ||
async function runTransformer(pipeline, asset, transformer, transformerName, preloadedConfig, parcelConfig) { | ||
const logger = new _logger.PluginLogger({ | ||
@@ -432,3 +447,3 @@ origin: transformerName | ||
if (asset.ast && (!transformer.canReuseAST || !transformer.canReuseAST({ | ||
if (asset.ast && asset.isASTDirty && (!transformer.canReuseAST || !transformer.canReuseAST({ | ||
ast: asset.ast, | ||
@@ -438,5 +453,7 @@ options: pipeline.pluginOptions, | ||
})) && pipeline.generate) { | ||
let output = await pipeline.generate(new _Asset.MutableAsset(asset)); | ||
var _output$map2; | ||
let output = await pipeline.generate(asset); | ||
asset.content = output.code; | ||
asset.ast = null; | ||
asset.mapBuffer = (_output$map2 = output.map) === null || _output$map2 === void 0 ? void 0 : _output$map2.toBuffer(); | ||
} // Parse if there is no AST available from a previous transform. | ||
@@ -446,3 +463,3 @@ | ||
if (!asset.ast && transformer.parse) { | ||
asset.ast = await transformer.parse({ | ||
let ast = await transformer.parse({ | ||
asset: new _Asset.MutableAsset(asset), | ||
@@ -454,2 +471,7 @@ config, | ||
}); | ||
if (ast) { | ||
asset.setAST(ast); | ||
asset.isASTDirty = false; | ||
} | ||
} // Transform. | ||
@@ -461,2 +483,3 @@ | ||
asset: new _Asset.MutableAsset(asset), | ||
ast: asset.ast, | ||
config, | ||
@@ -469,10 +492,11 @@ options: pipeline.pluginOptions, | ||
pipeline.generate = input => { | ||
if (transformer.generate) { | ||
return Promise.resolve(transformer.generate({ | ||
asset: input, | ||
config, | ||
if (transformer.generate && input.ast) { | ||
let generated = transformer.generate({ | ||
asset: new _Asset.Asset(input), | ||
ast: input.ast, | ||
options: pipeline.pluginOptions, | ||
resolve, | ||
logger | ||
})); | ||
}); | ||
input.clearAST(); | ||
return Promise.resolve(generated); | ||
} | ||
@@ -495,3 +519,3 @@ | ||
}); | ||
return Promise.all(results.map(result => asset.createChildAsset(result))); | ||
return Promise.all(results.map(result => asset.createChildAsset(result, transformerName, parcelConfig.filePath))); | ||
}; | ||
@@ -503,16 +527,4 @@ } | ||
async function finalize(asset, generate) { | ||
if (asset.ast && generate) { | ||
let result = await generate(new _Asset.MutableAsset(asset)); | ||
return asset.createChildAsset(_objectSpread({ | ||
type: asset.value.type, | ||
uniqueKey: asset.value.uniqueKey | ||
}, result)); | ||
} | ||
return asset; | ||
} | ||
function normalizeAssets(results) { | ||
return results.map(result => { | ||
return Promise.all(results.map(async result => { | ||
if (!(result instanceof _Asset.MutableAsset)) { | ||
@@ -525,4 +537,4 @@ return result; | ||
type: result.type, | ||
content: internalAsset.content, | ||
ast: result.ast, | ||
content: await internalAsset.content, | ||
ast: internalAsset.ast, | ||
mapBuffer: internalAsset.mapBuffer, | ||
@@ -540,3 +552,3 @@ // $FlowFixMe | ||
}; | ||
}); | ||
})); | ||
} | ||
@@ -543,0 +555,0 @@ |
@@ -62,3 +62,2 @@ "use strict"; | ||
report: _ReporterRunner.reportWorker.bind(null, workerApi), | ||
// $FlowFixMe | ||
options, | ||
@@ -84,3 +83,2 @@ config | ||
report: _ReporterRunner.reportWorker.bind(null, workerApi), | ||
// $FlowFixMe | ||
options, | ||
@@ -107,3 +105,2 @@ config | ||
config, | ||
// $FlowFixMe | ||
options, | ||
@@ -110,0 +107,0 @@ report: _ReporterRunner.reportWorker.bind(null, workerApi) |
{ | ||
"name": "@parcel/core", | ||
"version": "2.0.0-nightly.171+bac3f05f", | ||
"version": "2.0.0-nightly.175+db7e3a12", | ||
"license": "MIT", | ||
@@ -19,13 +19,13 @@ "publishConfig": { | ||
"dependencies": { | ||
"@parcel/cache": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/diagnostic": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/events": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/fs": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/logger": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/package-manager": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/plugin": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/cache": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/diagnostic": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/events": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/fs": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/logger": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/package-manager": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/plugin": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/source-map": "^2.0.0-alpha.4.3", | ||
"@parcel/types": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/utils": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/workers": "2.0.0-nightly.173+bac3f05f", | ||
"@parcel/types": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/utils": "2.0.0-nightly.177+db7e3a12", | ||
"@parcel/workers": "2.0.0-nightly.177+db7e3a12", | ||
"abortcontroller-polyfill": "^1.1.9", | ||
@@ -46,3 +46,3 @@ "browserslist": "^4.6.6", | ||
}, | ||
"gitHead": "bac3f05fa31574338f14ab9cd2c9bd78fb1c22ee" | ||
"gitHead": "db7e3a12105630abc44058bff7a88eb612f12e75" | ||
} |
@@ -20,2 +20,3 @@ // @flow strict-local | ||
import {md5FromObject} from '@parcel/utils'; | ||
import nullthrows from 'nullthrows'; | ||
import Graph, {type GraphOpts} from './Graph'; | ||
@@ -103,3 +104,5 @@ import {createDependency} from './Dependency'; | ||
static deserialize(opts: SerializedAssetGraph): AssetGraph { | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
let res = new AssetGraph(opts); | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
res.incompleteNodeIds = opts.incompleteNodeIds; | ||
@@ -112,2 +115,3 @@ res.hash = opts.hash; | ||
serialize(): SerializedAssetGraph { | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
return { | ||
@@ -339,3 +343,3 @@ ...super.serialize(), | ||
if (node.type === 'asset') { | ||
hash.update(node.value.outputHash); | ||
hash.update(nullthrows(node.value.outputHash)); | ||
} else if (node.type === 'dependency' && node.value.target) { | ||
@@ -342,0 +346,0 @@ hash.update(JSON.stringify(node.value.target)); |
@@ -246,2 +246,3 @@ // @flow strict-local | ||
dumpToGraphViz(this.assetGraph, 'AssetGraph'); | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
dumpToGraphViz(this.requestGraph, 'RequestGraph'); | ||
@@ -248,0 +249,0 @@ |
@@ -617,3 +617,7 @@ // @flow strict-local | ||
this.traverseAssets(bundle, asset => { | ||
hash.update([asset.outputHash, asset.filePath].join(':')); | ||
hash.update( | ||
[asset.outputHash, asset.filePath, asset.type, asset.uniqueKey].join( | ||
':', | ||
), | ||
); | ||
}); | ||
@@ -620,0 +624,0 @@ |
@@ -5,2 +5,3 @@ // @flow strict-local | ||
AST, | ||
ASTGenerator, | ||
Blob, | ||
@@ -13,4 +14,6 @@ ConfigResult, | ||
PackageJSON, | ||
PackageName, | ||
Stats, | ||
Symbol, | ||
Transformer, | ||
TransformerResult, | ||
@@ -20,4 +23,4 @@ } from '@parcel/types'; | ||
import v8 from 'v8'; | ||
import {Readable} from 'stream'; | ||
import crypto from 'crypto'; | ||
import SourceMap from '@parcel/source-map'; | ||
@@ -29,7 +32,14 @@ import { | ||
blobToStream, | ||
streamFromPromise, | ||
fallbackStream, | ||
TapStream, | ||
} from '@parcel/utils'; | ||
import nullthrows from 'nullthrows'; | ||
import {createDependency, mergeDependencies} from './Dependency'; | ||
import {mergeEnvironments, getEnvironmentHash} from './Environment'; | ||
import {PARCEL_VERSION} from './constants'; | ||
import loadPlugin from './loadParcelPlugin'; | ||
import PluginOptions from './public/PluginOptions'; | ||
import {Asset as PublicAsset} from './public/Asset'; | ||
import {PluginLogger} from '@parcel/logger'; | ||
@@ -44,2 +54,4 @@ type AssetOptions = {| | ||
mapKey?: ?string, | ||
astKey?: ?string, | ||
astGenerator?: ?ASTGenerator, | ||
dependencies?: Map<string, Dependency>, | ||
@@ -51,5 +63,5 @@ includedFiles?: Map<FilePath, File>, | ||
isSource: boolean, | ||
outputHash?: string, | ||
env: Environment, | ||
meta?: Meta, | ||
outputHash?: ?string, | ||
pipeline?: ?string, | ||
@@ -60,2 +72,4 @@ stats: Stats, | ||
uniqueKey?: ?string, | ||
plugin?: PackageName, | ||
configPath?: FilePath, | ||
|}; | ||
@@ -81,6 +95,8 @@ | ||
mapKey: options.mapKey, | ||
astKey: options.astKey, | ||
astGenerator: options.astGenerator, | ||
dependencies: options.dependencies || new Map(), | ||
includedFiles: options.includedFiles || new Map(), | ||
isSource: options.isSource, | ||
outputHash: options.outputHash || '', | ||
outputHash: options.outputHash, | ||
pipeline: options.pipeline, | ||
@@ -93,2 +109,4 @@ env: options.env, | ||
uniqueKey: uniqueKey, | ||
plugin: options.plugin, | ||
configPath: options.configPath, | ||
}; | ||
@@ -100,5 +118,6 @@ } | ||
options: ParcelOptions, | ||
content?: Blob, | ||
content?: ?(Blob | Promise<Buffer>), | ||
mapBuffer?: ?Buffer, | ||
ast?: ?AST, | ||
isASTDirty?: ?boolean, | ||
idBase?: ?string, | ||
@@ -110,6 +129,8 @@ |}; | ||
options: ParcelOptions; | ||
content: Blob; | ||
content: ?(Blob | Promise<Buffer>); | ||
mapBuffer: ?Buffer; | ||
ast: ?AST; | ||
isASTDirty: boolean; | ||
idBase: ?string; | ||
generatingPromise: ?Promise<void>; | ||
@@ -122,2 +143,3 @@ constructor({ | ||
ast, | ||
isASTDirty, | ||
idBase, | ||
@@ -127,5 +149,6 @@ }: InternalAssetOptions) { | ||
this.options = options; | ||
this.content = content || ''; | ||
this.content = content; | ||
this.mapBuffer = mapBuffer; | ||
this.ast = ast; | ||
this.isASTDirty = isASTDirty || false; | ||
this.idBase = idBase; | ||
@@ -139,38 +162,39 @@ } | ||
async commit(pipelineKey: string): Promise<void> { | ||
this.ast = null; | ||
let contentStream = this.getStream(); | ||
if ( | ||
// $FlowFixMe | ||
typeof contentStream.bytesRead === 'number' && | ||
// If the amount of data read from this stream so far isn't exactly the amount | ||
// of data that is available to be read, then it has been read from. | ||
contentStream.bytesRead !== contentStream.readableLength | ||
) { | ||
throw new Error( | ||
'Stream has already been read. This may happen if a plugin reads from a stream and does not replace it.', | ||
); | ||
// If there is a dirty AST, clear out any old content and map as these | ||
// must be regenerated later and shouldn't be committed. | ||
if (this.ast != null && this.isASTDirty) { | ||
this.content = null; | ||
this.mapBuffer = null; | ||
} | ||
let size = 0; | ||
let hash = crypto.createHash('md5'); | ||
let contentKey = | ||
this.content == null ? null : this.getCacheKey('content' + pipelineKey); | ||
let mapKey = | ||
this.mapBuffer == null ? null : this.getCacheKey('map' + pipelineKey); | ||
let astKey = | ||
this.ast == null ? null : this.getCacheKey('ast' + pipelineKey); | ||
// Since we can only read from the stream once, compute the content length | ||
// and hash while it's being written to the cache. | ||
let [contentKey, mapKey] = await Promise.all([ | ||
this.options.cache.setStream( | ||
this.getCacheKey('content' + pipelineKey), | ||
contentStream.pipe( | ||
new TapStream(buf => { | ||
size += buf.length; | ||
hash.update(buf); | ||
}), | ||
), | ||
), | ||
this.mapBuffer == null | ||
await Promise.all([ | ||
contentKey == null | ||
? Promise.resolve() | ||
: this.options.cache.setStream( | ||
contentKey, | ||
this.getStream().pipe( | ||
new TapStream(buf => { | ||
size += buf.length; | ||
}), | ||
), | ||
), | ||
this.mapBuffer == null || mapKey == null | ||
? Promise.resolve() | ||
: this.options.cache.setBlob(mapKey, this.mapBuffer), | ||
astKey == null | ||
? Promise.resolve() | ||
: this.options.cache.setBlob( | ||
this.getCacheKey('map' + pipelineKey), | ||
// $FlowFixMe strange that this occurs | ||
this.mapBuffer, | ||
astKey, | ||
// $FlowFixMe | ||
v8.serialize(this.ast), | ||
), | ||
@@ -180,30 +204,102 @@ ]); | ||
this.value.mapKey = mapKey; | ||
this.value.stats.size = size; | ||
this.value.outputHash = hash.digest('hex'); | ||
this.value.astKey = astKey; | ||
this.value.outputHash = md5FromString( | ||
[this.value.hash, pipelineKey].join(':'), | ||
); | ||
// TODO: how should we set the size when we only store an AST? | ||
if (this.content != null) { | ||
this.value.stats.size = size; | ||
} | ||
} | ||
async generateFromAST() { | ||
if (this.generatingPromise == null) { | ||
this.generatingPromise = this._generateFromAST(); | ||
} | ||
await this.generatingPromise; | ||
return this.content || ''; | ||
} | ||
async _generateFromAST() { | ||
let ast = await this.getAST(); | ||
if (ast == null) { | ||
throw new Error('Asset has no AST'); | ||
} | ||
let pluginName = nullthrows(this.value.plugin); | ||
let plugin: Transformer = await loadPlugin( | ||
this.options.packageManager, | ||
pluginName, | ||
nullthrows(this.value.configPath), | ||
); | ||
if (!plugin.generate) { | ||
throw new Error(`${pluginName} does not have a generate method`); | ||
} | ||
let {code, map} = await plugin.generate({ | ||
asset: new PublicAsset(this), | ||
ast, | ||
options: new PluginOptions(this.options), | ||
logger: new PluginLogger({origin: pluginName}), | ||
}); | ||
this.content = code; | ||
let mapBuffer = (this.mapBuffer = map?.toBuffer()); | ||
// Store the results in the cache so we can avoid generating again next time | ||
await Promise.all([ | ||
this.options.cache.setStream( | ||
nullthrows(this.value.contentKey), | ||
this.getStream(), | ||
), | ||
mapBuffer == null | ||
? Promise.resolve() | ||
: this.options.cache.setBlob(nullthrows(this.value.mapKey), mapBuffer), | ||
]); | ||
} | ||
ensureContent() { | ||
let contentKey = this.value.contentKey; | ||
if (contentKey != null && this.content == null) { | ||
// First try the contentKey, and if it doesn't exist, fall back to generating from AST | ||
this.content = fallbackStream( | ||
this.options.cache.getStream(contentKey), | ||
() => streamFromPromise(this.generateFromAST()), | ||
); | ||
} | ||
} | ||
async getCode(): Promise<string> { | ||
if (this.value.contentKey != null) { | ||
this.content = this.options.cache.getStream(this.value.contentKey); | ||
if (this.ast != null && this.isASTDirty) { | ||
throw new Error( | ||
'Cannot call getCode() on an asset with a dirty AST. For transformers, implement canReuseAST() and check asset.isASTDirty.', | ||
); | ||
} | ||
if (typeof this.content === 'string' || this.content instanceof Buffer) { | ||
this.content = this.content.toString(); | ||
} else { | ||
this.content = (await bufferStream(this.content)).toString(); | ||
this.ensureContent(); | ||
let content = await this.content; | ||
if (typeof content === 'string' || content instanceof Buffer) { | ||
return content.toString(); | ||
} else if (content != null) { | ||
this.content = bufferStream(content); | ||
return (await this.content).toString(); | ||
} | ||
return this.content; | ||
return ''; | ||
} | ||
async getBuffer(): Promise<Buffer> { | ||
if (this.value.contentKey != null) { | ||
this.content = this.options.cache.getStream(this.value.contentKey); | ||
} | ||
this.ensureContent(); | ||
let content = await this.content; | ||
if (typeof this.content === 'string' || this.content instanceof Buffer) { | ||
return Buffer.from(this.content); | ||
if (content == null) { | ||
return Buffer.alloc(0); | ||
} else if (typeof content === 'string' || content instanceof Buffer) { | ||
return Buffer.from(content); | ||
} | ||
this.content = await bufferStream(this.content); | ||
this.content = bufferStream(content); | ||
return this.content; | ||
@@ -213,7 +309,16 @@ } | ||
getStream(): Readable { | ||
if (this.value.contentKey != null) { | ||
this.content = this.options.cache.getStream(this.value.contentKey); | ||
this.ensureContent(); | ||
let content = this.content; | ||
if (content instanceof Readable) { | ||
// Remove content if it's a stream, as it should not be reused. | ||
this.content = null; | ||
return content; | ||
} | ||
return blobToStream(this.content); | ||
if (content instanceof Promise) { | ||
return streamFromPromise(content); | ||
} | ||
return blobToStream(content ?? Buffer.alloc(0)); | ||
} | ||
@@ -223,2 +328,3 @@ | ||
this.content = code; | ||
this.clearAST(); | ||
} | ||
@@ -228,2 +334,3 @@ | ||
this.content = buffer; | ||
this.clearAST(); | ||
} | ||
@@ -233,7 +340,16 @@ | ||
this.content = stream; | ||
this.clearAST(); | ||
} | ||
async getMapBuffer(): Promise<?Buffer> { | ||
if (!this.mapBuffer && this.value.mapKey != null) { | ||
this.mapBuffer = await this.options.cache.getBlob(this.value.mapKey); | ||
if (this.value.mapKey != null && this.mapBuffer == null) { | ||
try { | ||
this.mapBuffer = await this.options.cache.getBlob(this.value.mapKey); | ||
} catch (err) { | ||
if (err.code === 'ENOENT' && this.value.astKey != null) { | ||
await this.generateFromAST(); | ||
} else { | ||
throw err; | ||
} | ||
} | ||
} | ||
@@ -245,10 +361,7 @@ | ||
async getMap(): Promise<?SourceMap> { | ||
if (!this.mapBuffer) { | ||
await this.getMapBuffer(); | ||
} | ||
if (this.mapBuffer) { | ||
let mapBuffer = this.mapBuffer ?? (await this.getMapBuffer()); | ||
if (mapBuffer) { | ||
// Get sourcemap from flatbuffer | ||
let map = new SourceMap(); | ||
map.addBufferMappings(this.mapBuffer); | ||
map.addBufferMappings(mapBuffer); | ||
return map; | ||
@@ -264,2 +377,29 @@ } | ||
async getAST(): Promise<?AST> { | ||
if (this.value.astKey != null) { | ||
let serializedAst = await this.options.cache.getBlob(this.value.astKey); | ||
if (serializedAst != null) { | ||
// $FlowFixMe | ||
this.ast = v8.deserialize(serializedAst); | ||
} | ||
} | ||
return this.ast; | ||
} | ||
setAST(ast: AST): void { | ||
this.ast = ast; | ||
this.isASTDirty = true; | ||
this.value.astGenerator = { | ||
type: ast.type, | ||
version: ast.version, | ||
}; | ||
} | ||
clearAST() { | ||
this.ast = null; | ||
this.isASTDirty = false; | ||
this.value.astGenerator = null; | ||
} | ||
getCacheKey(key: string): string { | ||
@@ -301,22 +441,13 @@ return md5FromString( | ||
createChildAsset(result: TransformerResult): InternalAsset { | ||
let content = result.content ?? result.code ?? ''; | ||
createChildAsset( | ||
result: TransformerResult, | ||
plugin: PackageName, | ||
configPath: FilePath, | ||
): InternalAsset { | ||
let content = result.content ?? result.code ?? null; | ||
let hash; | ||
let size; | ||
if (content === this.content) { | ||
hash = this.value.hash; | ||
size = this.value.stats.size; | ||
} else if (typeof content === 'string' || content instanceof Buffer) { | ||
hash = md5FromString(content); | ||
size = content.length; | ||
} else { | ||
hash = null; | ||
size = NaN; | ||
} | ||
let asset = new InternalAsset({ | ||
value: createAsset({ | ||
idBase: this.idBase, | ||
hash, | ||
hash: this.value.hash, | ||
filePath: this.value.filePath, | ||
@@ -336,3 +467,2 @@ type: result.type, | ||
...this.value.meta, | ||
// $FlowFixMe | ||
...result.meta, | ||
@@ -345,3 +475,3 @@ }, | ||
time: 0, | ||
size, | ||
size: this.value.stats.size, | ||
}, | ||
@@ -351,2 +481,7 @@ symbols: new Map([...this.value.symbols, ...(result.symbols || [])]), | ||
uniqueKey: result.uniqueKey, | ||
astGenerator: result.ast | ||
? {type: result.ast.type, version: result.ast.version} | ||
: null, | ||
plugin, | ||
configPath, | ||
}), | ||
@@ -356,2 +491,3 @@ options: this.options, | ||
ast: result.ast, | ||
isASTDirty: result.ast === this.ast ? this.isASTDirty : true, | ||
mapBuffer: result.map ? result.map.toBuffer() : null, | ||
@@ -358,0 +494,0 @@ idBase: this.idBase, |
@@ -49,4 +49,3 @@ // @flow strict-local | ||
// $FlowFixMe | ||
return Object.assign({}, ...envs); | ||
} |
@@ -85,3 +85,2 @@ // @flow | ||
if (pipeline) { | ||
// $FlowFixMe | ||
return pipeline.map(pkg => { | ||
@@ -88,0 +87,0 @@ if (pkg === '...') return pkg; |
@@ -263,3 +263,5 @@ // @flow strict-local | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
let bundleGraph = await this.#bundlerRunner.bundle(assetGraph, {signal}); | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 (Windows only) | ||
dumpGraphToGraphViz(bundleGraph._graph, 'BundleGraph'); | ||
@@ -266,0 +268,0 @@ |
@@ -11,2 +11,3 @@ // @flow strict-local | ||
AST, | ||
ASTGenerator, | ||
ConfigResult, | ||
@@ -71,6 +72,2 @@ Dependency as IDependency, | ||
get ast(): ?AST { | ||
return this.#asset.ast; | ||
} | ||
get type(): string { | ||
@@ -124,2 +121,6 @@ return this.#asset.value.type; | ||
get astGenerator(): ?ASTGenerator { | ||
return this.#asset.value.astGenerator; | ||
} | ||
getConfig( | ||
@@ -163,2 +164,6 @@ filePaths: Array<FilePath>, | ||
getAST(): Promise<?AST> { | ||
return this.#asset.getAST(); | ||
} | ||
getMapBuffer(): Promise<?Buffer> { | ||
@@ -183,6 +188,2 @@ return this.#asset.getMapBuffer(); | ||
get outputHash(): string { | ||
return this.#asset.value.outputHash; | ||
} | ||
get stats(): Stats { | ||
@@ -207,10 +208,2 @@ return this.#asset.value.stats; | ||
get ast(): ?AST { | ||
return this.#asset.ast; | ||
} | ||
set ast(ast: ?AST): void { | ||
this.#asset.ast = ast; | ||
} | ||
setMap(map: ?SourceMap): void { | ||
@@ -256,6 +249,10 @@ this.#asset.setMap(map); | ||
addIncludedFile(file: File) { | ||
return this.#asset.addIncludedFile(file); | ||
addIncludedFile(file: File): void { | ||
this.#asset.addIncludedFile(file); | ||
} | ||
isASTDirty(): boolean { | ||
return this.#asset.isASTDirty; | ||
} | ||
setBuffer(buffer: Buffer): void { | ||
@@ -273,2 +270,6 @@ this.#asset.setBuffer(buffer); | ||
setAST(ast: AST): void { | ||
return this.#asset.setAST(ast); | ||
} | ||
addURLDependency(url: string, opts: $Shape<DependencyOptions>): string { | ||
@@ -275,0 +276,0 @@ return this.addDependency({ |
@@ -160,3 +160,2 @@ // @flow | ||
} else if (this.isNode() && this.engines.node != null && minVersions.node) { | ||
// $FlowFixMe | ||
return !semver.intersects(`< ${minVersions.node}`, this.engines.node); | ||
@@ -163,0 +162,0 @@ } |
@@ -75,2 +75,3 @@ // @flow strict-local | ||
static deserialize(opts: SerializedRequestGraph) { | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
let deserialized = new RequestGraph(opts); | ||
@@ -81,3 +82,3 @@ deserialized.invalidNodeIds = opts.invalidNodeIds; | ||
deserialized.unpredicatableNodeIds = opts.unpredicatableNodeIds; | ||
// $FlowFixMe | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 (Windows only) | ||
return deserialized; | ||
@@ -84,0 +85,0 @@ } |
@@ -75,3 +75,2 @@ // @flow strict-local | ||
...initialOptions.env, | ||
// $FlowFixMe | ||
...(await loadDotEnv( | ||
@@ -78,0 +77,0 @@ initialOptions.env ?? {}, |
// @flow strict-local | ||
import type { | ||
MutableAsset as IMutableAsset, | ||
FilePath, | ||
@@ -32,3 +31,3 @@ GenerateOutput, | ||
import ResolverRunner from './ResolverRunner'; | ||
import {MutableAsset, assetToInternalAsset} from './public/Asset'; | ||
import {Asset, MutableAsset, assetToInternalAsset} from './public/Asset'; | ||
import InternalAsset, {createAsset} from './InternalAsset'; | ||
@@ -39,3 +38,3 @@ import summarizeRequest from './summarizeRequest'; | ||
type GenerateFunc = (input: IMutableAsset) => Promise<GenerateOutput>; | ||
type GenerateFunc = (input: InternalAsset) => Promise<GenerateOutput>; | ||
@@ -240,3 +239,3 @@ type PostProcessFunc = ( | ||
let inputAssets = [initialAsset]; | ||
let resultingAssets; | ||
let resultingAssets = []; | ||
let finalAssets = []; | ||
@@ -266,6 +265,13 @@ for (let transformer of pipeline.transformers) { | ||
transformer.config, | ||
this.parcelConfig, | ||
); | ||
for (let result of transformerResults) { | ||
resultingAssets.push(asset.createChildAsset(result)); | ||
resultingAssets.push( | ||
asset.createChildAsset( | ||
result, | ||
transformer.name, | ||
this.parcelConfig.filePath, | ||
), | ||
); | ||
} | ||
@@ -281,9 +287,28 @@ } catch (e) { | ||
finalAssets = finalAssets.concat(resultingAssets); | ||
// Make assets with ASTs generate unless they are js assets and target uses | ||
// scope hoisting. This parallelizes generation and distributes work more | ||
// evenly across workers than if one worker needed to generate all assets in | ||
// a large bundle during packaging. | ||
let generate = pipeline.generate; | ||
if (generate != null) { | ||
await Promise.all( | ||
resultingAssets | ||
.filter( | ||
asset => | ||
asset.ast != null && | ||
!(asset.value.type === 'js' && asset.value.env.scopeHoist), | ||
) | ||
.map(async asset => { | ||
if (asset.isASTDirty) { | ||
let output = await generate(asset); | ||
asset.content = output.code; | ||
asset.mapBuffer = output.map?.toBuffer(); | ||
} | ||
return Promise.all( | ||
finalAssets.map(asset => | ||
finalize(nullthrows(asset), nullthrows(pipeline.generate)), | ||
), | ||
); | ||
asset.clearAST(); | ||
}), | ||
); | ||
} | ||
return finalAssets.concat(resultingAssets); | ||
} | ||
@@ -479,2 +504,3 @@ | ||
preloadedConfig: ?Config, | ||
parcelConfig: ParcelConfig, | ||
): Promise<Array<TransformerResult>> { | ||
@@ -511,2 +537,3 @@ const logger = new PluginLogger({origin: transformerName}); | ||
asset.ast && | ||
asset.isASTDirty && | ||
(!transformer.canReuseAST || | ||
@@ -520,5 +547,5 @@ !transformer.canReuseAST({ | ||
) { | ||
let output = await pipeline.generate(new MutableAsset(asset)); | ||
let output = await pipeline.generate(asset); | ||
asset.content = output.code; | ||
asset.ast = null; | ||
asset.mapBuffer = output.map?.toBuffer(); | ||
} | ||
@@ -528,3 +555,3 @@ | ||
if (!asset.ast && transformer.parse) { | ||
asset.ast = await transformer.parse({ | ||
let ast = await transformer.parse({ | ||
asset: new MutableAsset(asset), | ||
@@ -536,2 +563,6 @@ config, | ||
}); | ||
if (ast) { | ||
asset.setAST(ast); | ||
asset.isASTDirty = false; | ||
} | ||
} | ||
@@ -544,2 +575,3 @@ | ||
asset: new MutableAsset(asset), | ||
ast: asset.ast, | ||
config, | ||
@@ -553,13 +585,12 @@ options: pipeline.pluginOptions, | ||
// Create generate and postProcess functions that can be called later | ||
pipeline.generate = (input: IMutableAsset): Promise<GenerateOutput> => { | ||
if (transformer.generate) { | ||
return Promise.resolve( | ||
transformer.generate({ | ||
asset: input, | ||
config, | ||
options: pipeline.pluginOptions, | ||
resolve, | ||
logger, | ||
}), | ||
); | ||
pipeline.generate = (input: InternalAsset): Promise<GenerateOutput> => { | ||
if (transformer.generate && input.ast) { | ||
let generated = transformer.generate({ | ||
asset: new Asset(input), | ||
ast: input.ast, | ||
options: pipeline.pluginOptions, | ||
logger, | ||
}); | ||
input.clearAST(); | ||
return Promise.resolve(generated); | ||
} | ||
@@ -586,3 +617,11 @@ | ||
return Promise.all(results.map(result => asset.createChildAsset(result))); | ||
return Promise.all( | ||
results.map(result => | ||
asset.createChildAsset( | ||
result, | ||
transformerName, | ||
parcelConfig.filePath, | ||
), | ||
), | ||
); | ||
}; | ||
@@ -594,43 +633,30 @@ } | ||
async function finalize( | ||
asset: InternalAsset, | ||
generate: GenerateFunc, | ||
): Promise<InternalAsset> { | ||
if (asset.ast && generate) { | ||
let result = await generate(new MutableAsset(asset)); | ||
return asset.createChildAsset({ | ||
type: asset.value.type, | ||
uniqueKey: asset.value.uniqueKey, | ||
...result, | ||
}); | ||
} | ||
return asset; | ||
} | ||
function normalizeAssets( | ||
results: Array<TransformerResult | MutableAsset>, | ||
): Array<TransformerResult> { | ||
return results.map(result => { | ||
if (!(result instanceof MutableAsset)) { | ||
return result; | ||
} | ||
): Promise<Array<TransformerResult>> { | ||
return Promise.all( | ||
results.map<Promise<TransformerResult>>(async result => { | ||
if (!(result instanceof MutableAsset)) { | ||
return result; | ||
} | ||
let internalAsset = assetToInternalAsset(result); | ||
return { | ||
type: result.type, | ||
content: internalAsset.content, | ||
ast: result.ast, | ||
mapBuffer: internalAsset.mapBuffer, | ||
// $FlowFixMe | ||
dependencies: [...internalAsset.value.dependencies.values()], | ||
includedFiles: result.getIncludedFiles(), | ||
// $FlowFixMe | ||
env: result.env, | ||
isIsolated: result.isIsolated, | ||
isInline: result.isInline, | ||
pipeline: internalAsset.value.pipeline, | ||
meta: result.meta, | ||
uniqueKey: internalAsset.value.uniqueKey, | ||
}; | ||
}); | ||
let internalAsset = assetToInternalAsset(result); | ||
return { | ||
type: result.type, | ||
content: await internalAsset.content, | ||
ast: internalAsset.ast, | ||
mapBuffer: internalAsset.mapBuffer, | ||
// $FlowFixMe | ||
dependencies: [...internalAsset.value.dependencies.values()], | ||
includedFiles: result.getIncludedFiles(), | ||
// $FlowFixMe | ||
env: result.env, | ||
isIsolated: result.isIsolated, | ||
isInline: result.isInline, | ||
pipeline: internalAsset.value.pipeline, | ||
meta: result.meta, | ||
uniqueKey: internalAsset.value.uniqueKey, | ||
}; | ||
}), | ||
); | ||
} | ||
@@ -637,0 +663,0 @@ |
// @flow strict-local | ||
import type { | ||
ASTGenerator, | ||
BuildMode, | ||
@@ -111,3 +112,2 @@ BundleGroup, | ||
isSource: boolean, | ||
outputHash: string, | ||
env: Environment, | ||
@@ -118,6 +118,11 @@ meta: Meta, | ||
mapKey: ?string, | ||
outputHash: ?string, | ||
pipeline: ?string, | ||
astKey: ?string, | ||
astGenerator: ?ASTGenerator, | ||
symbols: Map<Symbol, Symbol>, | ||
sideEffects: boolean, | ||
uniqueKey?: ?string, | ||
configPath?: FilePath, | ||
plugin?: ?PackageName, | ||
|}; | ||
@@ -124,0 +129,0 @@ |
@@ -51,3 +51,2 @@ // @flow strict-local | ||
report: reportWorker.bind(null, workerApi), | ||
// $FlowFixMe | ||
options, | ||
@@ -74,3 +73,2 @@ config, | ||
report: reportWorker.bind(null, workerApi), | ||
// $FlowFixMe | ||
options, | ||
@@ -116,3 +114,2 @@ config, | ||
config, | ||
// $FlowFixMe | ||
options, | ||
@@ -119,0 +116,0 @@ report: reportWorker.bind(null, workerApi), |
@@ -86,5 +86,5 @@ // @flow | ||
validateConfigFile( | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
{ | ||
filePath: '.parcelrc', | ||
// $FlowFixMe | ||
resolvers: '123', | ||
@@ -115,3 +115,2 @@ }, | ||
filePath: '.parcelrc', | ||
// $FlowFixMe | ||
resolvers: ['parcel-foo-bar'], | ||
@@ -128,3 +127,2 @@ }, | ||
filePath: '.parcelrc', | ||
// $FlowFixMe | ||
resolvers: ['parcel-resolver-test'], | ||
@@ -140,3 +138,2 @@ }, | ||
filePath: '.parcelrc', | ||
// $FlowFixMe | ||
resolvers: ['parcel-resolver-test', '...'], | ||
@@ -179,5 +176,5 @@ }, | ||
validateConfigFile( | ||
// $FlowFixMe Added in Flow 0.121.0 upgrade in #4381 | ||
{ | ||
filePath: '.parcelrc', | ||
// $FlowFixMe | ||
extends: 2, | ||
@@ -184,0 +181,0 @@ }, |
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
Manifest confusion
Supply chain riskThis package has inconsistent metadata. This could be malicious or caused by an error when publishing the package.
Found 1 instance in 1 package
693308
19815
8