blob: d97586cd38fa5d47ab03acbf5fee89eee1700c82 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
/// An implementation of [Pipeline] that runs in-memory.
///
/// To define a step, implement [MemoryModularStep].
import 'pipeline.dart';
import 'suite.dart';
/// A hook to fetch data previously computed for a dependency.
typedef ModuleDataProvider = Object Function(Module, DataId);
typedef SourceProvider = String Function(Uri);
abstract class MemoryModularStep extends ModularStep {
Future<Map<DataId, Object>> execute(
Module module,
SourceProvider sourceProvider,
ModuleDataProvider dataProvider,
List<String> flags);
}
class MemoryPipeline extends Pipeline<MemoryModularStep> {
final Map<Uri, String> _sources;
/// Internal state to hold the current results as they are computed by the
/// pipeline. Expected to be null before and after the pipeline runs.
Map<Module, Map<DataId, Object>> _results;
/// A copy of [_result] at the time the pipeline last finished running.
Map<Module, Map<DataId, Object>> resultsForTesting;
final ConfigurationRegistry _registry;
/// Cache of results when [cacheSharedModules] is true
final List<Map<Module, Map<DataId, Object>>> _resultCache;
MemoryPipeline(this._sources, List<MemoryModularStep> steps,
{bool cacheSharedModules: false})
: _registry = cacheSharedModules ? new ConfigurationRegistry() : null,
_resultCache = cacheSharedModules ? [] : null,
super(steps, cacheSharedModules);
@override
Future<void> run(ModularTest test) async {
_results = {};
Map<Module, Map<DataId, Object>> cache = null;
if (cacheSharedModules) {
int id = _registry.computeConfigurationId(test);
if (id < _resultCache.length) {
cache = _resultCache[id];
} else {
assert(id == _resultCache.length);
_resultCache.add(cache = {});
}
_results.addAll(cache);
}
await super.run(test);
resultsForTesting = _results;
if (cacheSharedModules) {
for (var module in _results.keys) {
if (module.isShared) {
cache[module] = _results[module];
}
}
}
_results = null;
}
@override
Future<void> runStep(MemoryModularStep step, Module module,
Map<Module, Set<DataId>> visibleData, List<String> flags) async {
if (cacheSharedModules && module.isShared) {
bool allCachedResultsFound = true;
for (var dataId in step.resultData) {
if (_results[module] == null || _results[module][dataId] == null) {
allCachedResultsFound = false;
break;
}
}
if (allCachedResultsFound) {
step.notifyCached(module);
return;
}
}
Map<Module, Map<DataId, Object>> inputData = {};
visibleData.forEach((module, dataIdSet) {
inputData[module] = {};
for (var dataId in dataIdSet) {
inputData[module][dataId] = _results[module][dataId];
}
});
Map<Uri, String> inputSources = {};
if (step.needsSources) {
module.sources.forEach((relativeUri) {
var uri = module.rootUri.resolveUri(relativeUri);
inputSources[uri] = _sources[uri];
});
}
Map<DataId, Object> result = await step.execute(
module,
(Uri uri) => inputSources[uri],
(Module m, DataId id) => inputData[m][id],
flags);
for (var dataId in step.resultData) {
(_results[module] ??= {})[dataId] = result[dataId];
}
}
}