提交学习笔记专用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
7.2 KiB

  1. "use strict";
  2. Object.defineProperty(exports, "__esModule", { value: true });
  3. exports.ReactiveFlags = void 0;
  4. exports.createReactiveSystem = createReactiveSystem;
  5. var ReactiveFlags;
  6. (function (ReactiveFlags) {
  7. ReactiveFlags[ReactiveFlags["None"] = 0] = "None";
  8. ReactiveFlags[ReactiveFlags["Mutable"] = 1] = "Mutable";
  9. ReactiveFlags[ReactiveFlags["Watching"] = 2] = "Watching";
  10. ReactiveFlags[ReactiveFlags["RecursedCheck"] = 4] = "RecursedCheck";
  11. ReactiveFlags[ReactiveFlags["Recursed"] = 8] = "Recursed";
  12. ReactiveFlags[ReactiveFlags["Dirty"] = 16] = "Dirty";
  13. ReactiveFlags[ReactiveFlags["Pending"] = 32] = "Pending";
  14. })(ReactiveFlags || (exports.ReactiveFlags = ReactiveFlags = {}));
  15. function createReactiveSystem({ update, notify, unwatched, }) {
  16. return {
  17. link,
  18. unlink,
  19. propagate,
  20. checkDirty,
  21. shallowPropagate,
  22. };
  23. function link(dep, sub, version) {
  24. const prevDep = sub.depsTail;
  25. if (prevDep !== undefined && prevDep.dep === dep) {
  26. return;
  27. }
  28. const nextDep = prevDep !== undefined ? prevDep.nextDep : sub.deps;
  29. if (nextDep !== undefined && nextDep.dep === dep) {
  30. nextDep.version = version;
  31. sub.depsTail = nextDep;
  32. return;
  33. }
  34. const prevSub = dep.subsTail;
  35. if (prevSub !== undefined && prevSub.version === version && prevSub.sub === sub) {
  36. return;
  37. }
  38. const newLink = sub.depsTail
  39. = dep.subsTail
  40. = {
  41. version,
  42. dep,
  43. sub,
  44. prevDep,
  45. nextDep,
  46. prevSub,
  47. nextSub: undefined,
  48. };
  49. if (nextDep !== undefined) {
  50. nextDep.prevDep = newLink;
  51. }
  52. if (prevDep !== undefined) {
  53. prevDep.nextDep = newLink;
  54. }
  55. else {
  56. sub.deps = newLink;
  57. }
  58. if (prevSub !== undefined) {
  59. prevSub.nextSub = newLink;
  60. }
  61. else {
  62. dep.subs = newLink;
  63. }
  64. }
  65. function unlink(link, sub = link.sub) {
  66. const dep = link.dep;
  67. const prevDep = link.prevDep;
  68. const nextDep = link.nextDep;
  69. const nextSub = link.nextSub;
  70. const prevSub = link.prevSub;
  71. if (nextDep !== undefined) {
  72. nextDep.prevDep = prevDep;
  73. }
  74. else {
  75. sub.depsTail = prevDep;
  76. }
  77. if (prevDep !== undefined) {
  78. prevDep.nextDep = nextDep;
  79. }
  80. else {
  81. sub.deps = nextDep;
  82. }
  83. if (nextSub !== undefined) {
  84. nextSub.prevSub = prevSub;
  85. }
  86. else {
  87. dep.subsTail = prevSub;
  88. }
  89. if (prevSub !== undefined) {
  90. prevSub.nextSub = nextSub;
  91. }
  92. else if ((dep.subs = nextSub) === undefined) {
  93. unwatched(dep);
  94. }
  95. return nextDep;
  96. }
  97. function propagate(link) {
  98. let next = link.nextSub;
  99. let stack;
  100. top: do {
  101. const sub = link.sub;
  102. let flags = sub.flags;
  103. if (!(flags & 60)) {
  104. sub.flags = flags | 32;
  105. }
  106. else if (!(flags & 12)) {
  107. flags = 0;
  108. }
  109. else if (!(flags & 4)) {
  110. sub.flags = (flags & ~8) | 32;
  111. }
  112. else if (!(flags & 48) && isValidLink(link, sub)) {
  113. sub.flags = flags | 40;
  114. flags &= 1;
  115. }
  116. else {
  117. flags = 0;
  118. }
  119. if (flags & 2) {
  120. notify(sub);
  121. }
  122. if (flags & 1) {
  123. const subSubs = sub.subs;
  124. if (subSubs !== undefined) {
  125. const nextSub = (link = subSubs).nextSub;
  126. if (nextSub !== undefined) {
  127. stack = { value: next, prev: stack };
  128. next = nextSub;
  129. }
  130. continue;
  131. }
  132. }
  133. if ((link = next) !== undefined) {
  134. next = link.nextSub;
  135. continue;
  136. }
  137. while (stack !== undefined) {
  138. link = stack.value;
  139. stack = stack.prev;
  140. if (link !== undefined) {
  141. next = link.nextSub;
  142. continue top;
  143. }
  144. }
  145. break;
  146. } while (true);
  147. }
  148. function checkDirty(link, sub) {
  149. let stack;
  150. let checkDepth = 0;
  151. let dirty = false;
  152. top: do {
  153. const dep = link.dep;
  154. const flags = dep.flags;
  155. if (sub.flags & 16) {
  156. dirty = true;
  157. }
  158. else if ((flags & 17) === 17) {
  159. if (update(dep)) {
  160. const subs = dep.subs;
  161. if (subs.nextSub !== undefined) {
  162. shallowPropagate(subs);
  163. }
  164. dirty = true;
  165. }
  166. }
  167. else if ((flags & 33) === 33) {
  168. if (link.nextSub !== undefined || link.prevSub !== undefined) {
  169. stack = { value: link, prev: stack };
  170. }
  171. link = dep.deps;
  172. sub = dep;
  173. ++checkDepth;
  174. continue;
  175. }
  176. if (!dirty) {
  177. const nextDep = link.nextDep;
  178. if (nextDep !== undefined) {
  179. link = nextDep;
  180. continue;
  181. }
  182. }
  183. while (checkDepth--) {
  184. const firstSub = sub.subs;
  185. const hasMultipleSubs = firstSub.nextSub !== undefined;
  186. if (hasMultipleSubs) {
  187. link = stack.value;
  188. stack = stack.prev;
  189. }
  190. else {
  191. link = firstSub;
  192. }
  193. if (dirty) {
  194. if (update(sub)) {
  195. if (hasMultipleSubs) {
  196. shallowPropagate(firstSub);
  197. }
  198. sub = link.sub;
  199. continue;
  200. }
  201. dirty = false;
  202. }
  203. else {
  204. sub.flags &= ~32;
  205. }
  206. sub = link.sub;
  207. const nextDep = link.nextDep;
  208. if (nextDep !== undefined) {
  209. link = nextDep;
  210. continue top;
  211. }
  212. }
  213. return dirty;
  214. } while (true);
  215. }
  216. function shallowPropagate(link) {
  217. do {
  218. const sub = link.sub;
  219. const flags = sub.flags;
  220. if ((flags & 48) === 32) {
  221. sub.flags = flags | 16;
  222. if (flags & 2) {
  223. notify(sub);
  224. }
  225. }
  226. } while ((link = link.nextSub) !== undefined);
  227. }
  228. function isValidLink(checkLink, sub) {
  229. let link = sub.depsTail;
  230. while (link !== undefined) {
  231. if (link === checkLink) {
  232. return true;
  233. }
  234. link = link.prevDep;
  235. }
  236. return false;
  237. }
  238. }