An include or import cycle recursed without bound and crashed the host with a stack overflow, reachable from stylesheet data. The compile chain tracks the active load chain by resolved href and drops re-entry, while diamond composition keeps loading both copies with their own import precedences per 2.6.2. id() builds a per-document index on first use instead of re-walking the document per call, matching key(). Cycle and diamond regression tests added.
16 lines
750 B
Swift
16 lines
750 B
Swift
/// The state accumulated while flattening one unit: its queued
|
|
/// declarations, the import-precedence counter, and the included
|
|
/// documents' roots. Tree nodes hold their parents weakly, so the
|
|
/// roots must stay retained until the declarations are parsed or the
|
|
/// ancestor chain (xmlns declarations, exclusions, aliases in scope)
|
|
/// silently disappears.
|
|
struct XSLTUnitCollector {
|
|
var counter: Int
|
|
var declarations: [(XSLTTree, String)] = []
|
|
var retainedRoots: [XSLTTree] = []
|
|
/// The resolved hrefs on the active load chain (ancestors only, not
|
|
/// siblings): re-entry means an include or import cycle, which is
|
|
/// dropped; a diamond (two units loading the same sheet) stays legal.
|
|
var chain: Set<String> = []
|
|
}
|