@3sln/dodo 0.0.7 → 0.0.9

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/index.js CHANGED
@@ -1,14 +1,15 @@
1
1
  import vdomFactory from './src/vdom.js';
2
2
  import htmlFactory from './src/html.js';
3
- import * as scheduler from './src/scheduler.js';
3
+ import schedulerFactory from './src/scheduler.js';
4
4
 
5
5
  function dodoFactory(userSettings) {
6
6
  const vdomInstance = vdomFactory(userSettings);
7
7
  const htmlInstance = htmlFactory(vdomInstance);
8
+ const schedulerInstance = schedulerFactory(userSettings);
8
9
  return {
9
10
  ...vdomInstance,
10
11
  ...htmlInstance,
11
- ...scheduler,
12
+ ...schedulerInstance,
12
13
  };
13
14
  }
14
15
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@3sln/dodo",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "A minimal, configurable virtual DOM library.",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/src/scheduler.js CHANGED
@@ -1,79 +1,85 @@
1
- let scheduled = false;
2
- let frameId = 0;
3
- let queue = [];
1
+ export default function factory({window} = {}) {
2
+ const requestAnimationFrame = window?.requestAnimationFrame ?? globalThis.requestAnimationFrame;
3
+ const cancelAnimationFrame = window?.cancelAnimationFrame ?? globalThis.cancelAnimationFrame;
4
+ let scheduled = false;
5
+ let frameId = 0;
6
+ let queue = [];
4
7
 
5
- const FRAME_BUDGET = 10; // ms
6
- const CHUNK_SIZE = 100;
8
+ const FRAME_BUDGET = 10; // ms
9
+ const CHUNK_SIZE = 100;
7
10
 
8
- function _runTasks(tasks) {
9
- for (const f of tasks) {
10
- try {
11
- f();
12
- } catch (err) {
13
- console.error('Error in scheduled function:', err);
11
+ function _runTasks(tasks) {
12
+ for (const f of tasks) {
13
+ try {
14
+ f();
15
+ } catch (err) {
16
+ console.error('Error in scheduled function:', err);
17
+ }
14
18
  }
15
19
  }
16
- }
17
20
 
18
- function runQueue() {
19
- const startTime = performance.now();
20
- frameId = 0;
21
+ function runQueue() {
22
+ const startTime = performance.now();
23
+ frameId = 0;
21
24
 
22
- while (queue.length > 0) {
23
- const chunk = queue.splice(0, CHUNK_SIZE);
24
- _runTasks(chunk);
25
+ while (queue.length > 0) {
26
+ const chunk = queue.splice(0, CHUNK_SIZE);
27
+ _runTasks(chunk);
25
28
 
26
- if (performance.now() - startTime > FRAME_BUDGET && queue.length > 0) {
27
- frameId = requestAnimationFrame(runQueue);
28
- return;
29
+ if (performance.now() - startTime > FRAME_BUDGET && queue.length > 0) {
30
+ frameId = requestAnimationFrame(runQueue);
31
+ return;
32
+ }
29
33
  }
30
- }
31
-
32
- scheduled = false;
33
- }
34
34
 
35
- // Schedules a function to be executed on the next animation frame.
36
- export function schedule(f, {signal} = {}) {
37
- if (signal?.aborted) {
38
- return;
35
+ scheduled = false;
39
36
  }
40
37
 
41
- let task = f;
42
- // If a signal is provided, wrap the task to check for abortion before execution.
43
- if (signal) {
44
- task = () => {
45
- if (!signal.aborted) {
46
- f();
47
- }
48
- };
49
- }
38
+ // Schedules a function to be executed on the next animation frame.
39
+ function schedule(f, {signal} = {}) {
40
+ if (signal?.aborted) {
41
+ return;
42
+ }
43
+
44
+ let task = f;
45
+ // If a signal is provided, wrap the task to check for abortion before execution.
46
+ if (signal) {
47
+ task = () => {
48
+ if (!signal.aborted) {
49
+ f();
50
+ }
51
+ };
52
+ }
50
53
 
51
- queue.push(task);
54
+ queue.push(task);
52
55
 
53
- if (!scheduled) {
54
- scheduled = true;
55
- frameId = requestAnimationFrame(runQueue);
56
+ if (!scheduled) {
57
+ scheduled = true;
58
+ frameId = requestAnimationFrame(runQueue);
59
+ }
56
60
  }
57
- }
58
61
 
59
- // Immediately runs all queued tasks synchronously.
60
- export function flush() {
61
- if (frameId) {
62
- cancelAnimationFrame(frameId);
62
+ // Immediately runs all queued tasks synchronously.
63
+ function flush() {
64
+ if (frameId) {
65
+ cancelAnimationFrame(frameId);
66
+ }
67
+ const toRun = queue;
68
+ queue = [];
69
+ _runTasks(toRun);
70
+ scheduled = false;
71
+ frameId = 0;
63
72
  }
64
- const toRun = queue;
65
- queue = [];
66
- _runTasks(toRun);
67
- scheduled = false;
68
- frameId = 0;
69
- }
70
73
 
71
- // Clears all pending tasks.
72
- export function clear() {
73
- if (frameId) {
74
- cancelAnimationFrame(frameId);
74
+ // Clears all pending tasks.
75
+ function clear() {
76
+ if (frameId) {
77
+ cancelAnimationFrame(frameId);
78
+ }
79
+ queue = [];
80
+ scheduled = false;
81
+ frameId = 0;
75
82
  }
76
- queue = [];
77
- scheduled = false;
78
- frameId = 0;
83
+
84
+ return {schedule, flush, clear};
79
85
  }
package/src/vdom.js CHANGED
@@ -395,7 +395,8 @@ export default userSettings => {
395
395
  }
396
396
  } else {
397
397
  const oldHooks = state.vdom.hooks ?? EMPTY_MAP;
398
- const hooksIterator = toIterator(mapIter(hooks));
398
+ const newHooks = hooks ?? EMPTY_MAP;
399
+ const hooksIterator = toIterator(mapIter(newHooks));
399
400
  let result;
400
401
  while (!(result = hooksIterator.next()).done) {
401
402
  const [name, listener] = result.value;
@@ -427,7 +428,7 @@ export default userSettings => {
427
428
  while (!(result = oldHooksIterator.next()).done) {
428
429
  const [name] = result.value;
429
430
  const hookName = convertHookName(name);
430
- if (hookName[0] === '$' || mapGet(hooks, name) !== undefined) continue;
431
+ if (hookName[0] === '$' || mapGet(newHooks, name) !== undefined) continue;
431
432
  const oldListener = mapGet(oldHooks, name);
432
433
  if (typeof oldListener === 'function') {
433
434
  target.removeEventListener(hookName, oldListener);
@@ -459,10 +460,10 @@ export default userSettings => {
459
460
  break;
460
461
  }
461
462
  case ALIAS_NODE: {
462
- const innerVdom = newVdom.tag.apply(undefined, newVdom.args);
463
+ const innerVdom = newVdom.tag.apply(target, newVdom.args);
463
464
  if (innerVdom === undefined || innerVdom === null) break;
464
465
  if (isSeq(innerVdom)) {
465
- reconcileElementChildren(target, flattenSeq(innerVdom));
466
+ reconcileElementChildren(target, flattenSeq(innerVdom, true));
466
467
  } else {
467
468
  reconcileElementChildren(target, flattenVNodeChildren([innerVdom]));
468
469
  }
@@ -651,6 +652,7 @@ export default userSettings => {
651
652
  target.removeChild(nodeToRemove);
652
653
  }
653
654
 
655
+ const window = userSettings?.window ?? target.ownerDocument.defaultView;
654
656
  const moveBefore = window.Element.prototype.moveBefore;
655
657
  const insertBefore = window.Element.prototype.insertBefore;
656
658
  if (target.isConnected) {
@@ -748,7 +750,7 @@ export default userSettings => {
748
750
  }
749
751
 
750
752
  if (isSeq(vdom)) {
751
- reconcileElementChildren(target, flattenSeq(vdom));
753
+ reconcileElementChildren(target, flattenSeq(vdom, true));
752
754
  return;
753
755
  }
754
756