@microsoft/fast-element 2.10.3 → 3.0.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (351) hide show
  1. package/ARCHITECTURE_HTML_TAGGED_TEMPLATE_LITERAL.md +1 -1
  2. package/ARCHITECTURE_OVERVIEW.md +2 -2
  3. package/CHANGELOG.json +31 -1
  4. package/CHANGELOG.md +10 -2
  5. package/DECLARATIVE_DESIGN.md +806 -0
  6. package/DECLARATIVE_HTML.md +470 -0
  7. package/DECLARATIVE_MIGRATION.md +215 -0
  8. package/DECLARATIVE_RENDERING.md +530 -0
  9. package/DECLARATIVE_RENDERING_LIFECYCLE.md +288 -0
  10. package/DECLARATIVE_SCHEMA_OBSERVER_MAP.md +489 -0
  11. package/DESIGN.md +143 -34
  12. package/MIGRATION.md +387 -0
  13. package/README.md +208 -1
  14. package/SIZES.md +25 -0
  15. package/api-extractor.arrays.json +15 -0
  16. package/api-extractor.context.json +1 -0
  17. package/api-extractor.declarative.json +15 -0
  18. package/api-extractor.di.json +1 -0
  19. package/api-extractor.hydration.json +15 -0
  20. package/api-extractor.styles.json +15 -0
  21. package/dist/arrays/arrays.api.json +2621 -0
  22. package/dist/context/context.api.json +1 -1
  23. package/dist/declarative/declarative.api.json +7844 -0
  24. package/dist/di/di.api.json +2 -2
  25. package/dist/dts/array-observer.d.ts +2 -0
  26. package/dist/dts/arrays.d.ts +2 -0
  27. package/dist/dts/attr.d.ts +1 -0
  28. package/dist/dts/binding/signal.d.ts +6 -6
  29. package/dist/dts/binding/two-way.d.ts +1 -0
  30. package/dist/dts/binding.d.ts +7 -0
  31. package/dist/dts/components/attributes.d.ts +2 -5
  32. package/dist/dts/components/definition-schema-transforms.d.ts +9 -0
  33. package/dist/dts/components/element-controller.d.ts +80 -114
  34. package/dist/dts/components/element-hydration.d.ts +1 -1
  35. package/dist/dts/components/enable-hydration.d.ts +34 -0
  36. package/dist/dts/components/fast-definitions.d.ts +91 -42
  37. package/dist/dts/components/fast-element.d.ts +5 -8
  38. package/dist/dts/components/hydration-tracker.d.ts +40 -0
  39. package/dist/dts/components/hydration.d.ts +18 -53
  40. package/dist/dts/components/schema.d.ts +205 -0
  41. package/dist/dts/context.d.ts +6 -6
  42. package/dist/dts/css.d.ts +3 -0
  43. package/dist/dts/debug.d.ts +5 -1
  44. package/dist/dts/declarative/attribute-map.d.ts +58 -0
  45. package/dist/dts/declarative/debug.d.ts +5 -0
  46. package/dist/dts/declarative/index.d.ts +13 -0
  47. package/dist/dts/declarative/interfaces.d.ts +9 -0
  48. package/dist/dts/declarative/observer-map-utilities.d.ts +58 -0
  49. package/dist/dts/declarative/observer-map.d.ts +89 -0
  50. package/dist/dts/declarative/runtime.d.ts +5 -0
  51. package/dist/dts/declarative/syntax.d.ts +21 -0
  52. package/dist/dts/declarative/template-bridge.d.ts +33 -0
  53. package/dist/dts/declarative/template-parser.d.ts +98 -0
  54. package/dist/dts/declarative/template.d.ts +9 -0
  55. package/dist/dts/declarative/utilities.d.ts +312 -0
  56. package/dist/dts/di/di.d.ts +1 -1
  57. package/dist/dts/directives/children.d.ts +2 -0
  58. package/dist/dts/directives/node-observation.d.ts +2 -0
  59. package/dist/dts/directives/ref.d.ts +2 -0
  60. package/dist/dts/directives/repeat.d.ts +4 -0
  61. package/dist/dts/directives/slotted.d.ts +2 -0
  62. package/dist/dts/directives/when.d.ts +3 -0
  63. package/dist/dts/dom-policy.d.ts +1 -1
  64. package/dist/dts/html.d.ts +5 -0
  65. package/dist/dts/hydration/runtime.d.ts +7 -0
  66. package/dist/dts/hydration/target-builder.d.ts +15 -12
  67. package/dist/dts/hydration.d.ts +14 -0
  68. package/dist/dts/index.d.ts +38 -42
  69. package/dist/dts/index.debug.d.ts +0 -1
  70. package/dist/dts/index.rollup.debug.d.ts +0 -1
  71. package/dist/dts/interfaces.d.ts +1 -49
  72. package/dist/dts/observable.d.ts +3 -6
  73. package/dist/dts/observation/arrays.d.ts +1 -1
  74. package/dist/dts/observation/update-queue.d.ts +1 -1
  75. package/dist/dts/platform.d.ts +25 -4
  76. package/dist/dts/render.d.ts +7 -0
  77. package/dist/dts/schema.d.ts +1 -0
  78. package/dist/dts/state/exports.d.ts +1 -1
  79. package/dist/dts/state/state.d.ts +2 -2
  80. package/dist/dts/styles/css-directive.d.ts +5 -12
  81. package/dist/dts/styles/css.d.ts +5 -7
  82. package/dist/dts/styles/element-styles.d.ts +0 -10
  83. package/dist/dts/styles.d.ts +6 -0
  84. package/dist/dts/templating/children.d.ts +1 -1
  85. package/dist/dts/templating/html-binding-directive.d.ts +10 -0
  86. package/dist/dts/templating/html-directive.d.ts +17 -0
  87. package/dist/dts/templating/hydration-view.d.ts +109 -0
  88. package/dist/dts/templating/ref.d.ts +1 -1
  89. package/dist/dts/templating/render.d.ts +8 -2
  90. package/dist/dts/templating/repeat.d.ts +2 -2
  91. package/dist/dts/templating/slotted.d.ts +1 -1
  92. package/dist/dts/templating/template.d.ts +17 -9
  93. package/dist/dts/templating/view.d.ts +25 -102
  94. package/dist/dts/templating/when.d.ts +1 -1
  95. package/dist/dts/templating.d.ts +10 -0
  96. package/dist/dts/testing/exports.d.ts +2 -2
  97. package/dist/dts/tsdoc-metadata.json +1 -1
  98. package/dist/dts/updates.d.ts +1 -0
  99. package/dist/dts/volatile.d.ts +2 -0
  100. package/dist/esm/array-observer.js +1 -0
  101. package/dist/esm/arrays.js +1 -0
  102. package/dist/esm/attr.js +1 -0
  103. package/dist/esm/binding/normalize.js +1 -1
  104. package/dist/esm/binding/signal.js +4 -4
  105. package/dist/esm/binding/two-way.js +2 -1
  106. package/dist/esm/binding.js +4 -0
  107. package/dist/esm/components/attributes.js +8 -5
  108. package/dist/esm/components/definition-schema-transforms.js +23 -0
  109. package/dist/esm/components/element-controller.js +200 -269
  110. package/dist/esm/components/element-hydration.js +1 -1
  111. package/dist/esm/components/enable-hydration.js +100 -0
  112. package/dist/esm/components/fast-definitions.js +211 -49
  113. package/dist/esm/components/fast-element.js +18 -27
  114. package/dist/esm/components/hydration-tracker.js +93 -0
  115. package/dist/esm/components/hydration.js +62 -144
  116. package/dist/esm/components/schema.js +253 -0
  117. package/dist/esm/context.js +6 -6
  118. package/dist/esm/css.js +3 -0
  119. package/dist/esm/debug.js +26 -26
  120. package/dist/esm/declarative/attribute-map.js +121 -0
  121. package/dist/esm/declarative/debug.js +5 -0
  122. package/dist/esm/declarative/index.js +3 -0
  123. package/dist/esm/declarative/interfaces.js +10 -0
  124. package/dist/esm/declarative/observer-map-utilities.js +562 -0
  125. package/dist/esm/declarative/observer-map.js +216 -0
  126. package/dist/esm/declarative/runtime.js +14 -0
  127. package/dist/esm/declarative/syntax.js +36 -0
  128. package/dist/esm/declarative/template-bridge.js +170 -0
  129. package/dist/esm/declarative/template-parser.js +306 -0
  130. package/dist/esm/declarative/template.js +142 -0
  131. package/dist/esm/declarative/utilities.js +834 -0
  132. package/dist/esm/di/di.js +6 -8
  133. package/dist/esm/directives/children.js +1 -0
  134. package/dist/esm/directives/node-observation.js +1 -0
  135. package/dist/esm/directives/ref.js +1 -0
  136. package/dist/esm/directives/repeat.js +1 -0
  137. package/dist/esm/directives/slotted.js +1 -0
  138. package/dist/esm/directives/when.js +1 -0
  139. package/dist/esm/dom-policy.js +2 -2
  140. package/dist/esm/dom.js +1 -1
  141. package/dist/esm/html.js +2 -0
  142. package/dist/esm/hydration/runtime.js +33 -0
  143. package/dist/esm/hydration/target-builder.js +97 -90
  144. package/dist/esm/hydration.js +4 -0
  145. package/dist/esm/index.debug.js +2 -1
  146. package/dist/esm/index.js +34 -29
  147. package/dist/esm/index.rollup.debug.js +3 -2
  148. package/dist/esm/index.rollup.js +1 -1
  149. package/dist/esm/interfaces.js +1 -45
  150. package/dist/esm/observable.js +1 -4
  151. package/dist/esm/observation/arrays.js +1 -1
  152. package/dist/esm/observation/observable.js +5 -5
  153. package/dist/esm/observation/update-queue.js +47 -58
  154. package/dist/esm/platform.js +31 -30
  155. package/dist/esm/render.js +1 -0
  156. package/dist/esm/schema.js +1 -0
  157. package/dist/esm/state/exports.js +1 -1
  158. package/dist/esm/styles/css-directive.js +1 -2
  159. package/dist/esm/styles/css.js +15 -56
  160. package/dist/esm/styles/element-styles.js +69 -15
  161. package/dist/esm/styles.js +2 -0
  162. package/dist/esm/templating/html-binding-directive.js +24 -10
  163. package/dist/esm/templating/hydration-view.js +235 -0
  164. package/dist/esm/templating/render.js +13 -2
  165. package/dist/esm/templating/repeat.js +36 -34
  166. package/dist/esm/templating/template.js +7 -7
  167. package/dist/esm/templating/view.js +24 -233
  168. package/dist/esm/templating.js +7 -0
  169. package/dist/esm/testing/exports.js +2 -2
  170. package/dist/esm/updates.js +1 -0
  171. package/dist/esm/volatile.js +1 -0
  172. package/dist/fast-element.api.json +9017 -6996
  173. package/dist/fast-element.d.ts +3557 -796
  174. package/dist/fast-element.debug.js +5093 -4419
  175. package/dist/fast-element.debug.min.js +2 -2
  176. package/dist/fast-element.js +5398 -4655
  177. package/dist/fast-element.min.js +2 -2
  178. package/dist/fast-element.untrimmed.d.ts +881 -481
  179. package/dist/hydration/hydration.api.json +5237 -0
  180. package/dist/styles/styles.api.json +2672 -0
  181. package/docs/api-report.api.md +344 -167
  182. package/docs/arrays/api-report.api.md +114 -0
  183. package/docs/declarative/api-report.api.md +397 -0
  184. package/docs/hydration/api-report.api.md +285 -0
  185. package/docs/styles/api-report.api.md +135 -0
  186. package/package.json +149 -40
  187. package/playwright.declarative.config.ts +26 -0
  188. package/playwright.declarative.webui.config.ts +20 -0
  189. package/scripts/declarative/build-fixtures-with-webui.js +135 -0
  190. package/scripts/declarative/build-fixtures.js +49 -0
  191. package/scripts/declarative/build-fixtures.utilities.js +101 -0
  192. package/scripts/measure-sizes.js +219 -0
  193. package/scripts/run-api-extractor.js +39 -20
  194. package/test/declarative/fixtures/README.md +72 -0
  195. package/test/declarative/fixtures/WRITING_FIXTURES.md +330 -0
  196. package/test/declarative/fixtures/bindings/README.md +12 -0
  197. package/test/declarative/fixtures/bindings/attribute/entry.html +13 -0
  198. package/test/declarative/fixtures/bindings/attribute/fast-build.config.json +6 -0
  199. package/test/declarative/fixtures/bindings/attribute/index.html +25 -0
  200. package/test/declarative/fixtures/bindings/attribute/main.ts +41 -0
  201. package/test/declarative/fixtures/bindings/attribute/state.json +8 -0
  202. package/test/declarative/fixtures/bindings/attribute/templates.html +11 -0
  203. package/test/declarative/fixtures/bindings/content/entry.html +12 -0
  204. package/test/declarative/fixtures/bindings/content/fast-build.config.json +6 -0
  205. package/test/declarative/fixtures/bindings/content/index.html +19 -0
  206. package/test/declarative/fixtures/bindings/content/main.ts +27 -0
  207. package/test/declarative/fixtures/bindings/content/state.json +4 -0
  208. package/test/declarative/fixtures/bindings/content/templates.html +6 -0
  209. package/test/declarative/fixtures/bindings/dot-syntax/entry.html +11 -0
  210. package/test/declarative/fixtures/bindings/dot-syntax/fast-build.config.json +6 -0
  211. package/test/declarative/fixtures/bindings/dot-syntax/index.html +47 -0
  212. package/test/declarative/fixtures/bindings/dot-syntax/main.ts +59 -0
  213. package/test/declarative/fixtures/bindings/dot-syntax/state.json +16 -0
  214. package/test/declarative/fixtures/bindings/dot-syntax/templates.html +17 -0
  215. package/test/declarative/fixtures/bindings/event/entry.html +11 -0
  216. package/test/declarative/fixtures/bindings/event/fast-build.config.json +6 -0
  217. package/test/declarative/fixtures/bindings/event/index.html +43 -0
  218. package/test/declarative/fixtures/bindings/event/main.ts +43 -0
  219. package/test/declarative/fixtures/bindings/event/state.json +3 -0
  220. package/test/declarative/fixtures/bindings/event/templates.html +18 -0
  221. package/test/declarative/fixtures/bindings/host/entry.html +40 -0
  222. package/test/declarative/fixtures/bindings/host/fast-build.config.json +6 -0
  223. package/test/declarative/fixtures/bindings/host/index.html +96 -0
  224. package/test/declarative/fixtures/bindings/host/main.ts +222 -0
  225. package/test/declarative/fixtures/bindings/host/state.json +9 -0
  226. package/test/declarative/fixtures/bindings/host/templates.html +55 -0
  227. package/test/declarative/fixtures/directives/README.md +12 -0
  228. package/test/declarative/fixtures/directives/children/entry.html +11 -0
  229. package/test/declarative/fixtures/directives/children/fast-build.config.json +6 -0
  230. package/test/declarative/fixtures/directives/children/index.html +15 -0
  231. package/test/declarative/fixtures/directives/children/main.ts +22 -0
  232. package/test/declarative/fixtures/directives/children/state.json +3 -0
  233. package/test/declarative/fixtures/directives/children/templates.html +3 -0
  234. package/test/declarative/fixtures/directives/ref/entry.html +11 -0
  235. package/test/declarative/fixtures/directives/ref/fast-build.config.json +6 -0
  236. package/test/declarative/fixtures/directives/ref/index.html +15 -0
  237. package/test/declarative/fixtures/directives/ref/main.ts +17 -0
  238. package/test/declarative/fixtures/directives/ref/state.json +1 -0
  239. package/test/declarative/fixtures/directives/ref/templates.html +3 -0
  240. package/test/declarative/fixtures/directives/repeat/entry.html +21 -0
  241. package/test/declarative/fixtures/directives/repeat/fast-build.config.json +6 -0
  242. package/test/declarative/fixtures/directives/repeat/index.html +133 -0
  243. package/test/declarative/fixtures/directives/repeat/main.ts +110 -0
  244. package/test/declarative/fixtures/directives/repeat/sprites.svg +8 -0
  245. package/test/declarative/fixtures/directives/repeat/state.json +10 -0
  246. package/test/declarative/fixtures/directives/repeat/templates.html +75 -0
  247. package/test/declarative/fixtures/directives/slotted/entry.html +17 -0
  248. package/test/declarative/fixtures/directives/slotted/fast-build.config.json +6 -0
  249. package/test/declarative/fixtures/directives/slotted/index.html +27 -0
  250. package/test/declarative/fixtures/directives/slotted/main.ts +29 -0
  251. package/test/declarative/fixtures/directives/slotted/state.json +1 -0
  252. package/test/declarative/fixtures/directives/slotted/templates.html +7 -0
  253. package/test/declarative/fixtures/directives/when/entry.html +51 -0
  254. package/test/declarative/fixtures/directives/when/fast-build.config.json +6 -0
  255. package/test/declarative/fixtures/directives/when/index.html +136 -0
  256. package/test/declarative/fixtures/directives/when/main.ts +172 -0
  257. package/test/declarative/fixtures/directives/when/state.json +12 -0
  258. package/test/declarative/fixtures/directives/when/templates.html +75 -0
  259. package/test/declarative/fixtures/ecosystem/README.md +11 -0
  260. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/entry.html +12 -0
  261. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/fast-build.config.json +6 -0
  262. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/index.html +20 -0
  263. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/main.ts +68 -0
  264. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/state.json +4 -0
  265. package/test/declarative/fixtures/ecosystem/declarative-no-hydration/templates.html +7 -0
  266. package/test/declarative/fixtures/ecosystem/errors/entry.html +12 -0
  267. package/test/declarative/fixtures/ecosystem/errors/fast-build.config.json +6 -0
  268. package/test/declarative/fixtures/ecosystem/errors/index.html +20 -0
  269. package/test/declarative/fixtures/ecosystem/errors/main.ts +17 -0
  270. package/test/declarative/fixtures/ecosystem/errors/state.json +1 -0
  271. package/test/declarative/fixtures/ecosystem/errors/templates.html +7 -0
  272. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/entry.html +17 -0
  273. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/fast-build.config.json +6 -0
  274. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/index.html +56 -0
  275. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/main.ts +134 -0
  276. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/state.json +12 -0
  277. package/test/declarative/fixtures/ecosystem/lifecycle-callbacks/templates.html +34 -0
  278. package/test/declarative/fixtures/ecosystem/performance-metrics/entry.html +25 -0
  279. package/test/declarative/fixtures/ecosystem/performance-metrics/fast-build.config.json +6 -0
  280. package/test/declarative/fixtures/ecosystem/performance-metrics/fast-card.css +10 -0
  281. package/test/declarative/fixtures/ecosystem/performance-metrics/index.html +181 -0
  282. package/test/declarative/fixtures/ecosystem/performance-metrics/main.ts +58 -0
  283. package/test/declarative/fixtures/ecosystem/performance-metrics/state.json +6 -0
  284. package/test/declarative/fixtures/ecosystem/performance-metrics/templates.html +15 -0
  285. package/test/declarative/fixtures/extensions/README.md +15 -0
  286. package/test/declarative/fixtures/extensions/attribute-map/entry.html +14 -0
  287. package/test/declarative/fixtures/extensions/attribute-map/fast-build.config.json +6 -0
  288. package/test/declarative/fixtures/extensions/attribute-map/index.html +31 -0
  289. package/test/declarative/fixtures/extensions/attribute-map/main.ts +40 -0
  290. package/test/declarative/fixtures/extensions/attribute-map/state.json +4 -0
  291. package/test/declarative/fixtures/extensions/attribute-map/templates.html +14 -0
  292. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/entry.html +12 -0
  293. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/fast-build.config.json +7 -0
  294. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/index.html +25 -0
  295. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/main.ts +31 -0
  296. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/state.json +5 -0
  297. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy/templates.html +11 -0
  298. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/entry.html +13 -0
  299. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/fast-build.config.json +7 -0
  300. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/index.html +23 -0
  301. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/main.ts +37 -0
  302. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/state.json +1 -0
  303. package/test/declarative/fixtures/extensions/attribute-map-naming-strategy-camel-case/templates.html +9 -0
  304. package/test/declarative/fixtures/extensions/observer-map/entry.html +15 -0
  305. package/test/declarative/fixtures/extensions/observer-map/fast-build.config.json +6 -0
  306. package/test/declarative/fixtures/extensions/observer-map/index.html +442 -0
  307. package/test/declarative/fixtures/extensions/observer-map/main.ts +482 -0
  308. package/test/declarative/fixtures/extensions/observer-map/state.json +158 -0
  309. package/test/declarative/fixtures/extensions/observer-map/templates.html +172 -0
  310. package/test/declarative/fixtures/extensions/observer-map-config-object/entry.html +16 -0
  311. package/test/declarative/fixtures/extensions/observer-map-config-object/fast-build.config.json +6 -0
  312. package/test/declarative/fixtures/extensions/observer-map-config-object/index.html +27 -0
  313. package/test/declarative/fixtures/extensions/observer-map-config-object/main.ts +53 -0
  314. package/test/declarative/fixtures/extensions/observer-map-config-object/state.json +9 -0
  315. package/test/declarative/fixtures/extensions/observer-map-config-object/templates.html +12 -0
  316. package/test/declarative/fixtures/extensions/observer-map-deep-merge/README.md +98 -0
  317. package/test/declarative/fixtures/extensions/observer-map-deep-merge/entry.html +156 -0
  318. package/test/declarative/fixtures/extensions/observer-map-deep-merge/fast-build.config.json +6 -0
  319. package/test/declarative/fixtures/extensions/observer-map-deep-merge/index.html +376 -0
  320. package/test/declarative/fixtures/extensions/observer-map-deep-merge/main.ts +366 -0
  321. package/test/declarative/fixtures/extensions/observer-map-deep-merge/state.json +69 -0
  322. package/test/declarative/fixtures/extensions/observer-map-deep-merge/templates.html +91 -0
  323. package/test/declarative/fixtures/extensions/observer-map-properties/entry.html +14 -0
  324. package/test/declarative/fixtures/extensions/observer-map-properties/fast-build.config.json +6 -0
  325. package/test/declarative/fixtures/extensions/observer-map-properties/index.html +110 -0
  326. package/test/declarative/fixtures/extensions/observer-map-properties/main.ts +175 -0
  327. package/test/declarative/fixtures/extensions/observer-map-properties/state.json +29 -0
  328. package/test/declarative/fixtures/extensions/observer-map-properties/templates.html +55 -0
  329. package/test/declarative/fixtures/scenarios/README.md +7 -0
  330. package/test/declarative/fixtures/scenarios/nested-elements/entry.html +16 -0
  331. package/test/declarative/fixtures/scenarios/nested-elements/fast-build.config.json +6 -0
  332. package/test/declarative/fixtures/scenarios/nested-elements/index.html +126 -0
  333. package/test/declarative/fixtures/scenarios/nested-elements/main.ts +214 -0
  334. package/test/declarative/fixtures/scenarios/nested-elements/state.json +10 -0
  335. package/test/declarative/fixtures/scenarios/nested-elements/templates.html +54 -0
  336. package/test/declarative/index.html +12 -0
  337. package/test/declarative/vite.config.ts +55 -0
  338. package/test/declarative-main.ts +6 -0
  339. package/test/extension-subpaths-main.ts +9 -0
  340. package/test/main.ts +38 -33
  341. package/test/pure-declarative-main.ts +1 -0
  342. package/dist/dts/components/install-hydration.d.ts +0 -1
  343. package/dist/dts/pending-task.d.ts +0 -32
  344. package/dist/dts/polyfills.d.ts +0 -0
  345. package/dist/dts/styles/css-binding-directive.d.ts +0 -60
  346. package/dist/dts/templating/install-hydratable-view-templates.d.ts +0 -1
  347. package/dist/esm/components/install-hydration.js +0 -3
  348. package/dist/esm/pending-task.js +0 -28
  349. package/dist/esm/polyfills.js +0 -60
  350. package/dist/esm/styles/css-binding-directive.js +0 -76
  351. package/dist/esm/templating/install-hydratable-view-templates.js +0 -23
