@faiwer/react 0.8.3 → 0.9.0

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 (239) hide show
  1. package/README.md +20 -14
  2. package/dist/core/Children.d.ts +11 -0
  3. package/dist/core/Children.d.ts.map +1 -0
  4. package/dist/core/Children.js +35 -0
  5. package/dist/core/Children.js.map +1 -0
  6. package/dist/core/actions/applyAction.d.ts.map +1 -1
  7. package/dist/core/actions/applyAction.js +2 -0
  8. package/dist/core/actions/applyAction.js.map +1 -1
  9. package/dist/core/actions/createComment.action.d.ts +2 -2
  10. package/dist/core/actions/createComment.action.d.ts.map +1 -1
  11. package/dist/core/actions/createComment.action.js +1 -8
  12. package/dist/core/actions/createComment.action.js.map +1 -1
  13. package/dist/core/actions/createContainer.action.d.ts +7 -0
  14. package/dist/core/actions/createContainer.action.d.ts.map +1 -0
  15. package/dist/core/actions/createContainer.action.js +28 -0
  16. package/dist/core/actions/createContainer.action.js.map +1 -0
  17. package/dist/core/actions/createTag.action.d.ts +2 -1
  18. package/dist/core/actions/createTag.action.d.ts.map +1 -1
  19. package/dist/core/actions/createTag.action.js +107 -5
  20. package/dist/core/actions/createTag.action.js.map +1 -1
  21. package/dist/core/actions/createText.action.d.ts.map +1 -1
  22. package/dist/core/actions/createText.action.js +2 -5
  23. package/dist/core/actions/createText.action.js.map +1 -1
  24. package/dist/core/actions/dom/attributes.d.ts +4 -0
  25. package/dist/core/actions/dom/attributes.d.ts.map +1 -0
  26. package/dist/core/actions/dom/attributes.js +56 -0
  27. package/dist/core/actions/dom/attributes.js.map +1 -0
  28. package/dist/core/actions/dom/css.d.ts +6 -0
  29. package/dist/core/actions/dom/css.d.ts.map +1 -0
  30. package/dist/core/actions/dom/css.js +54 -0
  31. package/dist/core/actions/dom/css.js.map +1 -0
  32. package/dist/core/actions/dom/events.d.ts +3 -0
  33. package/dist/core/actions/dom/events.d.ts.map +1 -0
  34. package/dist/core/actions/dom/events.js +45 -0
  35. package/dist/core/actions/dom/events.js.map +1 -0
  36. package/dist/core/actions/dom/svg.d.ts +7 -0
  37. package/dist/core/actions/dom/svg.d.ts.map +1 -0
  38. package/dist/core/actions/dom/svg.js +76 -0
  39. package/dist/core/actions/dom/svg.js.map +1 -0
  40. package/dist/core/actions/dom/value.d.ts +17 -0
  41. package/dist/core/actions/dom/value.d.ts.map +1 -0
  42. package/dist/core/actions/dom/value.js +204 -0
  43. package/dist/core/actions/dom/value.js.map +1 -0
  44. package/dist/core/actions/helpers.d.ts +18 -11
  45. package/dist/core/actions/helpers.d.ts.map +1 -1
  46. package/dist/core/actions/helpers.js +78 -68
  47. package/dist/core/actions/helpers.js.map +1 -1
  48. package/dist/core/actions/relayout.action.d.ts +2 -1
  49. package/dist/core/actions/relayout.action.d.ts.map +1 -1
  50. package/dist/core/actions/relayout.action.js +119 -30
  51. package/dist/core/actions/relayout.action.js.map +1 -1
  52. package/dist/core/actions/remove.action.d.ts +3 -2
  53. package/dist/core/actions/remove.action.d.ts.map +1 -1
  54. package/dist/core/actions/remove.action.js +22 -18
  55. package/dist/core/actions/remove.action.js.map +1 -1
  56. package/dist/core/actions/replace.action.d.ts +1 -1
  57. package/dist/core/actions/replace.action.d.ts.map +1 -1
  58. package/dist/core/actions/replace.action.js +36 -11
  59. package/dist/core/actions/replace.action.js.map +1 -1
  60. package/dist/core/actions/setAttr.action.d.ts +1 -1
  61. package/dist/core/actions/setAttr.action.d.ts.map +1 -1
  62. package/dist/core/actions/setAttr.action.js +55 -87
  63. package/dist/core/actions/setAttr.action.js.map +1 -1
  64. package/dist/core/actions/setProps.action.d.ts.map +1 -1
  65. package/dist/core/actions/setProps.action.js +2 -1
  66. package/dist/core/actions/setProps.action.js.map +1 -1
  67. package/dist/core/actions/setRef.action.d.ts +1 -1
  68. package/dist/core/actions/setRef.action.d.ts.map +1 -1
  69. package/dist/core/actions/setRef.action.js +5 -6
  70. package/dist/core/actions/setRef.action.js.map +1 -1
  71. package/dist/core/actions/setText.action.d.ts.map +1 -1
  72. package/dist/core/actions/setText.action.js +3 -3
  73. package/dist/core/actions/setText.action.js.map +1 -1
  74. package/dist/core/classComponent.d.ts +33 -0
  75. package/dist/core/classComponent.d.ts.map +1 -0
  76. package/dist/core/classComponent.js +127 -0
  77. package/dist/core/classComponent.js.map +1 -0
  78. package/dist/core/compact.d.ts +10 -29
  79. package/dist/core/compact.d.ts.map +1 -1
  80. package/dist/core/compact.js +12 -100
  81. package/dist/core/compact.js.map +1 -1
  82. package/dist/core/components.d.ts +2 -2
  83. package/dist/core/components.d.ts.map +1 -1
  84. package/dist/core/components.js +22 -5
  85. package/dist/core/components.js.map +1 -1
  86. package/dist/core/createElement.d.ts +9 -9
  87. package/dist/core/createElement.d.ts.map +1 -1
  88. package/dist/core/createElement.js +19 -3
  89. package/dist/core/createElement.js.map +1 -1
  90. package/dist/core/createRoot.js.map +1 -1
  91. package/dist/core/reactNodeToFiberNode.d.ts.map +1 -1
  92. package/dist/core/reactNodeToFiberNode.js +6 -1
  93. package/dist/core/reactNodeToFiberNode.js.map +1 -1
  94. package/dist/core/reconciliation/app.js +3 -3
  95. package/dist/core/reconciliation/app.js.map +1 -1
  96. package/dist/core/reconciliation/collect/fromApp.d.ts.map +1 -1
  97. package/dist/core/reconciliation/collect/fromApp.js +3 -27
  98. package/dist/core/reconciliation/collect/fromApp.js.map +1 -1
  99. package/dist/core/reconciliation/collect/fromChildrenPair.d.ts.map +1 -1
  100. package/dist/core/reconciliation/collect/fromChildrenPair.js +24 -15
  101. package/dist/core/reconciliation/collect/fromChildrenPair.js.map +1 -1
  102. package/dist/core/reconciliation/collect/fromComponent.d.ts +2 -2
  103. package/dist/core/reconciliation/collect/fromComponent.d.ts.map +1 -1
  104. package/dist/core/reconciliation/collect/fromComponent.js +4 -8
  105. package/dist/core/reconciliation/collect/fromComponent.js.map +1 -1
  106. package/dist/core/reconciliation/collect/fromFiberPair.d.ts.map +1 -1
  107. package/dist/core/reconciliation/collect/fromFiberPair.js +6 -4
  108. package/dist/core/reconciliation/collect/fromFiberPair.js.map +1 -1
  109. package/dist/core/reconciliation/collect/fromNewFiber.d.ts.map +1 -1
  110. package/dist/core/reconciliation/collect/fromNewFiber.js +7 -15
  111. package/dist/core/reconciliation/collect/fromNewFiber.js.map +1 -1
  112. package/dist/core/reconciliation/effects.d.ts.map +1 -1
  113. package/dist/core/reconciliation/effects.js +0 -5
  114. package/dist/core/reconciliation/effects.js.map +1 -1
  115. package/dist/core/reconciliation/errors/ReactError.d.ts +7 -0
  116. package/dist/core/reconciliation/errors/ReactError.d.ts.map +1 -0
  117. package/dist/core/reconciliation/errors/ReactError.js +26 -0
  118. package/dist/core/reconciliation/errors/ReactError.js.map +1 -0
  119. package/dist/core/reconciliation/errors/stack.d.ts +9 -0
  120. package/dist/core/reconciliation/errors/stack.d.ts.map +1 -0
  121. package/dist/core/reconciliation/errors/stack.js +80 -0
  122. package/dist/core/reconciliation/errors/stack.js.map +1 -0
  123. package/dist/core/reconciliation/fibers.d.ts +7 -0
  124. package/dist/core/reconciliation/fibers.d.ts.map +1 -1
  125. package/dist/core/reconciliation/fibers.js +9 -2
  126. package/dist/core/reconciliation/fibers.js.map +1 -1
  127. package/dist/core/reconciliation/heap.d.ts +18 -0
  128. package/dist/core/reconciliation/heap.d.ts.map +1 -0
  129. package/dist/core/reconciliation/heap.js +81 -0
  130. package/dist/core/reconciliation/heap.js.map +1 -0
  131. package/dist/core/reconciliation/invalidateFiber.d.ts.map +1 -1
  132. package/dist/core/reconciliation/invalidateFiber.js +10 -4
  133. package/dist/core/reconciliation/invalidateFiber.js.map +1 -1
  134. package/dist/core/reconciliation/mount.d.ts.map +1 -1
  135. package/dist/core/reconciliation/mount.js +17 -7
  136. package/dist/core/reconciliation/mount.js.map +1 -1
  137. package/dist/core/reconciliation/postCommit.d.ts +1 -1
  138. package/dist/core/reconciliation/postCommit.d.ts.map +1 -1
  139. package/dist/core/reconciliation/postCommit.js +19 -4
  140. package/dist/core/reconciliation/postCommit.js.map +1 -1
  141. package/dist/core/reconciliation/queue.d.ts +21 -0
  142. package/dist/core/reconciliation/queue.d.ts.map +1 -0
  143. package/dist/core/reconciliation/queue.js +55 -0
  144. package/dist/core/reconciliation/queue.js.map +1 -0
  145. package/dist/core/reconciliation/render.js +5 -5
  146. package/dist/core/reconciliation/render.js.map +1 -1
  147. package/dist/core/reconciliation/runFiberComponents.d.ts.map +1 -1
  148. package/dist/core/reconciliation/runFiberComponents.js +2 -1
  149. package/dist/core/reconciliation/runFiberComponents.js.map +1 -1
  150. package/dist/core/reconciliation/typeGuards.d.ts +9 -1
  151. package/dist/core/reconciliation/typeGuards.d.ts.map +1 -1
  152. package/dist/core/reconciliation/typeGuards.js +25 -0
  153. package/dist/core/reconciliation/typeGuards.js.map +1 -1
  154. package/dist/core/reconciliation/validateApp.d.ts +3 -0
  155. package/dist/core/reconciliation/validateApp.d.ts.map +1 -0
  156. package/dist/core/reconciliation/validateApp.js +74 -0
  157. package/dist/core/reconciliation/validateApp.js.map +1 -0
  158. package/dist/hooks/helpers.d.ts +2 -2
  159. package/dist/hooks/helpers.d.ts.map +1 -1
  160. package/dist/hooks/helpers.js +3 -2
  161. package/dist/hooks/helpers.js.map +1 -1
  162. package/dist/hooks/index.d.ts +1 -1
  163. package/dist/hooks/index.d.ts.map +1 -1
  164. package/dist/hooks/index.js +1 -1
  165. package/dist/hooks/index.js.map +1 -1
  166. package/dist/hooks/useContext.d.ts.map +1 -1
  167. package/dist/hooks/useContext.js +16 -0
  168. package/dist/hooks/useContext.js.map +1 -1
  169. package/dist/hooks/useEffect.d.ts +2 -1
  170. package/dist/hooks/useEffect.d.ts.map +1 -1
  171. package/dist/hooks/useEffect.js +1 -1
  172. package/dist/hooks/useEffect.js.map +1 -1
  173. package/dist/hooks/useRef.d.ts +8 -3
  174. package/dist/hooks/useRef.d.ts.map +1 -1
  175. package/dist/hooks/useRef.js +27 -0
  176. package/dist/hooks/useRef.js.map +1 -1
  177. package/dist/hooks/useState.d.ts +1 -1
  178. package/dist/hooks/useState.d.ts.map +1 -1
  179. package/dist/hooks/useState.js +24 -1
  180. package/dist/hooks/useState.js.map +1 -1
  181. package/dist/index.d.ts +8 -1
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js +5 -0
  184. package/dist/index.js.map +1 -1
  185. package/dist/jsx-dev-runtime.d.ts +4 -4
  186. package/dist/jsx-dev-runtime.d.ts.map +1 -1
  187. package/dist/jsx-dev-runtime.js +4 -4
  188. package/dist/jsx-dev-runtime.js.map +1 -1
  189. package/dist/jsx-runtime.d.ts +3 -3
  190. package/dist/jsx-runtime.d.ts.map +1 -1
  191. package/dist/jsx-runtime.js +3 -3
  192. package/dist/jsx-runtime.js.map +1 -1
  193. package/dist/jsx.d.ts +176 -36
  194. package/dist/mocks.d.ts +21 -0
  195. package/dist/mocks.d.ts.map +1 -0
  196. package/dist/mocks.js +27 -0
  197. package/dist/mocks.js.map +1 -0
  198. package/dist/react.d.ts +46 -0
  199. package/dist/types/actions.d.ts +12 -4
  200. package/dist/types/actions.d.ts.map +1 -1
  201. package/dist/types/app.d.ts +17 -2
  202. package/dist/types/app.d.ts.map +1 -1
  203. package/dist/types/attributes.d.ts +42 -0
  204. package/dist/types/attributes.d.ts.map +1 -0
  205. package/dist/types/attributes.js +2 -0
  206. package/dist/types/attributes.js.map +1 -0
  207. package/dist/types/common.d.ts +13 -0
  208. package/dist/types/common.d.ts.map +1 -0
  209. package/dist/types/common.js +2 -0
  210. package/dist/types/common.js.map +1 -0
  211. package/dist/types/component.d.ts +5 -1
  212. package/dist/types/component.d.ts.map +1 -1
  213. package/dist/types/context.d.ts +3 -2
  214. package/dist/types/context.d.ts.map +1 -1
  215. package/dist/types/core.d.ts +17 -13
  216. package/dist/types/core.d.ts.map +1 -1
  217. package/dist/types/dom.d.ts +23 -27
  218. package/dist/types/dom.d.ts.map +1 -1
  219. package/dist/types/events.d.ts +31 -0
  220. package/dist/types/events.d.ts.map +1 -0
  221. package/dist/types/events.js +2 -0
  222. package/dist/types/events.js.map +1 -0
  223. package/dist/types/fiber.d.ts +31 -11
  224. package/dist/types/fiber.d.ts.map +1 -1
  225. package/dist/types/fiber.js +5 -1
  226. package/dist/types/fiber.js.map +1 -1
  227. package/dist/types/hooks.d.ts +8 -5
  228. package/dist/types/hooks.d.ts.map +1 -1
  229. package/dist/types/react.d.ts +35 -0
  230. package/dist/types/react.d.ts.map +1 -0
  231. package/dist/types/react.js +2 -0
  232. package/dist/types/react.js.map +1 -0
  233. package/dist/types/refs.d.ts +5 -8
  234. package/dist/types/refs.d.ts.map +1 -1
  235. package/package.json +15 -3
  236. package/dist/core/reconciliation/validateTree.d.ts +0 -6
  237. package/dist/core/reconciliation/validateTree.d.ts.map +0 -1
  238. package/dist/core/reconciliation/validateTree.js +0 -48
  239. package/dist/core/reconciliation/validateTree.js.map +0 -1
