← board

feature: PCL components adopt the Create(AOwner) virtual-constructor shape

Unblocked 2026-06-23: the compiler half is DONE (done/feature-metaclass-construct-dispatch, pinned v44). classRefVar.Create(args) dispatches through the dynamic VMT, parametrised virtual ctors work, and the TBaseClass(GetClass(name)).Create(AOwner) bridge is verified. PCL can now adopt the Create(AOwner); virtual; shape and have the streamer construct via metaclass.

Goal

Shape PCL's component/control classes like FPC's so the same source could compile under both and so the streamer constructs them through a metaclass:

This is the library half of urgent/feature-metaclass-construct-dispatch (the language half). They meet at "streaming constructs a component with an owner".

Ownership stance (deliberate)

FPC's TComponent auto-frees its owned children. We support the shape for compatibility but do NOT impose the religion:

Rationale: the owner system solves some problems and creates others (nil-owner + parent-only is a common, cleaner app pattern). Compatibility ≠ enforcement.

Scope

Acceptance

A streamed widget tree is constructed via Create(AOwner) (Owner may be nil), widgets keep their natural constructors (no CreateHandle/lazy stopgaps), Eliah + gui_suite green. App code that passes nil owner + sets Parent works unchanged.

Note

Blocked-by urgent/feature-metaclass-construct-dispatch for the streaming path, but the Create(AOwner) migration itself can proceed independently.

Progress 2026-06-23

DONE (the migration, which the ticket says can proceed independently):

BLOCKED — streamer adoption: replacing CreateInstance with TComponentClass(childCls).Create(parent) and dropping the four constructor-skip stopgaps. The metaclass-construct bridge stamps a non-canonical VMT → urgent/bug-metaclass-new-getclass-vmt. Streamer stays on CreateInstance + stopgaps (markers point at that ticket) until it lands.

Compiler gaps also hit (clean single-ctor path used instead, no workaround): default param on a constructor and overloaded constructors + inherited both fail to parse — noted for a future backlog ticket if the parameterless-convenience shape is ever wanted.

Progress 2026-06-24 — streamer adoption DONE

done/bug-metaclass-new-getclass-vmt (v45) cleared the block. TReader.ReadChildren now constructs each child via TComponentClass(childCls).Create(parent) (Owner = parent), so streamed components run their real virtual ctors. All four constructor-skip stopgaps reverted:

Gates: garin 116/116, gui_suite OK (incl test_pcl_lfm streaming), eliah build+smoke+screenshot green. Commit e71cb1c.