@@ -0,0 +1,100 @@
1
+ import { ensureHydrationRuntime } from "../hydration/runtime.js";
2
+ import { SourceLifetime } from "../observation/observable.js";
3
+ import { ElementController } from "./element-controller.js";
4
+ import { isHydratable } from "./hydration.js";
5
+ import { HydrationTracker } from "./hydration-tracker.js";
6
+ /**
7
+ * No-op handler used during prerendered bind to discard the
8
+ * upgrade-time burst of attributeChangedCallbacks.
9
+ */
10
+ function noopAttributeHandler() { }
11
+ let tracker = null;
12
+ let hookInstalled = false;
13
+ /**
14
+ * Enables hydration support for prerendered FAST elements.
15
+ *
16
+ * @remarks
17
+ * Call this before any FAST elements connect to the DOM. Hydration
18
+ * logic is not active unless this function is called, keeping
19
+ * `FASTElement` lightweight for client-side-only applications.
20
+ *
21
+ * Safe to call multiple times — the hydration hook is installed once
22
+ * and subsequent calls merge their options into the shared tracker.
23
+ *
24
+ * @example
25
+ * ```ts
26
+ * import { enableHydration } from "@microsoft/fast-element/hydration.js";
27
+ *
28
+ * enableHydration({
29
+ * hydrationComplete() {
30
+ * console.log("hydration complete");
31
+ * },
32
+ * });
33
+ * ```
34
+ *
35
+ * @param options - Optional callbacks for global hydration events.
36
+ * @public
37
+ */
38
+ export function enableHydration(options) {
39
+ ensureHydrationRuntime();
40
+ if (!hookInstalled) {
41
+ tracker = new HydrationTracker(options !== null && options !== void 0 ? options : {});
42
+ hookInstalled = true;
43
+ const activeTracker = tracker;
44
+ ElementController.installHydrationHook((controller, template, element, host) => {
45
+ var _a, _b;
46
+ if (!isHydratable(template)) {
47
+ return false;
48
+ }
49
+ const callbacks = controller.definition.lifecycleCallbacks;
50
+ activeTracker.add(element);
51
+ try {
52
+ try {
53
+ (_a = callbacks === null || callbacks === void 0 ? void 0 : callbacks.elementWillHydrate) === null || _a === void 0 ? void 0 : _a.call(callbacks, element);
54
+ }
55
+ catch (_c) {
56
+ // A lifecycle callback must never prevent hydration.
57
+ }
58
+ const firstChild = host.firstChild;
59
+ const lastChild = host.lastChild;
60
+ const view = template.hydrate(firstChild, lastChild, element);
61
+ controller.view = view;
62
+ const realHandler = controller.onAttributeChangedCallback;
63
+ controller.onAttributeChangedCallback = noopAttributeHandler;
64
+ try {
65
+ view._skipAttrUpdates = true;
66
+ view.isPrerendered = Promise.resolve(true);
67
+ view.isHydrated = Promise.resolve(true);
68
+ view.bind(controller.source);
69
+ view._skipAttrUpdates = false;
70
+ }
71
+ finally {
72
+ controller.onAttributeChangedCallback = realHandler;
73
+ }
74
+ view.sourceLifetime =
75
+ SourceLifetime.coupled;
76
+ controller.hasExistingShadowRoot = false;
77
+ try {
78
+ (_b = callbacks === null || callbacks === void 0 ? void 0 : callbacks.elementDidHydrate) === null || _b === void 0 ? void 0 : _b.call(callbacks, element);
79
+ }
80
+ catch (_d) {
81
+ // A lifecycle callback must never prevent post-hydration work.
82
+ }
83
+ }
84
+ finally {
85
+ activeTracker.remove(element);
86
+ }
87
+ return true;
88
+ });
89
+ }
90
+ else if (options && tracker) {
91
+ // Merge options into existing tracker for subsequent calls
92
+ tracker.mergeOptions(options);
93
+ }
94
+ }
95
+ /**
96
+ * The attribute used to defer hydration of an element.
97
+ * Retained for intersection observer viewport hydration rendering.
98
+ * @beta
99
+ */
100
+ export const deferHydrationAttribute = "defer-hydration";
@@ -8,11 +8,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  });
9
9
  };