@@ -0,0 +1,45 @@
1
+ import { ReactError } from '../../../core/reconciliation/errors/ReactError';
2
+ export const setEventHandler = (fiber, element, name, value) => {
3
+ const { events } = fiber.data;
4
+ if (value == null || value === false) {
5
+ if (events[name]) {
6
+ // Event handler was added before but now it's removed.
7
+ events[name].handler = null;
8
+ }
9
+ return;
10
+ }
11
+ if (typeof value !== 'function') {
12
+ throw new ReactError(fiber, `Unsupported format of event handler. It has to be "undefined" or a function`);
13
+ }
14
+ // Instead of adding and removing event handlers on every render, we can add a
15
+ // wrapper that calls `events[name]` and update only the internal
16
+ // function when it changes.
17
+ if (!events[name]) {
18
+ const capture = name.endsWith('Capture');
19
+ let eventName = name.slice(2).toLowerCase(); // onClick -> click.
20
+ if (capture) {
21
+ eventName = eventName.slice(0, eventName.length - 7);
22
+ }
23
+ if (eventName === 'change' &&
24
+ (fiber.tag === 'input' ||
25
+ fiber.tag === 'textarea' ||
26
+ fiber.tag === 'select')) {
27
+ eventName = 'input'; // Custom behavior. @see `./value.ts`.
28
+ }
29
+ events[name] = {
30
+ name: eventName,
31
+ handler: value,
32
+ capture,
33
+ wrapper: (event) => {
34
+ // Original React doesn't support stopping propagation on `false` return.
35
+ events[name].handler?.(event);
36
+ },
37
+ };
38
+ element.addEventListener(eventName, events[name].wrapper, { capture });
39
+ }
40
+ else {
41
+ // The tag is already listening to this event. Just update the internal ref.
42
+ events[name].handler = value;
43
+ }
44
+ };
45
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../../../src/core/actions/dom/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oDAAoD,CAAC;AAGhF,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,KAAmB,EACnB,OAAgB,EAChB,IAAY,EACZ,KAAmB,EACb,EAAE,CAAC;IACT,MAAM,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC;IAE9B,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,KAAK,EAAE,CAAC;QACrC,IAAI,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YACjB,uDAAuD;YACvD,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,IAAI,CAAC;QAC9B,CAAC;QACD,OAAO;IACT,CAAC;IAED,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;QAChC,MAAM,IAAI,UAAU,CAClB,KAAK,EACL,6EAA6E,CAC9E,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,iEAAiE;IACjE,4BAA4B;IAC5B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAClB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,oBAAoB;QACjE,IAAI,OAAO,EAAE,CAAC;YACZ,SAAS,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACvD,CAAC;QAED,IACE,SAAS,KAAK,QAAQ;YACtB,CAAC,KAAK,CAAC,GAAG,KAAK,OAAO;gBACpB,KAAK,CAAC,GAAG,KAAK,UAAU;gBACxB,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,EACzB,CAAC;YACD,SAAS,GAAG,OAAO,CAAC,CAAC,sCAAsC;QAC7D,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,GAAG;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,KAAK;YACd,OAAO;YACP,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE,CAAC;gBACzB,yEAAyE;gBACzE,MAAM,CAAC,IAAI,CAAE,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;YAAA,CAChC;SACF,CAAC;QACF,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACzE,CAAC;SAAM,CAAC;QACN,4EAA4E;QAC5E,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC;IAC/B,CAAC;AAAA,CACF,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * SVG is weird. Some of the attributes are in camelCase, and some are in
3
+ * kebab-case. This methods takes into account SVG-based nuances and sets the
4
+ * given attribute in the right way.
5
+ */
6
+ export declare const setSvgAttribute: (element: SVGElement, name: string, value: string) => void;
7
+ //# sourceMappingURL=svg.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.d.ts","sourceRoot":"","sources":["../../../../src/core/actions/dom/svg.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,eAAe,4DAW3B,CAAC"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * SVG is weird. Some of the attributes are in camelCase, and some are in
3
+ * kebab-case. This methods takes into account SVG-based nuances and sets the
4
+ * given attribute in the right way.
5
+ */
6
+ export const setSvgAttribute = (element, name, value) => {
7
+ if (name === 'className') {
8
+ name = 'class';
9
+ }
10
+ else if (!SVG_CAMEL_ATTRS.has(name)) {
11
+ name = name.replace(/[A-Z]/g, (m) => '-' + m.toLowerCase());
12
+ }
13
+ element.setAttribute(name, value);
14
+ };
15
+ // Most of SVG attributes are in kebab-cases. Here is the list of exclusions.
16
+ const SVG_CAMEL_ATTRS = new Set([
17
+ 'attributeName',
18
+ 'repeatCount',
19
+ 'attributeType',
20
+ 'baseFrequency',
21
+ 'baseProfile',
22
+ 'calcMode',
23
+ 'clipPathUnits',
24
+ 'diffuseConstant',
25
+ 'edgeMode',
26
+ 'Experimental',
27
+ 'filterUnits',
28
+ 'gradientTransform',
29
+ 'gradientUnits',
30
+ 'kernelMatrix',
31
+ 'kernelUnitLength',
32
+ 'keyPoints',
33
+ 'keySplines',
34
+ 'keyTimes',
35
+ 'lengthAdjust',
36
+ 'limitingConeAngle',
37
+ 'markerHeight',
38
+ 'markerUnits',
39
+ 'markerWidth',
40
+ 'maskContentUnits',
41
+ 'maskUnits',
42
+ 'numOctaves',
43
+ 'pathLength',
44
+ 'patternContentUnits',
45
+ 'patternTransform',
46
+ 'patternUnits',
47
+ 'pointsAtX',
48
+ 'pointsAtY',
49
+ 'pointsAtZ',
50
+ 'preserveAlpha',
51
+ 'preserveAspectRatio',
52
+ 'primitiveUnits',
53
+ 'refX',
54
+ 'refY',
55
+ 'repeatDur',
56
+ 'requiredExtensions',
57
+ 'requiredFeatures',
58
+ 'Experimental',
59
+ 'specularConstant',
60
+ 'specularExponent',
61
+ 'spreadMethod',
62
+ 'startOffset',
63
+ 'stdDeviation',
64
+ 'stitchTiles',
65
+ 'surfaceScale',
66
+ 'systemLanguage',
67
+ 'tableValues',
68
+ 'targetX',
69
+ 'targetY',
70
+ 'textLength',
71
+ 'viewBox',
72
+ 'xChannelSelector',
73
+ 'yChannelSelector',
74
+ 'zoomAndPan',
75
+ ]);
76
+ //# sourceMappingURL=svg.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svg.js","sourceRoot":"","sources":["../../../../src/core/actions/dom/svg.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAC7B,OAAmB,EACnB,IAAY,EACZ,KAAa,EACP,EAAE,CAAC;IACT,IAAI,IAAI,KAAK,WAAW,EAAE,CAAC;QACzB,IAAI,GAAG,OAAO,CAAC;IACjB,CAAC;SAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;QACtC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AAAA,CACnC,CAAC;AAEF,6EAA6E;AAC7E,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,eAAe;IACf,aAAa;IACb,eAAe;IACf,eAAe;IACf,aAAa;IACb,UAAU;IACV,eAAe;IACf,iBAAiB;IACjB,UAAU;IACV,cAAc;IACd,aAAa;IACb,mBAAmB;IACnB,eAAe;IACf,cAAc;IACd,kBAAkB;IAClB,WAAW;IACX,YAAY;IACZ,UAAU;IACV,cAAc;IACd,mBAAmB;IACnB,cAAc;IACd,aAAa;IACb,aAAa;IACb,kBAAkB;IAClB,WAAW;IACX,YAAY;IACZ,YAAY;IACZ,qBAAqB;IACrB,kBAAkB;IAClB,cAAc;IACd,WAAW;IACX,WAAW;IACX,WAAW;IACX,eAAe;IACf,qBAAqB;IACrB,gBAAgB;IAChB,MAAM;IACN,MAAM;IACN,WAAW;IACX,oBAAoB;IACpB,kBAAkB;IAClB,cAAc;IACd,kBAAkB;IAClB,kBAAkB;IAClB,cAAc;IACd,aAAa;IACb,cAAc;IACd,aAAa;IACb,cAAc;IACd,gBAAgB;IAChB,aAAa;IACb,SAAS;IACT,SAAS;IACT,YAAY;IACZ,SAAS;IACT,kBAAkB;IAClB,kBAAkB;IAClB,YAAY;CACb,CAAC,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { App, TagAttrValue, TagFiberNode } from '../../../types';
2
+ /**
3
+ * Original React has a very special behavior for the "onChange" event:
4
+ * - It treats "onChange" as an "onInput" event for form controls
5
+ * - If the "value" prop is provided and is not `null` or `undefined`, React
6
+ * treats the input as "controlled" and ignores user changes by restoring the
7
+ * original value after each input event
8
+ * - Even for controlled inputs, React still calls the "onChange" handler with
9
+ * the updated event.target.value before restoring the previous value
10
+ * - React overrides the property descriptor of the "value" property on the DOM
11
+ * element to intercept and track all value changes
12
+ */
13
+ export declare const setValueAttr: (fiber: TagFiberNode, attrName: "checked" | "value", attrValue: TagAttrValue) => void;
14
+ export declare const changeControlValue: (app: App, element: FormControl, attrName: "checked" | "value", valueRaw: unknown, restoreCursor?: boolean) => void;
15
+ type FormControl = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
16
+ export {};
17
+ //# sourceMappingURL=value.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value.d.ts","sourceRoot":"","sources":["../../../../src/core/actions/dom/value.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,GAAG,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAI1E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,YAAY,uFAsCxB,CAAC;AAmBF,eAAO,MAAM,kBAAkB,qHAiC9B,CAAC;AA2KF,KAAK,WAAW,GAAG,gBAAgB,GAAG,mBAAmB,GAAG,iBAAiB,CAAC"}
@@ -0,0 +1,204 @@
1
+ import { getAppByFiber } from '../../../core/reconciliation/app';
2
+ import { scheduleEffect } from '../../../core/reconciliation/effects';
3
+ import { nullthrowsForFiber } from '../../../core/reconciliation/errors/ReactError';
4
+ const stores = new WeakMap();
5
+ /**
6
+ * Original React has a very special behavior for the "onChange" event:
7
+ * - It treats "onChange" as an "onInput" event for form controls
8
+ * - If the "value" prop is provided and is not `null` or `undefined`, React
9
+ * treats the input as "controlled" and ignores user changes by restoring the
10
+ * original value after each input event
11
+ * - Even for controlled inputs, React still calls the "onChange" handler with
12
+ * the updated event.target.value before restoring the previous value
13
+ * - React overrides the property descriptor of the "value" property on the DOM
14
+ * element to intercept and track all value changes
15
+ */
16
+ export const setValueAttr = (fiber, attrName, attrValue) => {
17
+ const element = fiber.element;
18
+ const app = getAppByFiber(fiber);
19
+ // We continue to reference the same `events` object even after calling
20
+ // `displaceFiber`, so this assumption should hold
21
+ const { events } = fiber.data;
22
+ if (!events[VALUE_EVENT]) {
23
+ const store = setUpStore(app, element, attrName);
24
+ const onInput = createOnInputHandler(app, element, attrName, store);
25
+ events[VALUE_EVENT] = {
26
+ name: 'input',
27
+ handler: null,
28
+ capture: false,
29
+ wrapper: onInput,
30
+ };
31
+ element.addEventListener('input', onInput, {
32
+ capture: events[VALUE_EVENT].capture,
33
+ });
34
+ }
35
+ const store = nullthrowsForFiber(fiber, stores.get(element));
36
+ store.prev = attrValue;
37
+ if (attrValue != null) {
38
+ store.set(attrValue, true);
39
+ }
40
+ };
41
+ const VALUE_EVENT = 'x:input';
42
+ const setUpStore = (app, element, attrName) => {
43
+ const store = {
44
+ prev: null,
45
+ cursor: null,
46
+ set: changeControlValue.bind(null, app, element, attrName),
47
+ };
48
+ stores.set(element, store);
49
+ return store;
50
+ };
51
+ export const changeControlValue = (app, element, attrName, valueRaw, restoreCursor = false) => {
52
+ const value = toNativeValue(attrName, valueRaw);
53
+ if (element instanceof HTMLSelectElement) {
54
+ setSelectValue(app, element, value);
55
+ return;
56
+ }
57
+ if (element[attrName] === value) {
58
+ // Don't touch the value to avoid moving the cursor.
59
+ return;
60
+ }
61
+ // Non-reactively update the native value.
62
+ element[attrName] = value;
63
+ if ((element instanceof HTMLInputElement ||
64
+ element instanceof HTMLTextAreaElement) &&
65
+ attrName === 'value' &&
66
+ restoreCursor) {
67
+ const store = stores.get(element);
68
+ if (store.cursor != null) {
69
+ element.selectionStart = element.selectionEnd = store.cursor;
70
+ }
71
+ }
72
+ };
73
+ const createOnInputHandler = (app, element, attrName, store) => {
74
+ return function onInput() {
75
+ if (element instanceof HTMLInputElement &&
76
+ element.type === 'radio' &&
77
+ element.name) {
78
+ // Radio buttons require special group-based handling
79
+ onRadioClick(app, element);
80
+ return;
81
+ }
82
+ const newValue = element[attrName];
83
+ if (store.prev == null)
84
+ return; // Uncontrolled component - allow changes
85
+ if (store.prev === newValue)
86
+ return; // No actual change occurred
87
+ scheduleResetValueEffect(app, () => {
88
+ // The following render could make the control uncontrolled. In such a
89
+ // case we shouldn't restore the value. Now it's in free flight.
90
+ if (store.prev == null)
91
+ return;
92
+ if ((element instanceof HTMLInputElement ||
93
+ element instanceof HTMLTextAreaElement) &&
94
+ attrName === 'value') {
95
+ store.cursor = element.selectionStart;
96
+ }
97
+ // Restore the previous value since this is a controlled element
98
+ store.set(store.prev);
99
+ });
100
+ };
101
+ };
102
+ /**
103
+ * Radio button group handling:
104
+ *
105
+ * - Browsers don't emit "change" or "input" events for radio buttons that lose
106
+ * their "checked" state when another radio in the group is selected. The
107
+ * state change happens silently.
108
+ * - When a user selects a different radio button, the browser only emits an
109
+ * "input" event for the newly selected button. The event provides no
110
+ * information about which radio button was previously active.
111
+ * - Radio buttons form a group when they share the same "name" attribute within
112
+ * their containing <form> (or document if no form exists).
113
+ *
114
+ * This function enforces React's "controlled component" behavior for radio
115
+ * button groups. If any radio button in the group has "checked=true", all other
116
+ * radio buttons in the group must have "checked=false", even if they don't
117
+ * explicitly define a "checked" attribute (React assumes they do).
118
+ */
119
+ const onRadioClick = (app, element) => {
120
+ scheduleResetValueEffect(app, () => {
121
+ // Find all radio buttons in the same group (same name within the form)
122
+ const form = element.closest('form') ?? app.root.element;
123
+ const radios = form.querySelectorAll(`input[type="radio"]`);
124
+ // Look for a radio button that was previously controlled with checked=true
125
+ for (let i = 0; i < radios.length; ++i) {
126
+ const radio = radios[i];
127
+ if (radio.name === element.name && stores.get(radio)?.prev === true) {
128
+ // Restore the previously checked radio button's state, which will
129
+ // automatically uncheck the currently selected one. The correct state
130
+ // will be updated in the next render if setState was called from the
131
+ // user's onChange handler
132
+ stores.get(radio).set(true);
133
+ return;
134
+ }
135
+ }
136
+ const store = stores.get(element);
137
+ if (typeof store?.prev === 'boolean') {
138
+ // A single uncontrolled radio button with checked="false".
139
+ store.set(store.prev);
140
+ }
141
+ });
142
+ };
143
+ /**
144
+ * Converts React prop values to native DOM values:
145
+ * - value: null | undefined → '' (empty string, not "null")
146
+ * - checked: any value → boolean conversion
147
+ */
148
+ const toNativeValue = (attrName, newValue) => attrName === 'checked'
149
+ ? !!newValue
150
+ : newValue == null
151
+ ? '' // not "null"
152
+ : Array.isArray(newValue)
153
+ ? newValue.map((v) => String(v))
154
+ : String(newValue);
155
+ /**
156
+ * Schedules value restoration for controlled form elements.
157
+ *
158
+ * React maintains the value attribute for "controlled" HTML form controls,
159
+ * where only setState and subsequent renders can update their value. However,
160
+ * there's a brief window between the "onInput" event and the DOM/React render
161
+ * where the new value hasn't been reset yet. This function ensures the callback
162
+ * runs at the appropriate time to restore the controlled value.
163
+ */
164
+ const scheduleResetValueEffect = (app, fn) => {
165
+ let executed = false;
166
+ requestAnimationFrame(() => {
167
+ if (!executed) {
168
+ executed = true;
169
+ fn();
170
+ }
171
+ });
172
+ scheduleEffect(app, () => {
173
+ if (!executed) {
174
+ executed = true;
175
+ fn();
176
+ }
177
+ }, 'afterActions');
178
+ };
179
+ /**
180
+ * <select/> & <select multiple/> are very special cases.
181
+ * - When it has only one item selected its behavior is similar to single-mode
182
+ * selects. `value` reflects the only selected option's value.
183
+ * - When there is a multiple selection `value` reflects only the name of the
184
+ * 1st selected option, completely ignoring the rest of them.
185
+ *
186
+ * So, how do we handle it without `value`? We just need to update `selected`
187
+ * for each of the <option/>s.
188
+ */
189
+ const setSelectValue = (app, element, value) => {
190
+ // Unfortunately, we can't do it right away, because:
191
+ // 1. on the 1st render we have no inner options here yet
192
+ // 2. on subsequent render the inner options may not be fully updated yet.
193
+ scheduleResetValueEffect(app, () => {
194
+ const arr = Array.isArray(value) ? value : [value];
195
+ const set = new Set(arr.map((v) => String(v)));
196
+ for (const option of element.options) {
197
+ const selected = set.has(option.value);
198
+ if (option.selected !== selected) {
199
+ option.selected = selected;
200
+ }
201
+ }
202
+ });
203
+ };
204
+ //# sourceMappingURL=value.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"value.js","sourceRoot":"","sources":["../../../../src/core/actions/dom/value.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { DomNode, FiberNode, Ref, RefSetter } from '../../types';
1
+ import { type DomNode, type FiberNode, type TagFiberNode } from '../../types';
2
2
  /**
3
3
  * Determines if a prop name represents an event handler by checking if it
4
4
  * starts with "on". This follows React's convention where any prop beginning
@@ -13,31 +13,38 @@ import type { DomNode, FiberNode, Ref, RefSetter } from '../../types';
13
13
  export declare const isEventName: (name: string) => boolean;
14
14
  /**
15
15
  * Returns the DOM container for the given fiber node. This isn't always the
16
- * direct parent's element since the parent might be a compact node or a
17
- * fragment-like range (<!--begin|end-->), or it could be a portal node.
16
+ * direct parent's element since the parent might be a component, a fragment, or
17
+ * a portal node.
18
18
  */
