executeBundle method
dynamic
executeBundle(})
Execute an AstBundle with full import resolution.
Unlike execute, this method supports cross-module imports by creating an AstModuleLoader that resolves imports from the bundle's module map.
The entry point module is determined by:
- The
entryPointparameter (if provided) - The bundle's AstBundle.entryPointUri
Example
final runner = D4rtRunner();
// register bridges...
final bundle = AstBundle.fromFile('app.d4rtbundle');
final result = runner.executeBundle(bundle);
Implementation
dynamic executeBundle(
AstBundle bundle, {
String? entryPoint,
String name = 'main',
List<Object?>? positionalArgs,
Map<String, Object?>? namedArgs,
}) {
// Determine entry point URI
final entryUri = entryPoint ?? bundle.entryPointUri;
final entryAst = bundle.modules[entryUri];
if (entryAst == null) {
throw ArgumentD4rtException(
'Entry point "$entryUri" not found in bundle. '
'Available: ${bundle.modules.keys.join(", ")}',
);
}
// Initialize environment
final swInit = D4rtProfiler.enabled ? (Stopwatch()..start()) : null;
InterpretedFunction.clearParentMap();
final executionEnvironment = _initEnvironment();
if (D4rtProfiler.enabled) {
D4rtProfiler.record(
'executeBundle._initEnvironment', swInit!.elapsedMicroseconds);
}
// Create AstModuleLoader for import resolution
final swLoader = D4rtProfiler.enabled ? (Stopwatch()..start()) : null;
// PERF step #2: reuse bridged-module envs across executions, built under
// the shared warm parent (the execution environment's enclosing). Gated by
// [reuseAcrossRuns]:
// * Migrated (non-empty allowed-set) runners share envs process-wide via
// [_bridgedModuleEnvCache], keyed by the allowed-set signature.
// * Legacy runners reuse a *per-instance* [_instanceBridgedModuleEnvCache]
// — never shared across runners, so their `<default>`-package bridges
// cannot substitute into another runner.
// When [reuseAcrossRuns] is false both stay null → the loader rebuilds the
// module envs fresh every run for full inter-run isolation.
Map<String, Environment>? sharedBridgedModuleEnvs;
Environment? sharedModuleEnclosing;
if (reuseAcrossRuns) {
if (_allowedPackages.isNotEmpty) {
final key = (_allowedPackages.toList()..sort()).join('|');
sharedBridgedModuleEnvs =
_bridgedModuleEnvCache.putIfAbsent(key, () => {});
} else {
sharedBridgedModuleEnvs = _instanceBridgedModuleEnvCache ??= {};
}
sharedModuleEnclosing = executionEnvironment.enclosing;
}
final moduleLoader = AstModuleLoader(
modules: bundle.modules,
globalEnvironment: executionEnvironment,
runner: this,
sharedBridgedModuleEnvironments: sharedBridgedModuleEnvs,
sharedModuleEnclosing: sharedModuleEnclosing,
onBridgedModuleEnvBuilt: () => _debugBridgedModuleEnvBuilds++,
);
moduleLoader.currentLibrary = Uri.parse(entryUri);
// Step #3 (retention) — track the current run's loader so dispose() can
// release its parsed-module cache and debugLoadedModuleCount can observe it.
_lastModuleLoader = moduleLoader;
if (D4rtProfiler.enabled) {
D4rtProfiler.record(
'executeBundle.moduleLoader', swLoader!.elapsedMicroseconds);
}
Logger.debug(
'[D4rtRunner.executeBundle] Entry point: $entryUri '
'(${bundle.modules.length} modules in bundle)',
);
// Execute with full module context
return _executeInEnvironment(
compilationUnit: entryAst,
executionEnvironment: executionEnvironment,
moduleContext: moduleLoader,
name: name,
positionalArgs: positionalArgs,
namedArgs: namedArgs,
);
}