10
10
  var _a;
11
- import { isString, KernelServiceId } from "../interfaces.js";
11
+ import { isFunction, isString } from "../interfaces.js";
12
12
  import { Observable } from "../observation/observable.js";
13
- import { createTypeRegistry, FAST } from "../platform.js";
13
+ import { createTypeRegistry } from "../platform.js";
14
14
  import { ElementStyles } from "../styles/element-styles.js";
15
- import { AttributeConfiguration, AttributeDefinition } from "./attributes.js";
15
+ import { AttributeDefinition } from "./attributes.js";
16
16
  const defaultShadowOptions = { mode: "open" };
17
17
  const defaultElementOptions = {};
18
18
  const fastElementBaseTypes = new Set();
@@ -20,14 +20,156 @@ const fastElementBaseTypes = new Set();
20
20
  * The FAST custom element registry
21
21
  * @internal
22
22
  */
23
- export const fastElementRegistry = FAST.getById(KernelServiceId.elementRegistry, () => createTypeRegistry());
23
+ export const fastElementRegistry = createTypeRegistry();
24
+ const templateResolvers = new WeakMap();
25
+ const pendingTemplateResolutions = new WeakMap();
26
+ const templateResolutionErrors = new WeakMap();
27
+ const registeredTypesByRegistry = new WeakMap();
28
+ const extensionRegistries = new WeakMap();
29
+ const lateAttributeLookups = new WeakMap();
30
+ function isFASTElementTemplateResolver(value) {
31
+ return isFunction(value);
32
+ }
33
+ function isPromiseLike(value) {
34
+ return typeof (value === null || value === void 0 ? void 0 : value.then) === "function";
35
+ }
36
+ function getRegisteredTypes(registry = customElements) {
37
+ if (registry === customElements) {
38
+ return FASTElementDefinition.isRegistered;
39
+ }
40
+ let registeredTypes = registeredTypesByRegistry.get(registry);
41
+ if (!registeredTypes) {
42
+ registeredTypes = {};
43
+ registeredTypesByRegistry.set(registry, registeredTypes);
44
+ }
45
+ return registeredTypes;
46
+ }
47
+ function finalizeResolvedTemplate(definition, template) {
48
+ var _b, _c;
49
+ pendingTemplateResolutions.delete(definition);
50
+ if (definition.template === void 0 && template !== void 0) {
51
+ definition.template = template;
52
+ (_c = (_b = definition.lifecycleCallbacks) === null || _b === void 0 ? void 0 : _b.templateDidUpdate) === null || _c === void 0 ? void 0 : _c.call(_b, definition.name);
53
+ }
54
+ if (definition.template !== void 0) {
55
+ templateResolutionErrors.delete(definition);
56
+ templateResolvers.delete(definition);
57
+ return definition.template;
58
+ }
59
+ return void 0;
60
+ }
24
61
  /**
25
- * Values for the `templateOptions` property.
26
- * @alpha
62
+ * Applies extension callbacks to a FAST element definition.
63
+ * @internal
27
64
  */