19
19
  export declare const getParentElement: (fiber: FiberNode) => Element;
20
+ export declare const asElement: (node: Node | null) => Element;
20
21
  /**
21
- * Finds the anchor node for attaching other nodes. There are two scenarios:
22
- * 1) [element, null] - the new node should be added to the beginning of the
23
- * element;
24
- * 2) [element, child] - the new node should be added right after `child`.
22
+ * Returns the 1st DOM-node of the given auto-container fiber. Pass custom
23
+ * `children` if `fiber`'s children are incorrect.
25
24
  */
26
- export declare const getAnchor: (fiber: FiberNode) => [Element, Node | null];
25
+ export declare const getFirstContainerElement: (fiber: FiberNode, children?: FiberNode[]) => DomNode;
26
+ /** Returns the last DOM-node of the given auto-container fiber */
27
+ export declare const getLastContainerElement: (fiber: FiberNode) => DomNode;
27
28
  /**
28
29
  * Returns all direct DOM nodes associated with the given fiber. This isn't
29
- * always a single node since components and fragments may be in expanded state
30
- * (<!--begin--> + content + <!--end-->).
30
+ * always a single node since components and fragments may be in the
31
+ * auto-container mode. That means they contain more then one direct DOM-nodes
32
+ * that are inlined into the `fiber`'s DOM container.
31
33
  */
