registerExtensions method
Registers a body callback that wires additional bridge state
(e.g. registerRelaxers(), registerD4rtRuntimeExtensions(),
registerD4rtInterfaceProxyOverrides()) after the main
registerBridgedClass/registerBridgedEnum/etc. registrations
for packageName have happened.
The body is not run immediately — the runner queues it and runs
every queued body in registration order when finalizeBridges is
called (or implicitly on the first execute*/executeBundle* call
that follows). This replaces the comment-driven "must run AFTER
bridges" rule (formerly enforced by code ordering inside
FlutterD4rt._registerBridges) with an enforced mechanism: bridge
packages declare their wiring up front, and the runner controls
when it runs.
Idempotent on package name: a second call with the same
packageName overwrites the previous body — the contract is one
extension callback per bridge package. The body itself must
internally tolerate being run more than once if the embedder
constructs multiple D4rtRunner instances in the same process,
since the D4 / BridgedClass registries it touches are static.
(Step 5 made all the per-key D4 registries idempotent on factory
identity, so this contract is satisfied for the standard
register* calls.)
Step 7/11: the body is stored on the package's pooled bundle
(_packagePool entry for packageName) rather than an instance map,
and this instance records the package in _extensionPackages (in
registration order) so finalizeBridges knows which pooled callbacks
to fire and when. Firing is once per package per process — the first
runner to finalize the package fires it, later runners (and later
instances granted the already-pooled package) skip it.
Throws StateError if finalizeBridges has already run on this runner — adding extensions after finalization is a misuse.
Implementation
void registerExtensions(String packageName, void Function() body) {
if (_bridgesFinalized) {
throw StateError(
'Cannot registerExtensions("$packageName"): finalizeBridges() has '
'already been called on this D4rtRunner. Register all extensions '
'before the first execute*/executeBundle* call (or call '
'finalizeBridges() explicitly after the last registerExtensions).',
);
}
_bundleFor(packageName).extensionCallback = body;
_extensionPackages.add(packageName);
}