28
- export const TemplateOptions = {
29
- deferAndHydrate: "defer-and-hydrate",
30
- };
65
+ export function applyFASTElementExtensions(definition, registry = definition.registry, extensions) {
66
+ if (!(extensions === null || extensions === void 0 ? void 0 : extensions.length)) {
67
+ return;
68
+ }
69
+ const typedDefinition = definition;
70
+ let registries = extensionRegistries.get(typedDefinition);
71
+ if (registries === null || registries === void 0 ? void 0 : registries.has(registry)) {
72
+ return;
73
+ }
74
+ if (registries === void 0) {
75
+ registries = new WeakSet();
76
+ extensionRegistries.set(typedDefinition, registries);
77
+ }
78
+ registries.add(registry);
79
+ for (const extension of extensions) {
80
+ extension(definition);
81
+ }
82
+ }
83
+ /**
84
+ * Tracks attribute definitions that were added after the element was already
85
+ * registered with the platform and therefore are not covered by the browser's
86
+ * static observedAttributes snapshot.
87
+ * @internal
88
+ */
89
+ export function trackLateAttributeDefinition(definition, attribute) {
90
+ const typedDefinition = definition;
91
+ let lateAttributeLookup = lateAttributeLookups.get(typedDefinition);
92
+ if (lateAttributeLookup === void 0) {
93
+ const lookup = Object.create(null);
94
+ lateAttributeLookups.set(typedDefinition, lookup);
95
+ lateAttributeLookup = lookup;
96
+ }
97
+ lateAttributeLookup[attribute.attribute] = attribute;
98
+ }
99
+ /**
100
+ * Gets the attribute definitions that were added after platform registration.
101
+ * @internal
102
+ */
103
+ export function getLateAttributeLookup(definition) {
104
+ var _b;
105
+ return ((_b = lateAttributeLookups.get(definition)) !== null && _b !== void 0 ? _b : null);
106
+ }
107
+ /**
108
+ * Resolves the concrete template for a FAST element definition when the
109
+ * definition was composed with a template resolver.
110
+ * @internal
111
+ */
112
+ export function resolveFASTElementTemplate(definition) {
113
+ if (definition.template !== void 0) {
114
+ templateResolutionErrors.delete(definition);
115
+ return definition.template;
116
+ }
117
+ const pendingResolution = pendingTemplateResolutions.get(definition);
118
+ if (pendingResolution) {
119
+ return pendingResolution;
120
+ }
121
+ const templateResolver = templateResolvers.get(definition);
122
+ if (!templateResolver) {
123
+ return void 0;
124
+ }
125
+ templateResolutionErrors.delete(definition);
126
+ let template;
127
+ try {
128
+ template = templateResolver(definition);
129
+ }
130
+ catch (error) {
131
+ templateResolutionErrors.set(definition, error);
132
+ throw error;
133
+ }
134
+ if (isPromiseLike(template)) {
135
+ const resolution = Promise.resolve(template)
136
+ .then(resolvedTemplate => finalizeResolvedTemplate(definition, resolvedTemplate))
137
+ .catch(error => {
138
+ pendingTemplateResolutions.delete(definition);
139
+ templateResolutionErrors.set(definition, error);
140
+ throw error;
141
+ });
142
+ pendingTemplateResolutions.set(definition, resolution);
143
+ return resolution;
144
+ }
145
+ return finalizeResolvedTemplate(definition, template);
146
+ }
147
+ /**
148
+ * Indicates whether a definition still has a pending template resolver.
149
+ * @internal
150
+ */
151
+ export function hasFASTElementTemplateResolver(definition) {
152
+ return templateResolvers.has(definition);
153
+ }
154
+ /**
155
+ * Gets any pending template resolution error for a FAST element definition.
156
+ * @internal
157
+ */
158
+ export function getFASTElementTemplateError(definition) {
159
+ return templateResolutionErrors.get(definition);
160
+ }
161
+ /**
162
+ * Sets or clears the template resolution error for a FAST element definition.
163
+ * @internal
164
+ */
165
+ export function setFASTElementTemplateError(definition, error) {
166
+ const typedDefinition = definition;
167
+ if (error === void 0) {
168
+ templateResolutionErrors.delete(typedDefinition);
169
+ return;
170
+ }
171
+ templateResolutionErrors.set(typedDefinition, error);
172
+ }
31
173
  /**
32
174
  * Defines metadata for a FASTElement.
33
175
  * @public
@@ -39,7 +181,8 @@ export class FASTElementDefinition {
39
181
  get isDefined() {
40
182
  return this.platformDefined;
41
183
  }
42
- constructor(type, nameOrConfig = type.definition) {
184
+ constructor(type, nameOrConfig = type
185
+ .definition) {
43
186
  var _b;
44
187
  this.platformDefined = false;
45
188
  if (isString(nameOrConfig)) {
@@ -47,9 +190,13 @@ export class FASTElementDefinition {
47
190
  }
48
191
  this.type = type;
49
192
  this.name = nameOrConfig.name;
50
- this.template = nameOrConfig.template;
51
- this.templateOptions = nameOrConfig.templateOptions;
52
193
  this.registry = (_b = nameOrConfig.registry) !== null && _b !== void 0 ? _b : customElements;
194
+ if (isFASTElementTemplateResolver(nameOrConfig.template)) {
195
+ templateResolvers.set(this, nameOrConfig.template);
196
+ }
197
+ else {
198
+ this.template = nameOrConfig.template;
199
+ }
53
200
  const proto = type.prototype;
54
201
  const attributes = AttributeDefinition.collect(type, nameOrConfig.attributes);
55
202
  const observedAttributes = new Array(attributes.length);
@@ -80,20 +227,44 @@ export class FASTElementDefinition {
80
227
  ? defaultElementOptions
81
228
  : Object.assign(Object.assign({}, defaultElementOptions), nameOrConfig.elementOptions);
82
229
  this.styles = ElementStyles.normalize(nameOrConfig.styles);
230
+ this.schema = nameOrConfig.schema;
83
231
  fastElementRegistry.register(this);
84
- Observable.defineProperty(_a.isRegistered, this.name);
85
- _a.isRegistered[this.name] = this.type;
232
+ const registeredTypes = getRegisteredTypes(this.registry);
233
+ if (!Object.prototype.hasOwnProperty.call(registeredTypes, this.name)) {
234
+ Observable.defineProperty(registeredTypes, this.name);
235
+ }
236
+ registeredTypes[this.name] = this.type;
86
237
  }
87
238
  /**
88
239
  * Defines a custom element based on this definition.
89
240
  * @param registry - The element registry to define the element in.
241
+ * @param extensions - An optional array of extension callbacks to invoke
242
+ * with this definition before platform registration.
90
243
  * @remarks
91
244
  * This operation is idempotent per registry.
92
245
  */
