* Adds the provided source to the init fragment. * @template Context * @param {Source} source sources * @param {MaybeMergeableInitFragment<Context>[]} initFragments init fragments * @param {Context} context context * @returns {Source} source
(source, initFragments, context)
| 106 | * @returns {Source} source |
| 107 | */ |
| 108 | static addToSource(source, initFragments, context) { |
| 109 | if (initFragments.length > 0) { |
| 110 | // Sort fragments by position. If 2 fragments have the same position, |
| 111 | // use their index. |
| 112 | const sortedFragments = initFragments |
| 113 | .map(extractFragmentIndex) |
| 114 | .sort(sortFragmentWithIndex); |
| 115 | |
| 116 | // Deduplicate fragments. If a fragment has no key, it is always included. |
| 117 | /** @type {Map<InitFragmentKey | symbol, MaybeMergeableInitFragment<Context> | MaybeMergeableInitFragment<Context>[]>} */ |
| 118 | const keyedFragments = new Map(); |
| 119 | for (const [fragment] of sortedFragments) { |
| 120 | if (typeof fragment.mergeAll === "function") { |
| 121 | if (!fragment.key) { |
| 122 | throw new Error( |
| 123 | `InitFragment with mergeAll function must have a valid key: ${fragment.constructor.name}` |
| 124 | ); |
| 125 | } |
| 126 | const oldValue = keyedFragments.get(fragment.key); |
| 127 | if (oldValue === undefined) { |
| 128 | keyedFragments.set(fragment.key, fragment); |
| 129 | } else if (Array.isArray(oldValue)) { |
| 130 | oldValue.push(fragment); |
| 131 | } else { |
| 132 | keyedFragments.set(fragment.key, [oldValue, fragment]); |
| 133 | } |
| 134 | continue; |
| 135 | } else if (typeof fragment.merge === "function") { |
| 136 | const key = /** @type {InitFragmentKey} */ (fragment.key); |
| 137 | const oldValue = |
| 138 | /** @type {MaybeMergeableInitFragment<Context>} */ |
| 139 | (keyedFragments.get(key)); |
| 140 | if (oldValue !== undefined) { |
| 141 | keyedFragments.set(key, fragment.merge(oldValue)); |
| 142 | continue; |
| 143 | } |
| 144 | } |
| 145 | keyedFragments.set(fragment.key || Symbol("fragment key"), fragment); |
| 146 | } |
| 147 | |
| 148 | const concatSource = new ConcatSource(); |
| 149 | /** @type {(string | Source)[]} */ |
| 150 | const endContents = []; |
| 151 | for (let fragment of keyedFragments.values()) { |
| 152 | if (Array.isArray(fragment)) { |
| 153 | fragment = |
| 154 | /** @type {[MaybeMergeableInitFragment<Context> & { mergeAll: (fragments: MaybeMergeableInitFragment<Context>[]) => MaybeMergeableInitFragment<Context>[] }, ...MaybeMergeableInitFragment<Context>[]]} */ |
| 155 | (fragment)[0].mergeAll(fragment); |
| 156 | } |
| 157 | const content = |
| 158 | /** @type {MaybeMergeableInitFragment<Context>} */ |
| 159 | (fragment).getContent(context); |
| 160 | if (content) { |
| 161 | concatSource.add(content); |
| 162 | } |
| 163 | const endContent = |
| 164 | /** @type {MaybeMergeableInitFragment<Context>} */ |
| 165 | (fragment).getEndContent(context); |
no test coverage detected