@unsetsoft/ryunixjs 0.1.4 → 0.1.11

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/component.js CHANGED
@@ -1,6 +1,14 @@
1
- import { reconcile } from "./reconciler";
2
- export class Component {
3
- constructor(props) {
4
- this.props = props;
5
- }
6
- }
1
+ import { scheduleUpdate } from "./reconciler";
2
+ export class Component {
3
+ constructor(props) {
4
+ this.props = props;
5
+ this.state = this.state || {};
6
+ }
7
+ setState(partialState) {
8
+ // this.state = Object.assign({}, this.state, partialState);
9
+ // scheduleUpdate(this.__internalInstance, partialState);
10
+ throw Error(
11
+ "This function is not implemented yet, has a lot of bugs. You can check https://github.com/UnSetSoft/Ryunixjs/issues/10 for more information."
12
+ );
13
+ }
14
+ }
package/lib/reconciler.js CHANGED
@@ -1,102 +1,596 @@
1
- import { updateDomProperties } from "./dom-utils";
2
- import { TEXT_ELEMENT } from "./element";
3
- let rootInstance = null;
4
- export function render(element, parentDom) {
5
- const prevInstance = rootInstance;
6
- const nextInstance = reconcile(parentDom, prevInstance, element);
7
- rootInstance = nextInstance;
8
- }
9
-
10
- export function reconcile(parentDom, instance, element) {
11
- if (instance === null) {
12
- const newInstance = instantiate(element);
13
- parentDom.appendChild(newInstance.dom);
14
- return newInstance;
15
- }
16
-
17
- if (element == null) {
18
- parentDom.removeChild(instance.dom);
19
- return null;
20
- }
21
-
22
- if (instance.element.type !== element.type) {
23
- const newInstance = instantiate(element);
24
- parentDom.replaceChild(instance.dom, newInstance.dom);
25
- return newInstance;
26
- }
27
-
28
- if (typeof element.type === "string") {
29
- instance.childInstances = reconcileChildren(instance, element);
30
- instance.element = element;
31
- return instance;
32
- }
33
-
34
- // Si no es una cadena, asumimos que es un componente personalizado
35
- instance.publicInstance.props = element.props;
36
- const childElement = instance.publicInstance.render();
37
- const oldChildInstance = instance.childInstance;
38
- const childInstance = reconcile(parentDom, oldChildInstance, childElement);
39
- instance.dom = childInstance.dom;
40
- instance.childInstance = childInstance;
41
- instance.element = element;
42
- return instance;
43
- }
44
-
45
- function instantiate(element) {
46
- const { type, props } = element;
47
- const isDomElement = typeof type === "string";
48
- if (isDomElement) {
49
- const isTextElement = type === TEXT_ELEMENT;
50
- const dom = isTextElement
51
- ? document.createTextNode("")
52
- : document.createElement(type);
53
- updateDomProperties(dom, [], props);
54
- const childElements = props.children || [];
55
- const childInstances = childElements.map(instantiate);
56
- const childDoms = childInstances.map((childInstance) => childInstance.dom);
57
- childDoms.forEach((childDom) => dom.appendChild(childDom));
58
- const instance = {
59
- dom,
60
- element,
61
- childInstances,
62
- };
63
- return instance;
64
- } else {
65
- const instance = {};
66
- const publicInstance = createPublicInstance(element, instance);
67
- const childElement = publicInstance.render();
68
- const childInstance = instantiate(childElement);
69
- const dom = childInstance.dom;
70
- Object.assign(instance, {
71
- dom,
72
- element,
73
- childInstance,
74
- publicInstance,
75
- });
76
- return instance;
77
- }
78
- }
79
- function createPublicInstance(element, internalInstance) {
80
- const { type, props } = element;
81
- const publicInstance = new type(props);
82
- publicInstance.__internalInstance = internalInstance;
83
- return publicInstance;
84
- }
85
-
86
- function reconcileChildren(instance, element) {
87
- const { dom, childInstances } = instance;
88
- const nextChildElements = element.props.children || [];
89
-
90
- const newChildInstances = [];
91
-
92
- const count = Math.max(childInstances.length, nextChildElements.length);
93
-
94
- for (let i = 0; i < count; i++) {
95
- const childInstance = childInstances[i];
96
- const childElement = nextChildElements[i];
97
- const newChildInstance = reconcile(dom, childInstance, childElement);
98
- newChildInstances.push(newChildInstance);
99
- }
100
-
101
- return newChildInstances.filter(Boolean);
102
- }
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
+ /**
452
+ * The `render` function takes in elements and a parent DOM node, and schedules a reconciliation
453
+ * process to update the DOM with the new elements.
454
+ * @param elements - an array of elements to be rendered in the parent DOM.
455
+ * @param parentDom - parentDom is a reference to the DOM element where the rendered elements will be
456
+ * appended as children. It is the container element for the rendered components.
457
+ */
458
+ export function render(elements, parentDom) {
459
+ workQueue.push({
460
+ from: HOST_ROOT,
461
+ dom: parentDom,
462
+ newProps: { children: elements },
463
+ });
464
+ requestIdleCallback(performWork);
465
+ }
466
+
467
+ /**
468
+ * The function reconciles the differences between the previous and current instances of a component
469
+ * and updates the DOM accordingly.
470
+ * @param parentDom - The DOM element that serves as the parent container for the rendered component
471
+ * tree.
472
+ * @param instance - An object representing the current state of the component instance being
473
+ * reconciled. It contains information about the component's rendered DOM node, its element type, and
474
+ * its child instances. If this is the first time the component is being rendered, this parameter will
475
+ * be null.
476
+ * @param element - The element parameter represents the new element that needs to be rendered or
477
+ * updated in the DOM. It contains information about the type of element (e.g. div, span, custom
478
+ * component), its props (e.g. className, onClick), and its children (if any).
479
+ * @returns an instance object that represents the updated state of the component after reconciling the
480
+ * changes made to the virtual DOM.
481
+ */
482
+ export function reconcile(parentDom, instance, element) {
483
+ if (instance === null) {
484
+ const newInstance = instantiate(element);
485
+ parentDom.appendChild(newInstance.dom);
486
+ return newInstance;
487
+ } else if (element == null) {
488
+ parentDom.removeChild(instance.dom);
489
+ return null;
490
+ } else if (instance.element.type !== element.type) {
491
+ const newInstance = instantiate(element);
492
+ parentDom.replaceChild(newInstance.dom, instance.dom);
493
+ return newInstance;
494
+ } else if (typeof element.type === "string") {
495
+ instance.childInstances = reconcileChildren(instance, element);
496
+ instance.element = element;
497
+ return instance;
498
+ } else {
499
+ instance.publicInstance.props = element.props;
500
+ const childElement = instance.publicInstance.render();
501
+ const oldChildInstance = instance.childInstance;
502
+ const childInstance = reconcile(parentDom, oldChildInstance, childElement);
503
+ instance.dom = childInstance.dom;
504
+ instance.childInstance = childInstance;
505
+ instance.element = element;
506
+ return instance;
507
+ }
508
+ }
509
+
510
+ /**
511
+ * The function creates an instance of a DOM element or a custom component element and returns it.
512
+ * @param element - The element to be instantiated, which can be a DOM element or a custom component.
513
+ * It contains information about the type of the element (string for DOM elements, function for custom
514
+ * components) and its props (attributes and children).
515
+ * @returns The function `instantiate` returns an instance object that contains a reference to the
516
+ * corresponding DOM node, the element that was passed in, and an array of child instances. The exact
517
+ * properties of the instance object depend on whether the element is a DOM element or a custom
518
+ * component.
519
+ */ function instantiate(element) {
520
+ const { type, props } = element;
521
+ const isDomElement = typeof type === "string";
522
+ if (isDomElement) {
523
+ const isTextElement = type === TEXT_ELEMENT;
524
+ const dom = isTextElement
525
+ ? document.createTextNode("")
526
+ : document.createElement(type);
527
+ updateDomProperties(dom, [], props);
528
+ const childElements = props.children || [];
529
+ const childInstances = childElements.map(instantiate);
530
+ const childDoms = childInstances.map((childInstance) => childInstance.dom);
531
+ childDoms.forEach((childDom) => dom.appendChild(childDom));
532
+ const instance = {
533
+ dom,
534
+ element,
535
+ childInstances,
536
+ };
537
+ return instance;
538
+ } else {
539
+ const instance = {};
540
+ const publicInstance = createPublicInstance(element, instance);
541
+ const childElement = publicInstance.render();
542
+ const childInstance = instantiate(childElement);
543
+ const dom = childInstance.dom;
544
+ Object.assign(instance, {
545
+ dom,
546
+ element,
547
+ childInstance,
548
+ publicInstance,
549
+ });
550
+ return instance;
551
+ }
552
+ }
553
+ /**
554
+ * The function creates a public instance of a given element with its corresponding props and internal
555
+ * instance.
556
+ * @param element - An object that represents a React element, typically created using JSX syntax or
557
+ * React.createElement() function.
558
+ * @param internalInstance - The internalInstance parameter is an object that represents the internal
559
+ * instance of a component. It may contain information such as the component's state, context, and
560
+ * lifecycle methods. This parameter is used to associate the public instance of a component with its
561
+ * internal instance.
562
+ * @returns a newly created public instance of a given element type with its props.
563
+ */
564
+ function createPublicInstance(element, internalInstance) {
565
+ const { type, props } = element;
566
+ const publicInstance = new type(props);
567
+ publicInstance.__internalInstance = internalInstance;
568
+ return publicInstance;
569
+ }
570
+
571
+ /**
572
+ * This function reconciles the child instances of a component with its new child elements.
573
+ * @param instance - an object representing the current instance of a component
574
+ * @param element - The element is a React element that represents the new version of the component
575
+ * being rendered. It contains information about the component's props and children.
576
+ * @returns an array of new child instances that have been reconciled with the given parent instance
577
+ * and child elements. The filter method is used to remove any falsy values from the array, such as
578
+ * null or undefined.
579
+ */
580
+ function reconcileChildren(instance, element) {
581
+ const { dom, childInstances } = instance;
582
+ const nextChildElements = element.props.children || [];
583
+
584
+ const newChildInstances = [];
585
+
586
+ const count = Math.max(childInstances.length, nextChildElements.length);
587
+
588
+ for (let i = 0; i < count; i++) {
589
+ const childInstance = childInstances[i];
590
+ const childElement = nextChildElements[i];
591
+ const newChildInstance = reconcile(dom, childInstance, childElement);
592
+ newChildInstances.push(newChildInstance);
593
+ }
594
+
595
+ return newChildInstances.filter(Boolean);
596
+ }
package/lib/ryunix.js CHANGED
@@ -1,10 +1,10 @@
1
- import { render } from "./reconciler";
2
- import { createElement } from "./element";
3
- import { Component } from "./component";
4
- import { useLoaded } from "./hooks";
5
- export { createElement, render, Component, useLoaded };
6
- export default {
7
- render,
8
- createElement,
9
- Component,
10
- };
1
+ import { render } from "./reconciler";
2
+ import { createElement } from "./element";
3
+ import { Component } from "./component";
4
+ import { useLoaded } from "./hooks";
5
+ export { createElement, render, Component, useLoaded };
6
+ export default {
7
+ render,
8
+ createElement,
9
+ Component,
10
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unsetsoft/ryunixjs",
3
- "version": "0.1.4",
3
+ "version": "0.1.11",
4
4
  "license": "MIT",
5
5
  "main": "./dist/Ryunix.js",
6
6
  "private": false,