93
- define(registry = this.registry) {
246
+ define(registry = this.registry, extensions) {
94
247
  var _b, _c;
95
248
  const type = this.type;
96
249
  if (!registry.get(this.name)) {
250
+ applyFASTElementExtensions(this, registry, extensions);
251
+ if (this.template === void 0 && templateResolvers.has(this)) {
252
+ void Promise.resolve()
253
+ .then(() => resolveFASTElementTemplate(this))
254
+ .then(template => {
255
+ var _b, _c;
256
+ if (template !== void 0 && !registry.get(this.name)) {
257
+ this.platformDefined = true;
258
+ registry.define(this.name, type, this.elementOptions);
259
+ (_c = (_b = this.lifecycleCallbacks) === null || _b === void 0 ? void 0 : _b.elementDidDefine) === null || _c === void 0 ? void 0 : _c.call(_b, this.name);
260
+ }
261
+ })
262
+ .catch(error => {
263
+ setFASTElementTemplateError(this, error);
264
+ Observable.notify(this, "template");
265
+ });
266
+ return this;
267
+ }
97
268
  this.platformDefined = true;
98
269
  registry.define(this.name, type, this.elementOptions);
99
270
  (_c = (_b = this.lifecycleCallbacks) === null || _b === void 0 ? void 0 : _b.elementDidDefine) === null || _c === void 0 ? void 0 : _c.call(_b, this.name);
@@ -107,11 +278,11 @@ export class FASTElementDefinition {
107
278
  * that describes the element to define.
108
279
  */
109
280
  static compose(type, nameOrDef) {
110
- if (fastElementBaseTypes.has(type) || fastElementRegistry.getByType(type)) {
111
- return new _a(class extends type {
112
- }, nameOrDef);
113
- }
114
- return new _a(type, nameOrDef);
281
+ const definition = fastElementBaseTypes.has(type) || fastElementRegistry.getByType(type)
282
+ ? new _a(class extends type {
283
+ }, nameOrDef)
284
+ : new _a(type, nameOrDef);
285
+ return Promise.resolve(definition);
115
286
  }
116
287
  /**
117
288
  * Registers a FASTElement base type.
@@ -121,31 +292,6 @@ export class FASTElementDefinition {
121
292
  static registerBaseType(type) {
122
293
  fastElementBaseTypes.add(type);
123
294
  }
124
- /**
125
- * Creates an instance of FASTElementDefinition asynchronously. This option assumes
126
- * that a template and shadowOptions will be provided and completes when those requirements
127
- * are met.
128
- * @param type - The type this definition is being created for.
129
- * @param nameOrDef - The name of the element to define or a config object
130
- * that describes the element to define.
131
- * @alpha
132
- */
133
- static composeAsync(type, nameOrDef) {
134
- return new Promise(resolve => {
135
- if (fastElementBaseTypes.has(type) || fastElementRegistry.getByType(type)) {
136
- resolve(new _a(class extends type {
137
- }, nameOrDef));
138
- }
139
- const definition = new _a(type, nameOrDef);
140
- Observable.getNotifier(definition).subscribe({
141
- handleChange: () => {
142
- var _b, _c;
143
- (_c = (_b = definition.lifecycleCallbacks) === null || _b === void 0 ? void 0 : _b.templateDidUpdate) === null || _c === void 0 ? void 0 : _c.call(_b, definition.name);
144
- resolve(definition);
145
- },
146
- }, "template");
147
- });
148
- }
149
295
  }
150
296
  _a = FASTElementDefinition;
151
297
  /**
@@ -167,12 +313,28 @@ FASTElementDefinition.getForInstance = fastElementRegistry.getForInstance;
167
313
  * @param name - The name of the defined custom element.
168
314
  * @alpha
169
315
  */
170
- FASTElementDefinition.registerAsync = (name) => __awaiter(void 0, void 0, void 0, function* () {
316
+ FASTElementDefinition.register = (name, registry = customElements) => __awaiter(void 0, void 0, void 0, function* () {
317
+ const registeredTypes = getRegisteredTypes(registry);
318
+ if (!Object.prototype.hasOwnProperty.call(registeredTypes, name)) {
319
+ Observable.defineProperty(registeredTypes, name);
320
+ }
171
321
  return new Promise(resolve => {
172
- if (_a.isRegistered[name]) {
173
- resolve(_a.isRegistered[name]);
322
+ if (registeredTypes[name]) {
323
+ resolve(registeredTypes[name]);
324
+ return;
174
325
  }
175
- Observable.getNotifier(_a.isRegistered).subscribe({ handleChange: () => resolve(_a.isRegistered[name]) }, name);
326
+ const notifier = Observable.getNotifier(registeredTypes);
327
+ const subscriber = {
328
+ handleChange: () => {
329
+ const value = registeredTypes[name];
330
+ if (!value) {
331
+ return;
332
+ }
333
+ notifier.unsubscribe(subscriber, name);
334
+ resolve(value);
335
+ },
336
+ };
337
+ notifier.subscribe(subscriber, name);
176
338
  });
177
339
  });
178
340
  Observable.defineProperty(FASTElementDefinition.prototype, "template");
@@ -1,6 +1,6 @@
1
1
  import { isFunction } from "../interfaces.js";
2
2
  import { ElementController } from "./element-controller.js";
3
- import { FASTElementDefinition, } from "./fast-definitions.js";
3
+ import { applyFASTElementExtensions, FASTElementDefinition, resolveFASTElementTemplate, } from "./fast-definitions.js";
4
4
  /* eslint-disable-next-line @typescript-eslint/explicit-function-return-type */
5
5
  function createFASTElement(BaseType) {
6
6
  const type = class extends BaseType {
@@ -31,29 +31,25 @@ function compose(type, nameOrDef) {
31
31
  }
32
32
  return FASTElementDefinition.compose(this, type);
33
33
  }
34
- function defineAsync(type, nameOrDef) {
35
- if (isFunction(type)) {
36
- return new Promise(resolve => {
37
- FASTElementDefinition.composeAsync(type, nameOrDef).then(value => {
38
- resolve(value);
39
- });
40
- }).then(value => {
41
- return value.define().type;
42
- });
43
- }
44
- return new Promise(resolve => {
45
- FASTElementDefinition.composeAsync(this, type).then(value => {
46
- resolve(value);
47
- });
48
- }).then(value => {
49
- return value.define().type;
50
- });
34
+ function isPromiseLike(value) {
35
+ return typeof (value === null || value === void 0 ? void 0 : value.then) === "function";
51
36
  }
52
- function define(type, nameOrDef) {
53
- if (isFunction(type)) {
54
- return FASTElementDefinition.compose(type, nameOrDef).define().type;
37
+ function define(type, nameOrDef, extensions) {
38
+ if (Array.isArray(nameOrDef)) {
39
+ extensions = nameOrDef;
40
+ nameOrDef = undefined;
55
41
  }
56
- return FASTElementDefinition.compose(this, type).define().type;
42
+ const composePromise = isFunction(type)
43
+ ? FASTElementDefinition.compose(type, nameOrDef)
44
+ : FASTElementDefinition.compose(this, type);
45
+ return composePromise.then(def => {
46
+ applyFASTElementExtensions(def, def.registry, extensions);
47
+ const template = resolveFASTElementTemplate(def);
48
+ if (isPromiseLike(template)) {
49
+ return template.then(() => def.define().type);
50
+ }
51
+ return def.define().type;
52
+ });
57
53
  }
58
54
  function from(BaseType) {
59
55
  return createFASTElement(BaseType);
@@ -82,11 +78,6 @@ export const FASTElement = Object.assign(createFASTElement(HTMLElement), {
82
78
  * @public
83
79
  */
84
80
  compose,
85
- /**
86
- * Defines metadata for a FASTElement which can be used after it has been resolved to define the element.
87
- * @alpha
88
- */
89
- defineAsync,
90
81
  });
91
82
  /**
92
83
  * Decorator: Defines a platform custom element based on `FASTElement`.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Tracks prerendered elements through the hydration lifecycle and
3
+ * fires global callbacks at start and completion. Per-element callbacks
4
+ * (`elementWillHydrate`, `elementDidHydrate`) are handled through
5
+ * definition-level `TemplateLifecycleCallbacks`.
6
+ *
7
+ * @public
8
+ */
9
+ export class HydrationTracker {
10
+ constructor(options) {
11
+ this.options = options;
12
+ this.elements = new Set();
13
+ this.started = false;
14
+ this.checkTimer = null;
15
+ }
16
+ /**
17
+ * Registers an element as pending hydration.
18
+ * Fires `hydrationStarted` on the first call.
19
+ */
20
+ add(element) {
21
+ var _a, _b;
22
+ if (!this.started) {
23
+ this.started = true;
24
+ try {
25
+ (_b = (_a = this.options).hydrationStarted) === null || _b === void 0 ? void 0 : _b.call(_a);
26
+ }
27
+ catch (_c) {
28
+ // A lifecycle callback must never prevent hydration.
29
+ }
30
+ }
31
+ this.elements.add(element);
32
+ }
33
+ /**
34
+ * Removes an element from the pending set and schedules
35
+ * a debounced completion check.
36
+ */
37
+ remove(element) {
38
+ this.elements.delete(element);
39
+ // Debounce: reset on every removal so we wait until no
40
+ // new elements arrive before declaring complete.
41
+ if (this.checkTimer !== null) {
42
+ clearTimeout(this.checkTimer);
43
+ }
44
+ if (this.elements.size === 0) {
45
+ this.checkTimer = setTimeout(() => {
46
+ var _a, _b;
47
+ this.checkTimer = null;
48
+ if (this.elements.size === 0) {
49
+ try {
50
+ (_b = (_a = this.options).hydrationComplete) === null || _b === void 0 ? void 0 : _b.call(_a);
51
+ }
52
+ catch (_c) {
53
+ // A lifecycle callback must never prevent post-hydration cleanup.
54
+ }
55
+ finally {
56
+ this.started = false;
57
+ }
58
+ }
59
+ }, 0);
60
+ }
61
+ }
62
+ /**
63
+ * Merges additional options into the tracker, chaining
64
+ * callbacks so both the original and new callbacks fire.
65
+ */
66
+ mergeOptions(incoming) {
67
+ const prev = this.options;
68
+ this.options = {
69
+ hydrationStarted: chainCallback(prev.hydrationStarted, incoming.hydrationStarted),
70
+ hydrationComplete: chainCallback(prev.hydrationComplete, incoming.hydrationComplete),
71
+ };
72
+ }
73
+ }
74
+ function chainCallback(first, second) {
75
+ if (!first)
76
+ return second;
77
+ if (!second)
78
+ return first;
79
+ return () => {
80
+ try {
81
+ first();
82
+ }
83
+ catch (_a) {
84
+ // Isolate callbacks so one consumer cannot suppress another.
85
+ }
86
+ try {
87
+ second();
88
+ }
89
+ catch (_b) {
90
+ // Isolate callbacks so one consumer cannot suppress another.
91
+ }
92
+ };
93
+ }