32
34
  export declare const getFiberDomNodes: (fiber: FiberNode) => DomNode[];
33
35
  /**
34
36
  * When a node leaves the DOM tree, we need to update all associated ref
35
37
  * objects and ref handlers.
36
38
  */
37
- export declare const unsetRef: <T>(ref: Ref<T | null> | RefSetter<T | null>) => void;
39
+ export declare const unsetRef: (fiber: TagFiberNode, immediate: boolean) => void;
38
40
  /**
39
41
  * To help avoid memory leaks, this method removes fiber properties that
40
42
  * can hold references to other objects.
41
43
  */
42
44
  export declare const emptyFiberNode: (fiber: FiberNode) => void;
45
+ /**
46
+ * Calls the given fn against every single child in the fiben fiber tree.
47
+ * Return `false` to stop traversing right away.
48
+ */
49
+ export declare const traverseFiberTree: (fiber: FiberNode, fn: (fiber: FiberNode) => void | boolean) => boolean;
43
50
  //# sourceMappingURL=helpers.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/core/actions/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAM7E;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,2BAAmD,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,+BAa5B,CAAC;AA6BF;;;;;GAKG;AACH,eAAO,MAAM,SAAS,8CAiCrB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,iCAwB5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,GAAI,CAAC,mDAMzB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,4BAQ1B,CAAC"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/core/actions/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,YAAY,EAClB,MAAM,oBAAoB,CAAC;AAc5B;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,2BAAmD,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,+BAa5B,CAAC;AAEF,eAAO,MAAM,SAAS,gCAMrB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,uDAUpC,CAAC;AAEF,kEAAkE;AAClE,eAAO,MAAM,uBAAuB,+BAOnC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,iCAuC5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,QAAQ,mDAsBpB,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,4BAW1B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,yEAe7B,CAAC"}
