@unsetsoft/ryunixjs 0.1.14-beta.0 → 0.2.0-beta.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.
package/lib/dom.js ADDED
@@ -0,0 +1,409 @@
1
+ /**
2
+ * The function creates a new element with the given type, props, and children.
3
+ * @param type - The type of the element to be created, such as "div", "span", "h1", etc.
4
+ * @param props - The `props` parameter is an object that contains the properties or attributes of the
5
+ * element being created. These properties can include things like `className`, `id`, `style`, and any
6
+ * other custom attributes that the user wants to add to the element. The `props` object is spread
7
+ * using the spread
8
+ * @param children - The `children` parameter is a rest parameter that allows the function to accept
9
+ * any number of arguments after the `props` parameter. These arguments will be treated as children
10
+ * elements of the created element. The `map` function is used to iterate over each child and create a
11
+ * new element if it is not
12
+ * @returns A JavaScript object with a `type` property and a `props` property. The `type` property is
13
+ * set to the `type` argument passed into the function, and the `props` property is an object that
14
+ * includes any additional properties passed in the `props` argument, as well as a `children` property
15
+ * that is an array of any child elements passed in the `...children` argument
16
+ */
17
+ function createElement(type, props, ...children) {
18
+ return {
19
+ type,
20
+ props: {
21
+ ...props,
22
+ children: children.map((child) =>
23
+ typeof child === "object" ? child : createTextElement(child)
24
+ ),
25
+ },
26
+ };
27
+ }
28
+
29
+ /**
30
+ * The function creates a text element with a given text value.
31
+ * @param text - The text content that will be used to create a new text element.
32
+ * @returns A JavaScript object with a `type` property set to `"TEXT_ELEMENT"` and a `props` property
33
+ * that contains a `nodeValue` property set to the `text` parameter and an empty `children` array.
34
+ */
35
+ function createTextElement(text) {
36
+ return {
37
+ type: "TEXT_ELEMENT",
38
+ props: {
39
+ nodeValue: text,
40
+ children: [],
41
+ },
42
+ };
43
+ }
44
+
45
+ /**
46
+ * The function creates a new DOM element based on the given fiber object and updates its properties.
47
+ * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
48
+ * contains information about the element type, props, and children of the node.
49
+ * @returns The `createDom` function returns a newly created DOM element based on the `fiber` object
50
+ * passed as an argument. If the `fiber` object represents a text element, a text node is created using
51
+ * `document.createTextNode("")`. Otherwise, a new element is created using
52
+ * `document.createElement(fiber.type)`. The function then calls the `updateDom` function to update the
53
+ * properties of the newly created
54
+ */
55
+ function createDom(fiber) {
56
+ const dom =
57
+ fiber.type == "TEXT_ELEMENT"
58
+ ? document.createTextNode("")
59
+ : document.createElement(fiber.type);
60
+
61
+ updateDom(dom, {}, fiber.props);
62
+
63
+ return dom;
64
+ }
65
+
66
+ const isEvent = (key) => key.startsWith("on");
67
+ const isProperty = (key) => key !== "children" && !isEvent(key);
68
+ const isNew = (prev, next) => (key) => prev[key] !== next[key];
69
+ const isGone = (prev, next) => (key) => !(key in next);
70
+
71
+ /**
72
+ * The function updates the DOM by removing old event listeners and properties, and adding new ones
73
+ * based on the previous and next props.
74
+ * @param dom - The DOM element that needs to be updated with new props.
75
+ * @param prevProps - An object representing the previous props (properties) of a DOM element.
76
+ * @param nextProps - An object containing the new props that need to be updated in the DOM.
77
+ */
78
+ function updateDom(dom, prevProps, nextProps) {
79
+ Object.keys(prevProps)
80
+ .filter(isEvent)
81
+ .filter((key) => !(key in nextProps) || isNew(prevProps, nextProps)(key))
82
+ .forEach((name) => {
83
+ const eventType = name.toLowerCase().substring(2);
84
+ dom.removeEventListener(eventType, prevProps[name]);
85
+ });
86
+
87
+ Object.keys(prevProps)
88
+ .filter(isProperty)
89
+ .filter(isGone(prevProps, nextProps))
90
+ .forEach((name) => {
91
+ dom[name] = "";
92
+ });
93
+
94
+ Object.keys(nextProps)
95
+ .filter(isProperty)
96
+ .filter(isNew(prevProps, nextProps))
97
+ .forEach((name) => {
98
+ dom[name] = nextProps[name];
99
+ });
100
+
101
+ Object.keys(nextProps)
102
+ .filter(isEvent)
103
+ .filter(isNew(prevProps, nextProps))
104
+ .forEach((name) => {
105
+ const eventType = name.toLowerCase().substring(2);
106
+ dom.addEventListener(eventType, nextProps[name]);
107
+ });
108
+ }
109
+
110
+ /**
111
+ * The function commits changes made to the virtual DOM to the actual DOM.
112
+ */
113
+ function commitRoot() {
114
+ deletions.forEach(commitWork);
115
+ commitWork(wipRoot.child);
116
+ currentRoot = wipRoot;
117
+ wipRoot = null;
118
+ }
119
+
120
+ /**
121
+ * The function commits changes made to the DOM based on the effect tag of the fiber.
122
+ * @param fiber - A fiber is a unit of work in React's reconciliation process. It represents a
123
+ * component and its state at a particular point in time. The `commitWork` function takes a fiber as a
124
+ * parameter to commit the changes made during the reconciliation process to the actual DOM.
125
+ * @returns The function does not return anything, it performs side effects by manipulating the DOM.
126
+ */
127
+ function commitWork(fiber) {
128
+ if (!fiber) {
129
+ return;
130
+ }
131
+
132
+ let domParentFiber = fiber.parent;
133
+ while (!domParentFiber.dom) {
134
+ domParentFiber = domParentFiber.parent;
135
+ }
136
+ const domParent = domParentFiber.dom;
137
+
138
+ if (fiber.effectTag === "PLACEMENT" && fiber.dom != null) {
139
+ domParent.appendChild(fiber.dom);
140
+ } else if (fiber.effectTag === "UPDATE" && fiber.dom != null) {
141
+ updateDom(fiber.dom, fiber.alternate.props, fiber.props);
142
+ } else if (fiber.effectTag === "DELETION") {
143
+ commitDeletion(fiber, domParent);
144
+ }
145
+
146
+ commitWork(fiber.child);
147
+ commitWork(fiber.sibling);
148
+ }
149
+
150
+ /**
151
+ * The function removes a fiber's corresponding DOM node from its parent node or recursively removes
152
+ * its child's DOM node until it finds a node to remove.
153
+ * @param fiber - a fiber node in a fiber tree, which represents a component or an element in the React
154
+ * application.
155
+ * @param domParent - The parent DOM element from which the fiber's DOM element needs to be removed.
156
+ */
157
+ function commitDeletion(fiber, domParent) {
158
+ if (fiber.dom) {
159
+ domParent.removeChild(fiber.dom);
160
+ } else {
161
+ commitDeletion(fiber.child, domParent);
162
+ }
163
+ }
164
+
165
+ let containerRoot = null;
166
+
167
+ /**
168
+ * The function creates a root container for a web application.
169
+ * @param root - The parameter `root` is likely referring to an HTML element that will serve as the
170
+ * root or container for a web application or component. The `createRoot` function takes this element
171
+ * as an argument and assigns it to a variable called `containerRoot`. This variable can then be used
172
+ * to manipulate the contents
173
+ */
174
+ function createRoot(root) {
175
+ containerRoot = root;
176
+ }
177
+
178
+ /**
179
+ * The function renders an element into a container using a work-in-progress root.
180
+ * @param element - The element parameter is the component or element that needs to be rendered in the
181
+ * container. It could be a React component or a DOM element.
182
+ * @param container - The container parameter is the DOM element where the rendered element will be
183
+ * appended to. this parameter is optional if you use createRoot().
184
+ */
185
+ function render(element, container) {
186
+ wipRoot = {
187
+ dom: containerRoot || container,
188
+ props: {
189
+ children: [element],
190
+ },
191
+ alternate: currentRoot,
192
+ };
193
+ deletions = [];
194
+ nextUnitOfWork = wipRoot;
195
+ }
196
+
197
+ let nextUnitOfWork = null;
198
+ let currentRoot = null;
199
+ let wipRoot = null;
200
+ let deletions = null;
201
+
202
+ /**
203
+ * This function uses requestIdleCallback to perform work on a fiber tree until it is complete or the
204
+ * browser needs to yield to other tasks.
205
+ * @param deadline - The `deadline` parameter is an object that represents the amount of time the
206
+ * browser has to perform work before it needs to handle other tasks. It has a `timeRemaining()` method
207
+ * that returns the amount of time remaining before the deadline is reached. The `shouldYield` variable
208
+ * is used to determine
209
+ */
210
+ function workLoop(deadline) {
211
+ let shouldYield = false;
212
+ while (nextUnitOfWork && !shouldYield) {
213
+ nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
214
+ shouldYield = deadline.timeRemaining() < 1;
215
+ }
216
+
217
+ if (!nextUnitOfWork && wipRoot) {
218
+ commitRoot();
219
+ }
220
+
221
+ requestIdleCallback(workLoop);
222
+ }
223
+
224
+ requestIdleCallback(workLoop);
225
+
226
+ /**
227
+ * The function performs a unit of work by updating either a function component or a host component and
228
+ * returns the next fiber to be processed.
229
+ * @param fiber - A fiber is a unit of work in React that represents a component and its state. It
230
+ * contains information about the component's type, props, and children, as well as pointers to its
231
+ * parent, child, and sibling fibers. The `performUnitOfWork` function takes a fiber as a parameter and
232
+ * performs work
233
+ * @returns The function `performUnitOfWork` returns the next fiber to be processed. If the current
234
+ * fiber has a child, it returns the child. Otherwise, it looks for the next sibling of the current
235
+ * fiber. If there are no more siblings, it goes up the tree to the parent and looks for the next
236
+ * sibling of the parent. The function returns `null` if there are no more fibers to process.
237
+ */
238
+ function performUnitOfWork(fiber) {
239
+ const isFunctionComponent = fiber.type instanceof Function;
240
+ if (isFunctionComponent) {
241
+ updateFunctionComponent(fiber);
242
+ } else {
243
+ updateHostComponent(fiber);
244
+ }
245
+ if (fiber.child) {
246
+ return fiber.child;
247
+ }
248
+ let nextFiber = fiber;
249
+ while (nextFiber) {
250
+ if (nextFiber.sibling) {
251
+ return nextFiber.sibling;
252
+ }
253
+ nextFiber = nextFiber.parent;
254
+ }
255
+ }
256
+
257
+ let wipFiber = null;
258
+ let hookIndex = null;
259
+
260
+ /**
261
+ * This function updates a function component by setting up a work-in-progress fiber, resetting the
262
+ * hook index, creating an empty hooks array, rendering the component, and reconciling its children.
263
+ * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
264
+ * contains information about the component, its props, state, and children. In this function, it is
265
+ * used to update the state of the component and its children.
266
+ */
267
+ function updateFunctionComponent(fiber) {
268
+ wipFiber = fiber;
269
+ hookIndex = 0;
270
+ wipFiber.hooks = [];
271
+ const children = [fiber.type(fiber.props)];
272
+ reconcileChildren(fiber, children);
273
+ }
274
+
275
+ /**
276
+ * This function updates a host component's DOM element and reconciles its children.
277
+ * @param fiber - A fiber is a unit of work in React that represents a component and its state. It
278
+ * contains information about the component's type, props, and children, as well as pointers to other
279
+ * fibers in the tree.
280
+ */
281
+ function updateHostComponent(fiber) {
282
+ if (!fiber.dom) {
283
+ fiber.dom = createDom(fiber);
284
+ }
285
+ reconcileChildren(fiber, fiber.props.children);
286
+ }
287
+
288
+ /**
289
+ * This function reconciles the children of a fiber node with a new set of elements, creating new
290
+ * fibers for new elements, updating existing fibers for elements with the same type, and marking old
291
+ * fibers for deletion if they are not present in the new set of elements.
292
+ * @param wipFiber - A work-in-progress fiber object representing a component or element in the virtual
293
+ * DOM tree.
294
+ * @param elements - an array of elements representing the new children to be rendered in the current
295
+ * fiber's subtree
296
+ */
297
+ function reconcileChildren(wipFiber, elements) {
298
+ let index = 0;
299
+ let oldFiber = wipFiber.alternate && wipFiber.alternate.child;
300
+ let prevSibling = null;
301
+
302
+ while (index < elements.length || oldFiber != null) {
303
+ const element = elements[index];
304
+ let newFiber = null;
305
+
306
+ const sameType = oldFiber && element && element.type == oldFiber.type;
307
+
308
+ if (sameType) {
309
+ newFiber = {
310
+ type: oldFiber.type,
311
+ props: element.props,
312
+ dom: oldFiber.dom,
313
+ parent: wipFiber,
314
+ alternate: oldFiber,
315
+ effectTag: "UPDATE",
316
+ };
317
+ }
318
+ if (element && !sameType) {
319
+ newFiber = {
320
+ type: element.type,
321
+ props: element.props,
322
+ dom: null,
323
+ parent: wipFiber,
324
+ alternate: null,
325
+ effectTag: "PLACEMENT",
326
+ };
327
+ }
328
+ if (oldFiber && !sameType) {
329
+ oldFiber.effectTag = "DELETION";
330
+ deletions.push(oldFiber);
331
+ }
332
+
333
+ if (oldFiber) {
334
+ oldFiber = oldFiber.sibling;
335
+ }
336
+
337
+ if (index === 0) {
338
+ wipFiber.child = newFiber;
339
+ } else if (element) {
340
+ prevSibling.sibling = newFiber;
341
+ }
342
+
343
+ prevSibling = newFiber;
344
+ index++;
345
+ }
346
+ }
347
+
348
+ // Hooks
349
+
350
+ /**
351
+ * The function creates a state hook for a React-like framework.
352
+ * @param initial - The initial value of the state for the hook.
353
+ * @returns The `useStore` function returns an array with two elements: the current state value and a
354
+ * `setState` function that can be used to update the state.
355
+ */
356
+ function useStore(initial) {
357
+ const oldHook =
358
+ wipFiber.alternate &&
359
+ wipFiber.alternate.hooks &&
360
+ wipFiber.alternate.hooks[hookIndex];
361
+ const hook = {
362
+ state: oldHook ? oldHook.state : initial,
363
+ queue: [],
364
+ };
365
+
366
+ const actions = oldHook ? oldHook.queue : [];
367
+ actions.forEach((action) => {
368
+ console.log(action);
369
+ hook.state = action(hook.state);
370
+ });
371
+
372
+ /**
373
+ * The function `setState` updates the state of a component in React by adding an action to a queue
374
+ * and setting up a new work-in-progress root.
375
+ * @param action - The `action` parameter is an object that represents a state update to be performed
376
+ * on a component. It contains information about the type of update to be performed and any new data
377
+ * that needs to be applied to the component's state.
378
+ */
379
+ const setState = (action) => {
380
+ hook.queue.push(action);
381
+ wipRoot = {
382
+ dom: currentRoot.dom,
383
+ props: currentRoot.props,
384
+ alternate: currentRoot,
385
+ };
386
+ nextUnitOfWork = wipRoot;
387
+ deletions = [];
388
+ };
389
+
390
+ wipFiber.hooks.push(hook);
391
+ hookIndex++;
392
+ return [hook.state, setState];
393
+ }
394
+
395
+ function Fragment() {
396
+ return null;
397
+ }
398
+
399
+ // export
400
+
401
+ export {
402
+ // Main functions
403
+ createElement,
404
+ render,
405
+ createRoot,
406
+ // Hooks
407
+ useStore,
408
+ Fragment,
409
+ };
package/lib/main.js ADDED
@@ -0,0 +1,13 @@
1
+ import { createElement, render, createRoot } from "./dom";
2
+ import { Fragment, useStore } from "./dom";
3
+
4
+ // Hooks
5
+ export { useStore, Fragment };
6
+
7
+ // General
8
+
9
+ export default {
10
+ createElement,
11
+ render,
12
+ createRoot,
13
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unsetsoft/ryunixjs",
3
- "version": "0.1.14-beta.0",
3
+ "version": "0.2.0-beta.1",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.js",
6
6
  "private": false,
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "homepage": "https://github.com/UnSetSoft/Ryunixjs#readme",
11
11
  "scripts": {
12
- "build": "rollup ./lib/ryunix.js --file ./dist/Ryunix.js --format umd --name Ryunix",
12
+ "build": "rollup ./lib/main.js --file ./dist/Ryunix.js --format umd --name Ryunix",
13
13
  "postinstall": "yarn build"
14
14
  },
15
15
  "dependencies": {
package/lib/component.js DELETED
@@ -1,25 +0,0 @@
1
- import { scheduleUpdate } from "./reconciler";
2
-
3
- export class Component {
4
- constructor(props) {
5
- this.props = props;
6
- this.state = this.state || {};
7
- }
8
- setState(partialState) {
9
- // this.state = Object.assign({}, this.state, partialState);
10
- // scheduleUpdate(this.__internalInstance, partialState);
11
- throw Error(
12
- "This function is not implemented yet, has a lot of bugs. You can check https://github.com/UnSetSoft/Ryunixjs/issues/10 for more information."
13
- );
14
- }
15
- }
16
-
17
- export class Fragment {
18
- constructor(props) {
19
- this.props = props;
20
- }
21
-
22
- render() {
23
- return this.props.children;
24
- }
25
- }
package/lib/dom-utils.js DELETED
@@ -1,25 +0,0 @@
1
- /**
2
- * This function updates the properties and event listeners of a DOM element based on the previous and
3
- * next props passed as arguments.
4
- * @param dom - The DOM element that needs to be updated with new properties.
5
- * @param prevProps - An object representing the previous properties of a DOM element.
6
- * @param nextProps - An object containing the new props that need to be updated on the DOM element.
7
- */
8
- export function updateDomProperties(dom, prevProps, nextProps) {
9
- const isEvent = name => name.startsWith("on");
10
- const isAttribute = name => !isEvent(name) && name != "children";
11
- Object.keys(prevProps).filter(isEvent).forEach(name => {
12
- const eventType = name.toLowerCase().substring(2);
13
- dom.removeEventListener(eventType, prevProps[name]);
14
- });
15
- Object.keys(prevProps).filter(isAttribute).forEach(name => {
16
- dom[name] = null;
17
- });
18
- Object.keys(nextProps).filter(isAttribute).forEach(name => {
19
- dom[name] = nextProps[name];
20
- });
21
- Object.keys(nextProps).filter(isEvent).forEach(name => {
22
- const eventType = name.toLowerCase().substring(2);
23
- dom.addEventListener(eventType, nextProps[name]);
24
- });
25
- }
package/lib/element.js DELETED
@@ -1,37 +0,0 @@
1
- const TEXT_ELEMENT = "TEXT";
2
-
3
- /**
4
- * This function creates a new element with the given type, configuration object, and children.
5
- * @param type - The type of the element being created (e.g. "div", "span", "h1", etc.).
6
- * @param configObject - The `configObject` parameter is an object that contains the properties and
7
- * values for the element's attributes. These attributes can include things like `className`, `id`,
8
- * `style`, and any other custom attributes that the user wants to add to the element.
9
- * @param args - The `args` parameter is a rest parameter that allows the function to accept any number
10
- * of additional arguments after the `configObject` parameter. These additional arguments are used as
11
- * children elements for the created element.
12
- * @returns An object with two properties: "type" and "props".
13
- */
14
- export function createElement(type, configObject, ...args) {
15
- const props = Object.assign({}, configObject);
16
- const hasChildren = args.length > 0;
17
- const nodeChildren = hasChildren ? [...args] : [];
18
- props.children = nodeChildren.filter(Boolean).map(c => c instanceof Object ? c : createTextElement(c));
19
- return {
20
- type,
21
- props
22
- };
23
- }
24
-
25
- /**
26
- * The function creates a text element with a given node value and an empty array of children.
27
- * @param nodeValue - The value of the text node that will be created.
28
- * @returns The function `createTextElement` is returning an element object with a `nodeValue` property
29
- * and an empty `children` array. This element object represents a text node in the virtual DOM.
30
- */
31
- function createTextElement(nodeValue) {
32
- return createElement(TEXT_ELEMENT, {
33
- nodeValue,
34
- children: []
35
- });
36
- }
37
- export { TEXT_ELEMENT };
package/lib/hooks.js DELETED
@@ -1,5 +0,0 @@
1
- const useLoaded = (fn) => {
2
- return document.addEventListener("DOMContentLoaded", fn);
3
- };
4
-
5
- export { useLoaded };
package/lib/reconciler.js DELETED
@@ -1,612 +0,0 @@
1
- import { updateDomProperties } from "./dom-utils";
2
- import { TEXT_ELEMENT } from "./element";
3
-
4
- let rootInstance = null;
5
- const ENOUGH_TIME = 1;
6
- let workQueue = [];
7
- let nextUnitOfWork = null;
8
- const CLASS_COMPONENT = "class";
9
- const HOST_ROOT = "root";
10
- const HOST_COMPONENT = "host";
11
- const PLACEMENT = "PLACEMENT"; // this is for a child that needs to be added
12
- const DELETION = "DELETION"; //for a child that needs to be deleted.
13
- const UPDATE = "UPDATE"; // for a child that needs to be updated. refresh the props
14
- let pendingCommit = null;
15
-
16
- /**
17
- * The function adds a task to a work queue and requests idle callback to perform the work.
18
- * @param task - The task parameter is a function that represents the work that needs to be done. It
19
- * will be added to the workQueue array, which is a queue of tasks waiting to be executed. The
20
- * requestIdleCallback function will be used to schedule the execution of the performWork function,
21
- * which will process the tasks
22
- */
23
- function schedule(task) {
24
- workQueue.push(task);
25
- requestIdleCallback(performWork);
26
- }
27
-
28
- /**
29
- * This function performs work in a loop using requestIdleCallback and commits any pending changes.
30
- * @param deadline - The `deadline` parameter is a time value representing the deadline by which the
31
- * `performWork` function should finish its work. It is used to ensure that the function does not
32
- * exceed a certain amount of time and cause the browser to become unresponsive. The function will stop
33
- * working on the current task when
34
- */
35
- function performWork(deadline) {
36
- if (!nextUnitOfWork) {
37
- initialUnitOfWork();
38
- }
39
- loopThroughWork(deadline);
40
- if (nextUnitOfWork || workQueue.length > 0) {
41
- requestIdleCallback(performWork);
42
- }
43
-
44
- if (pendingCommit) {
45
- commitAllWork(pendingCommit);
46
- }
47
- }
48
-
49
- /**
50
- * The function commits all the effects of a fiber and updates the root container fiber.
51
- * @param fiber - The fiber parameter is an object that represents a node in the fiber tree. It
52
- * contains information about the component, its state, props, and children. The fiber also has a
53
- * reference to its parent, child, and sibling fibers.
54
- */
55
- function commitAllWork(fiber) {
56
- fiber.effects.forEach((f) => {
57
- commitWork(f);
58
- });
59
-
60
- fiber.stateNode._rootContainerFiber = fiber;
61
- nextUnitOfWork = null;
62
- pendingCommit = null;
63
- }
64
-
65
- /**
66
- * The function commits changes to the DOM based on the effect tag of the fiber.
67
- * @param fiber - A fiber is a lightweight unit of work that represents a component and its state
68
- * during the reconciliation process in React's virtual DOM. It contains information about the
69
- * component's type, props, state, and children, as well as pointers to its parent, child, and sibling
70
- * fibers.
71
- * @returns If the fiber tag is HOST_ROOT, nothing is being returned.
72
- */
73
- function commitWork(fiber) {
74
- if (fiber.tag == HOST_ROOT) {
75
- return;
76
- }
77
- let domParentFiber = fiber.parent;
78
- while (domParentFiber.tag == CLASS_COMPONENT) {
79
- domParentFiber = domParentFiber.parent;
80
- }
81
- const domParent = domParentFiber.stateNode;
82
- if (fiber.effectTag == PLACEMENT && fiber.tag == HOST_COMPONENT) {
83
- domParent.appendChild(fiber.stateNode);
84
- } else if (fiber.effectTag == UPDATE) {
85
- updateDomProperties(fiber.stateNode, fiber.alternate.props, fiber.props);
86
- } else if (fiber.effectTag == DELETION) {
87
- commitDeletion(fiber, domParent);
88
- }
89
- }
90
-
91
- /**
92
- * The function removes a fiber and its corresponding DOM node from the parent DOM node.
93
- * @param fiber - The fiber is a data structure used by React to represent a component and its state
94
- * during the rendering process. It contains information about the component's type, props, children,
95
- * and other metadata.
96
- * @param domParent - The DOM element that is the parent of the component being deleted.
97
- * @returns The function does not explicitly return anything, but it will exit the function and return
98
- * control to the calling function when the condition `if (node == fiber)` is met.
99
- */
100
- function commitDeletion(fiber, domParent) {
101
- let node = fiber;
102
- while (true) {
103
- if (node.tag == CLASS_COMPONENT) {
104
- node = node.child;
105
- continue;
106
- }
107
- domParent.removeChild(node.stateNode);
108
- while (node != fiber && !node.sibling) {
109
- node = node.parent;
110
- }
111
- if (node == fiber) {
112
- return;
113
- }
114
- node = node.sibling;
115
- }
116
- }
117
-
118
- /**
119
- * The function begins the work of updating a fiber either for a class component or a host component.
120
- * @param wipFiber - wipFiber is a fiber object that represents the work-in-progress (WIP) component
121
- * being worked on by the reconciler in a React application. It contains information about the
122
- * component's type, props, state, and children, as well as pointers to its parent, sibling, and child
123
- * fibers
124
- */
125
- function beginWork(wipFiber) {
126
- if (wipFiber.tag == CLASS_COMPONENT) {
127
- updateClassFiber(wipFiber);
128
- } else {
129
- updateHostFiber(wipFiber);
130
- }
131
- }
132
-
133
- /**
134
- * This function updates the host fiber by creating a new DOM element and reconciling its children.
135
- * @param wipFiber - wipFiber is a work-in-progress fiber object that represents a component or element
136
- * in the virtual DOM tree. It contains information about the component's type, props, state, and
137
- * children. The function `updateHostFiber` uses this wipFiber object to update the corresponding DOM
138
- * element
139
- */
140
- function updateHostFiber(wipFiber) {
141
- if (!wipFiber.stateNode) {
142
- wipFiber.stateNode = createDomElement(wipFiber);
143
- }
144
- const newChildElements = wipFiber.props.children;
145
- reconcileChildrenArray(wipFiber, newChildElements);
146
- }
147
-
148
- /**
149
- * This function updates the state and props of a fiber node and reconciles its child elements.
150
- * @param wipFiber - wipFiber is a work-in-progress fiber that represents a component in the fiber
151
- * tree. It contains information about the component's type, props, state, and children. The function
152
- * `updateClassFiber` updates the state and props of the component represented by the wipFiber.
153
- * @returns Nothing is being returned explicitly in this function. It either updates the instance and
154
- * child fibers or clones the child fibers and returns nothing.
155
- */
156
- function updateClassFiber(wipFiber) {
157
- let instance = wipFiber.stateNode;
158
- if (instance == null) {
159
- instance = wipFiber.stateNode = createInstance(wipFiber);
160
- } else if (wipFiber.props == instance.props && !wipFiber.partialState) {
161
- cloneChildFibers(wipFiber);
162
- return;
163
- }
164
-
165
- instance.props = wipFiber.props;
166
- instance.state = Object.assign({}, instance.state, wipFiber.partialState);
167
- wipFiber.partialState = null;
168
-
169
- const newChildElements = wipFiber.stateNode.render();
170
- reconcileChildrenArray(wipFiber, newChildElements);
171
- }
172
-
173
- /**
174
- * The function creates an instance of a component using the given fiber.
175
- * @param fiber - The "fiber" parameter is an object that represents a node in the fiber tree. It
176
- * contains information about the component type, props, children, and other metadata needed for
177
- * rendering and updating the component.
178
- * @returns The function `createInstance` returns an instance of the component class specified in the
179
- * `fiber` argument, with the props passed to it. The instance also has a reference to the `fiber`
180
- * object.
181
- */
182
- function createInstance(fiber) {
183
- const instance = new fiber.type(fiber.props);
184
- instance.__fiber = fiber;
185
- return instance;
186
- }
187
-
188
- /**
189
- * This function creates a new DOM element based on the given fiber object.
190
- * @param fiber - The "fiber" parameter is an object that represents a node in the virtual DOM tree. It
191
- * contains information about the element's type, props, and children.
192
- * @returns The function `createDomElement` returns a DOM element created using the
193
- * `document.createElement` method. If the `fiber` object represents a text element, then a text node
194
- * is created using `document.createTextNode` method. The properties of the element are updated using
195
- * the `updateDomProperties` function.
196
- */
197
- function createDomElement(fiber) {
198
- const isTextElement = fiber.type === TEXT_ELEMENT;
199
- const dom = isTextElement
200
- ? document.createTextNode("")
201
- : document.createElement(fiber.type);
202
- updateDomProperties(dom, [], fiber.props);
203
- return dom;
204
- }
205
-
206
- /**
207
- * This function performs work on a fiber and its children, completing each unit of work before moving
208
- * on to the next.
209
- * @param wipFiber - wipFiber stands for "work-in-progress fiber". In React, a fiber is a lightweight
210
- * representation of a component or element in the component tree. The wipFiber parameter represents
211
- * the current fiber that is being worked on by the reconciler during the rendering process. The
212
- * performUnitOfWork function performs
213
- * @returns the next unit of work to be performed, which is either the first child of the current fiber
214
- * (if it has one), or the next sibling of the current fiber (if it has one), or the parent of the
215
- * current fiber (if it has no more siblings).
216
- */
217
- function performUnitOfWork(wipFiber) {
218
- beginWork(wipFiber);
219
- if (wipFiber.child) {
220
- return wipFiber.child;
221
- }
222
-
223
- let uow = wipFiber;
224
- while (uow) {
225
- completeWork(uow);
226
-
227
- if (uow.sibling) {
228
- return uow.sibling;
229
- }
230
-
231
- uow = uow.parent;
232
- }
233
- }
234
-
235
- /**
236
- * The function initializes a unit of work by dequeuing an update from a work queue and setting the
237
- * next unit of work based on the update's properties.
238
- * @returns The function does not have a return statement, so it returns undefined.
239
- */
240
- function initialUnitOfWork() {
241
- const update = workQueue.shift();
242
-
243
- if (!update) {
244
- return;
245
- }
246
-
247
- if (update.partialState) {
248
- update.instance.__fiber.partialState = update.partialState;
249
- }
250
-
251
- const root =
252
- update.from === HOST_ROOT
253
- ? update.dom._rootContainerFiber
254
- : getRootNode(update.instance.__fiber);
255
-
256
- nextUnitOfWork = {
257
- tag: HOST_ROOT,
258
- stateNode: update.dom || root.stateNode,
259
- props: update.newProps || root.props,
260
- alternate: root,
261
- };
262
- }
263
-
264
- /**
265
- * The function returns the root node of a given fiber by traversing up the parent chain.
266
- * @param fiber - The "fiber" parameter is likely referring to a data structure used in React.js to
267
- * represent a component and its state. It is used in the function to traverse the component tree and
268
- * find the root node of the tree.
269
- * @returns The function `getRootNode` returns the root node of a given fiber by traversing up the
270
- * fiber tree until it reaches the topmost parent node.
271
- */
272
- function getRootNode(fiber) {
273
- let node = fiber;
274
- while (node.parent) {
275
- node = node.parent;
276
- }
277
- return node;
278
- }
279
-
280
- /**
281
- * This function loops through work while there is still time remaining before the deadline.
282
- * @param deadline - The `deadline` parameter is an object that represents a deadline by which the
283
- * current task should be completed. It has a `timeRemaining()` method that returns the amount of time
284
- * left until the deadline, in milliseconds. The `loopThroughWork()` function uses this `deadline`
285
- * object to check if there
286
- */
287
- function loopThroughWork(deadline) {
288
- while (nextUnitOfWork && deadline.timeRemaining() > ENOUGH_TIME) {
289
- nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
290
- }
291
- }
292
-
293
- /**
294
- * The function creates an array of children elements, either from an array or a single element.
295
- * @param children - The parameter `children` is expected to be a value that represents the children of
296
- * a parent element in a web page. It can be an array of child elements or a single child element. If
297
- * `children` is not provided or is falsy, an empty array is returned.
298
- * @returns The function `createArrayOfChildren` is returning an array. If the `children` parameter is
299
- * falsy (e.g. `null`, `undefined`, `false`, `0`, `NaN`, or an empty string), it returns an empty
300
- * array. If `children` is already an array, it returns that array. Otherwise, it returns an array with
301
- * `children` as its only element.
302
- */
303
- function createArrayOfChildren(children) {
304
- return !children ? [] : Array.isArray(children) ? children : [children];
305
- }
306
-
307
- /**
308
- * This function reconciles the children of a fiber node with a new array of child elements.
309
- * @param wipFiber - The work-in-progress fiber, which represents the current state of the component
310
- * being rendered or updated.
311
- * @param newChildElements - an array of new child elements to be reconciled with the existing children
312
- * of the current fiber (wipFiber).
313
- */
314
- function reconcileChildrenArray(wipFiber, newChildElements) {
315
- const elements = createArrayOfChildren(newChildElements);
316
-
317
- let index = 0;
318
-
319
- let oldFiber = wipFiber.alternate ? wipFiber.alternate.child : null;
320
- let newFiber = null;
321
- while (index < elements.length || oldFiber != null) {
322
- const prevFiber = newFiber;
323
-
324
- const element = index < elements.length && elements[index];
325
-
326
- const sameType = oldFiber && element && element.type == oldFiber.type;
327
-
328
- if (sameType) {
329
- newFiber = {
330
- type: oldFiber.type,
331
- tag: oldFiber.tag,
332
- stateNode: oldFiber.stateNode,
333
- props: element.props,
334
- parent: wipFiber,
335
- alternate: oldFiber,
336
- partialState: oldFiber.partialState,
337
- effectTag: UPDATE,
338
- };
339
- }
340
-
341
- if (element && !sameType) {
342
- newFiber = {
343
- type: element.type,
344
- tag:
345
- typeof element.type === "string" ? HOST_COMPONENT : CLASS_COMPONENT,
346
- props: element.props,
347
- parent: wipFiber,
348
- effectTag: PLACEMENT,
349
- };
350
- }
351
-
352
- if (oldFiber && !sameType) {
353
- oldFiber.effectTag = DELETION;
354
- wipFiber.effects = wipFiber.effects || [];
355
-
356
- wipFiber.effects.push(oldFiber);
357
- }
358
-
359
- if (oldFiber) {
360
- oldFiber = oldFiber.sibling;
361
- }
362
-
363
- if (index == 0) {
364
- wipFiber.child = newFiber;
365
- } else if (prevFiber && element) {
366
- prevFiber.sibling = newFiber;
367
- }
368
-
369
- index++;
370
- }
371
- }
372
-
373
- /**
374
- * The function clones child fibers from a parent fiber.
375
- * @param parentFiber - The parent fiber is an object that represents a component or element in the
376
- * React tree. It contains information about the component or element, such as its type, props, and
377
- * children. The function `cloneChildFibers` is used to clone the child fibers of the parent fiber.
378
- * @returns If the `oldFiber` does not have a child, then nothing is returned. Otherwise, a new set of
379
- * child fibers is created based on the `oldFiber` and attached to the `parentFiber`. No value is
380
- * explicitly returned from the function.
381
- */
382
- function cloneChildFibers(parentFiber) {
383
- const oldFiber = parentFiber.alternate;
384
-
385
- if (!oldFiber.child) {
386
- return;
387
- }
388
-
389
- let oldChild = oldFiber.child;
390
-
391
- let prevChild = null;
392
-
393
- while (oldChild) {
394
- const newChild = {
395
- type: oldChild.type,
396
- tag: oldChild.tag,
397
- stateNode: oldChild.stateNode,
398
- props: oldChild.props,
399
- partialState: oldChild.partialState,
400
- alternate: oldChild,
401
- parent: parentFiber,
402
- };
403
- if (prevChild) {
404
- prevChild.sibling = newChild;
405
- } else {
406
- parentFiber.child = newChild;
407
- }
408
- prevChild = newChild;
409
- oldChild = oldChild.sibling;
410
- }
411
- }
412
-
413
- /**
414
- * The function completes work on a fiber and adds its effects to its parent's effects list or sets it
415
- * as the pending commit.
416
- * @param fiber - a fiber object representing a component or element in the React tree
417
- */
418
- function completeWork(fiber) {
419
- if (fiber.tag == CLASS_COMPONENT) {
420
- fiber.stateNode.__fiber = fiber;
421
- }
422
-
423
- if (fiber.parent) {
424
- const childEffects = fiber.effects || [];
425
-
426
- const thisEffect = fiber.effectTag != null ? [fiber] : [];
427
- const parentEffects = fiber.parent.effects || [];
428
-
429
- fiber.parent.effects = parentEffects.concat(childEffects, thisEffect);
430
- } else {
431
- pendingCommit = fiber;
432
- }
433
- }
434
-
435
- /**
436
- * This function schedules an update for a class component with the given instance and partial state.
437
- * @param instance - The instance parameter refers to an instance of a class component in React. It is
438
- * used to identify which component needs to be updated with the new state.
439
- * @param partialState - partialState is an object that contains the updated state values for a
440
- * component. When a component's state changes, the partialState object is passed to the scheduleUpdate
441
- * function to schedule a re-render of the component with the updated state values.
442
- */
443
- export function scheduleUpdate(instance, partialState) {
444
- schedule({
445
- from: CLASS_COMPONENT,
446
- instance: instance,
447
- partialState: partialState,
448
- });
449
- }
450
-
451
- let rootElement;
452
-
453
- export const createRoot = (parentDom) => {
454
- rootElement = parentDom;
455
- };
456
-
457
- /**
458
- * The `render` function takes in elements and a parent DOM node, and schedules a reconciliation
459
- * process to update the DOM with the new elements.
460
- * @param elements - an array of elements to be rendered in the parent DOM.
461
- * @param parentDom - parentDom is a reference to the DOM element where the rendered elements will be
462
- * appended as children. It is the container element for the rendered components.
463
- */
464
-
465
- export function rootClient(elements) {
466
- workQueue.push({
467
- from: "root",
468
- dom: rootElement,
469
- newProps: { children: elements },
470
- });
471
- requestIdleCallback(performWork);
472
- }
473
-
474
- export function render(elements, parentDom) {
475
- workQueue.push({
476
- from: HOST_ROOT,
477
- dom: parentDom,
478
- newProps: { children: elements },
479
- });
480
- requestIdleCallback(performWork);
481
- }
482
-
483
- /**
484
- * The function reconciles the differences between the previous and current instances of a component
485
- * and updates the DOM accordingly.
486
- * @param parentDom - The DOM element that serves as the parent container for the rendered component
487
- * tree.
488
- * @param instance - An object representing the current state of the component instance being
489
- * reconciled. It contains information about the component's rendered DOM node, its element type, and
490
- * its child instances. If this is the first time the component is being rendered, this parameter will
491
- * be null.
492
- * @param element - The element parameter represents the new element that needs to be rendered or
493
- * updated in the DOM. It contains information about the type of element (e.g. div, span, custom
494
- * component), its props (e.g. className, onClick), and its children (if any).
495
- * @returns an instance object that represents the updated state of the component after reconciling the
496
- * changes made to the virtual DOM.
497
- */
498
- export function reconcile(parentDom, instance, element) {
499
- if (instance === null) {
500
- const newInstance = instantiate(element);
501
- parentDom.appendChild(newInstance.dom);
502
- return newInstance;
503
- } else if (element == null) {
504
- parentDom.removeChild(instance.dom);
505
- return null;
506
- } else if (instance.element.type !== element.type) {
507
- const newInstance = instantiate(element);
508
- parentDom.replaceChild(newInstance.dom, instance.dom);
509
- return newInstance;
510
- } else if (typeof element.type === "string") {
511
- instance.childInstances = reconcileChildren(instance, element);
512
- instance.element = element;
513
- return instance;
514
- } else {
515
- instance.publicInstance.props = element.props;
516
- const childElement = instance.publicInstance.render();
517
- const oldChildInstance = instance.childInstance;
518
- const childInstance = reconcile(parentDom, oldChildInstance, childElement);
519
- instance.dom = childInstance.dom;
520
- instance.childInstance = childInstance;
521
- instance.element = element;
522
- return instance;
523
- }
524
- }
525
-
526
- /**
527
- * The function creates an instance of a DOM element or a custom component element and returns it.
528
- * @param element - The element to be instantiated, which can be a DOM element or a custom component.
529
- * It contains information about the type of the element (string for DOM elements, function for custom
530
- * components) and its props (attributes and children).
531
- * @returns The function `instantiate` returns an instance object that contains a reference to the
532
- * corresponding DOM node, the element that was passed in, and an array of child instances. The exact
533
- * properties of the instance object depend on whether the element is a DOM element or a custom
534
- * component.
535
- */ function instantiate(element) {
536
- const { type, props } = element;
537
- const isDomElement = typeof type === "string";
538
- if (isDomElement) {
539
- const isTextElement = type === TEXT_ELEMENT;
540
- const dom = isTextElement
541
- ? document.createTextNode("")
542
- : document.createElement(type);
543
- updateDomProperties(dom, [], props);
544
- const childElements = props.children || [];
545
- const childInstances = childElements.map(instantiate);
546
- const childDoms = childInstances.map((childInstance) => childInstance.dom);
547
- childDoms.forEach((childDom) => dom.appendChild(childDom));
548
- const instance = {
549
- dom,
550
- element,
551
- childInstances,
552
- };
553
- return instance;
554
- } else {
555
- const instance = {};
556
- const publicInstance = createPublicInstance(element, instance);
557
- const childElement = publicInstance.render();
558
- const childInstance = instantiate(childElement);
559
- const dom = childInstance.dom;
560
- Object.assign(instance, {
561
- dom,
562
- element,
563
- childInstance,
564
- publicInstance,
565
- });
566
- return instance;
567
- }
568
- }
569
- /**
570
- * The function creates a public instance of a given element with its corresponding props and internal
571
- * instance.
572
- * @param element - An object that represents a React element, typically created using JSX syntax or
573
- * React.createElement() function.
574
- * @param internalInstance - The internalInstance parameter is an object that represents the internal
575
- * instance of a component. It may contain information such as the component's state, context, and
576
- * lifecycle methods. This parameter is used to associate the public instance of a component with its
577
- * internal instance.
578
- * @returns a newly created public instance of a given element type with its props.
579
- */
580
- function createPublicInstance(element, internalInstance) {
581
- const { type, props } = element;
582
- const publicInstance = new type(props);
583
- publicInstance.__internalInstance = internalInstance;
584
- return publicInstance;
585
- }
586
-
587
- /**
588
- * This function reconciles the child instances of a component with its new child elements.
589
- * @param instance - an object representing the current instance of a component
590
- * @param element - The element is a React element that represents the new version of the component
591
- * being rendered. It contains information about the component's props and children.
592
- * @returns an array of new child instances that have been reconciled with the given parent instance
593
- * and child elements. The filter method is used to remove any falsy values from the array, such as
594
- * null or undefined.
595
- */
596
- function reconcileChildren(instance, element) {
597
- const { dom, childInstances } = instance;
598
- const nextChildElements = element.props.children || [];
599
-
600
- const newChildInstances = [];
601
-
602
- const count = Math.max(childInstances.length, nextChildElements.length);
603
-
604
- for (let i = 0; i < count; i++) {
605
- const childInstance = childInstances[i];
606
- const childElement = nextChildElements[i];
607
- const newChildInstance = reconcile(dom, childInstance, childElement);
608
- newChildInstances.push(newChildInstance);
609
- }
610
-
611
- return newChildInstances.filter(Boolean);
612
- }
package/lib/ryunix.js DELETED
@@ -1,13 +0,0 @@
1
- import { render, rootClient, createRoot } from "./reconciler";
2
- import { createElement } from "./element";
3
- import { Component, Fragment } from "./component";
4
- import { useLoaded } from "./hooks";
5
- export { createElement, render, Component, useLoaded, Fragment };
6
- export default {
7
- render,
8
- createElement,
9
- Component,
10
- Fragment,
11
- rootClient,
12
- createRoot,
13
- };