@@ -1,7 +1,8 @@
1
- import { nullthrows } from '../../utils';
2
- import { isBeginOf, isCompactNone, isCompactSingleChild } from '../compact';
3
- import { NULL_FIBER } from '../reconciliation/fibers';
4
- import { buildCommentText } from '../reconciliation/comments';
1
+ import { isEmptyContainer, isSingleChildContainer, isAutoContainer, } from '../compact';
2
+ import { isFiberDead, NULL_FIBER } from '../reconciliation/fibers';
3
+ import { scheduleEffect } from '../reconciliation/effects';
4
+ import { getAppByFiber } from '../reconciliation/app';
5
+ import { nullthrowsForFiber, ReactError, } from '../reconciliation/errors/ReactError';
5
6
  /**
6
7
  * Determines if a prop name represents an event handler by checking if it
7
8
  * starts with "on". This follows React's convention where any prop beginning
@@ -16,8 +17,8 @@ import { buildCommentText } from '../reconciliation/comments';
16
17
  export const isEventName = (name) => name.startsWith('on');
17
18
  /**
18
19
  * Returns the DOM container for the given fiber node. This isn't always the
19
- * direct parent's element since the parent might be a compact node or a
20
- * fragment-like range (<!--begin|end-->), or it could be a portal node.
20
+ * direct parent's element since the parent might be a component, a fragment, or
21
+ * a portal node.
21
22
  */
22
23
  export const getParentElement = (fiber) => {
23
24
  while (fiber.parent.type === 'component' ||
@@ -27,99 +28,91 @@ export const getParentElement = (fiber) => {
27
28
  if (fiber.parent.data instanceof HTMLElement) {
28
29
  return fiber.parent.data; // Portal.
29
30
  }
30
- return nullthrows(fiber.parent?.element);
31
+ return nullthrowsForFiber(fiber, fiber.parent?.element);
31
32
  };
32
- /**
33
- * Finds the !--begin comment for the given !--end comment.
34
- */
35
- const getBeginComment = (fiber) => {
36
- let node = asComment(fiber.element).previousSibling;
37
- const text = buildCommentText('begin', fiber.id);
38
- while (!(node instanceof Comment) || node.textContent !== text)
39
- node = nullthrows(node.previousSibling);
40
- return node;
41
- };
42
- const asElement = (node) => {
33
+ export const asElement = (node) => {
43
34
  if (!(node instanceof Element)) {
44
35
  throw new Error(`node is not element`);
45
36
  }
46
37
  return node;
47
38
  };
48
- const asComment = (node) => {
49
- if (!(node instanceof Comment)) {
50
- throw new Error(`node is not comment`);
51
- }
52
- return node;
53
- };
54
39
  /**
55
- * Finds the anchor node for attaching other nodes. There are two scenarios:
56
- * 1) [element, null] - the new node should be added to the beginning of the
57
- * element;
58
- * 2) [element, child] - the new node should be added right after `child`.
40
+ * Returns the 1st DOM-node of the given auto-container fiber. Pass custom
41
+ * `children` if `fiber`'s children are incorrect.
59
42
  */
60
- export const getAnchor = (fiber) => {
61
- if (fiber.type === 'tag') {
62
- return [
63
- asElement(fiber.data instanceof HTMLElement
64
- ? fiber.data // Portal's `element` is !--r:portal
65
- : fiber.element),
66
- null,
67
- ];
43
+ export const getFirstContainerElement = (fiber, children = fiber.children) => {
44
+ let [firstNode] = children;
45
+ while (!(firstNode.element instanceof Node)) {
46
+ [firstNode] = firstNode.children;
68
47
  }
69
- if (fiber.type === 'component' || fiber.type === 'fragment') {
70
- if (isCompactSingleChild(fiber)) {
71
- throw new Error(`Solo-compact fibers cannot be used as an anchor`);
72
- }
73
- if (isCompactNone(fiber)) {
74
- throw new Error(`Cannot use !--empty node as an anchor`);
75
- }
76
- // E.g.
77
- // <div>
78
- // <something/>
79
- // <!--r:begin:1--> // a component or a fragment
80
- // … // the content of the `fiber`
81
- // <!--r:end:1-->
82
- // <something/>
83
- return [getParentElement(fiber), getBeginComment(fiber)];
48
+ return firstNode.element;
49
+ };
50
+ /** Returns the last DOM-node of the given auto-container fiber */
51
+ export const getLastContainerElement = (fiber) => {
52
+ let lastNode = fiber.children.at(-1);
53
+ while (!(lastNode.element instanceof Node)) {
54
+ lastNode = lastNode.children.at(-1);
84
55
  }
85
- // "text" & "null" types cannot contain children.
86
- throw new Error(`Unsupported anchor type: ${fiber.type}`);
56
+ return lastNode.element;
87
57
  };
88
58
  /**
89
59
  * Returns all direct DOM nodes associated with the given fiber. This isn't
90
- * always a single node since components and fragments may be in expanded state
91
- * (<!--begin--> + content + <!--end-->).
60
+ * always a single node since components and fragments may be in the
61
+ * auto-container mode. That means they contain more then one direct DOM-nodes
62
+ * that are inlined into the `fiber`'s DOM container.
92
63
  */
93
64
  export const getFiberDomNodes = (fiber) => {
65
+ if (isFiberDead(fiber)) {
66
+ throw new ReactError(fiber, `Can't get fiber children for a dead fiber`);
67
+ }
94
68
  switch (fiber.type) {
95
69
  case 'component':
96
70
  case 'fragment': {
97
- if (isCompactSingleChild(fiber) || isCompactNone(fiber)) {
98
- return [fiber.element];
71
+ if (isAutoContainer(fiber)) {
72
+ const first = getFirstContainerElement(fiber);
73
+ const last = getLastContainerElement(fiber);
74
+ const result = [first];
75
+ let domNode = first.nextSibling;
76
+ while (domNode !== last) {
77
+ result.push(domNode);
78
+ domNode = domNode.nextSibling;
79
+ }
80
+ result.push(last);
81
+ return result;
82
+ }
83
+ if (isSingleChildContainer(fiber)) {
84
+ return getFiberDomNodes(fiber.children[0]);
99
85
  }
100
- // Collect [!--begin, …content, !--end]:
101
- const list = [nullthrows(fiber.element)];
102
- let prev = nullthrows(list[0].previousSibling);
103
- while (prev && !isBeginOf(prev, fiber)) {
104
- list.push(prev);
105
- prev = nullthrows(prev.previousSibling);
86
+ if (isEmptyContainer(fiber)) {
87
+ return [fiber.element];
106
88
  }
107
- list.push(prev);
108
- return list.reverse();
89
+ throw new ReactError(fiber, `Unknown kind of fiber`);
109
90
  }
110
91
  case 'null':
111
92
  case 'tag':
112
93
  case 'text':
113
- return [nullthrows(fiber.element)];
94
+ return [nullthrowsForFiber(fiber, fiber.element)];
114
95
  }
115
96
  };
116
97
  /**
117
98
  * When a node leaves the DOM tree, we need to update all associated ref
118
99
  * objects and ref handlers.
119
100
  */
120
- export const unsetRef = (ref) => {
101
+ export const unsetRef = (fiber, immediate) => {
102
+ const { ref } = fiber;
121
103
  if (typeof ref === 'function') {
122
- ref(null);
104
+ if (immediate) {
105
+ ref(null);
106
+ // TODO: add a test ^.
107
+ }
108
+ else {
109
+ // It can be a setter (e.g., <div onRef={setContainer}/>). Since we
110
+ // shouldn't allow invalidating components during commit phase we need
111
+ // to schedule an async update.
112
+ scheduleEffect(getAppByFiber(fiber), () => {
113
+ ref(null);
114
+ }, 'refsUnmount');
115
+ }
123
116
  }
124
117
  else {
125
118
  ref.current = null;
@@ -130,6 +123,8 @@ export const unsetRef = (ref) => {
130
123
  * can hold references to other objects.
131
124
  */
132
125
  export const emptyFiberNode = (fiber) => {
126
+ // For debug purposes mark dead nodes with a negative number.
127
+ fiber.id = -fiber.id;
133
128
  fiber.data = null;
134
129
  fiber.element = null;
135
130
  fiber.component = null;
@@ -138,4 +133,19 @@ export const emptyFiberNode = (fiber) => {
138
133
  fiber.ref = null;
139
134
  fiber.parent = NULL_FIBER;
140
135
  };
136
+ /**
137
+ * Calls the given fn against every single child in the fiben fiber tree.
138
+ * Return `false` to stop traversing right away.
139
+ */
140
+ export const traverseFiberTree = (fiber, fn) => {
141
+ if (fn(fiber) === false) {
142
+ return false;
143
+ }
144
+ for (const child of fiber.children) {
145
+ if (traverseFiberTree(child, fn) === false) {
146
+ return false;
147
+ }
148
+ }
149
+ return true;
150
+ };
141
151
  //# sourceMappingURL=helpers.js.map