From 0aba94505fccbd8bcf5474d4b4ed44464f7f8f24 Mon Sep 17 00:00:00 2001 From: Faustze Date: Fri, 24 Jul 2026 16:40:56 +0300 Subject: [PATCH] chore: remove stale content/browser/Event Loop/ leftover files MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit An earlier sync (before the Obsidian-Vault itself was flattened) had recreated this nested folder in content/. sync-obsidian-notes.sh only copies/overwrites from the vault โ€” it never prunes files that no longer exist there โ€” so these stale duplicates of Rendering Pipeline.md, Event Loop, Microtasks, Macrotasks.md and index.md kept shipping to the live site even after the vault was fixed and re-synced. --- content-ru/.translation-manifest.json | 2 +- .../Event Loop, Microtasks, Macrotasks.md | 88 -------------- .../browser/Event Loop/Rendering Pipeline.md | 107 ------------------ content/browser/Event Loop/index.md | 12 -- 4 files changed, 1 insertion(+), 208 deletions(-) delete mode 100644 content/browser/Event Loop/Event Loop, Microtasks, Macrotasks.md delete mode 100644 content/browser/Event Loop/Rendering Pipeline.md delete mode 100644 content/browser/Event Loop/index.md diff --git a/content-ru/.translation-manifest.json b/content-ru/.translation-manifest.json index 3f98e86edaf8..d230994aee12 100644 --- a/content-ru/.translation-manifest.json +++ b/content-ru/.translation-manifest.json @@ -96,8 +96,8 @@ "leetcode/Untagged/2726-calculator-with-method-chaining.md": "249ec94bdb2fa52ded25c266daf411ed4e208d966f0041939aabe4d647d99c7f", "leetcode/Untagged/index.md": "988a5773fd5f501cd92b5b3223500966941b19d5f2d21448da391cdc4895f064", "leetcode/index.md": "88c151c7c5564227dea91e47d96076632d854dd7fc1eddfa45440093be401dc3", - "vue/Internals/Compiler.md": "c46b3dd12912b11bc4f0a34b2abba574baff9626f42df410eab279ae77b99e90", "vue/Internals/Reactivity.md": "9b502f513195b4512f4d8188f1ac30746030e1c5a52a6a626d51c80c15752d24", + "vue/Internals/Compiler.md": "c46b3dd12912b11bc4f0a34b2abba574baff9626f42df410eab279ae77b99e90", "vue/Internals/index.md": "0637645f58c346554c1687702236afa74ed3b25e795a4c0ad5038369ed0479fb", "vue/index.md": "aa6244e7ef392b574ddd86f1cafeeac49e03dda7df6eb83b1767e493d1059669" } diff --git a/content/browser/Event Loop/Event Loop, Microtasks, Macrotasks.md b/content/browser/Event Loop/Event Loop, Microtasks, Macrotasks.md deleted file mode 100644 index f56fe5af4d00..000000000000 --- a/content/browser/Event Loop/Event Loop, Microtasks, Macrotasks.md +++ /dev/null @@ -1,88 +0,0 @@ -# โฑ Event Loop, Microtasks, Macrotasks, requestAnimationFrame - -## ๐Ÿ’ก Core idea - -> The Event Loop doesn't execute code. It's a dispatcher: it checks whether the call stack is empty, then moves the next queued task into it. - -Two questions this note answers: why does `setTimeout(fn, 0)` always run after all synchronous code *and* all promises? And why does an infinite `Promise.then()` chain freeze the tab dead, while an infinite `requestAnimationFrame` loop doesn't? - ---- -# ๐Ÿงญ The participants - -1. **Call Stack** โ€” runs synchronous JS line by line. Nothing else runs while it isn't empty. -2. **JS engine (V8, etc.)** โ€” executes only the call stack. It has no built-in concept of `setTimeout`, the DOM, or `fetch` โ€” none of that is part of the ECMAScript spec. -3. **Web APIs** (browser) / **libuv** (Node.js) โ€” a separate part of the runtime that actually counts timers, listens for network/DOM events, and prepares frames. -4. **Macrotask queue** โ€” `setTimeout`, `setInterval`, DOM events, I/O. FIFO; the Event Loop pulls **one task at a time** from it. -5. **Microtask queue** โ€” `Promise.then`, `queueMicrotask`, `MutationObserver`. FIFO, but the Event Loop **drains it completely** before doing anything else. -6. **Event Loop** โ€” the dispatcher itself: in a loop, it checks "is the call stack empty?", pulls the next task, pushes it onto the stack. - ---- -# ๐Ÿ”‘ The golden rule - -> After every synchronous task, the Event Loop **fully drains** the microtask queue โ€” including microtasks added while draining is in progress. Only once the queue is empty does it move on (to rendering, or to a single macrotask). - -The difference isn't "priority" โ€” it's a different draining strategy: microtasks mean *"finish everything that has piled up, however much that turns out to be"*; a macrotask means *"take exactly one thing and hand control back to the dispatcher"*. - -**One full loop iteration:** - -``` -Call Stack (all synchronous code) - โ†’ drain microtask queue COMPLETELY (even if it refills while draining) - โ†’ requestAnimationFrame callbacks (a snapshot of exactly this frame) - โ†’ Render: Layout โ†’ Paint โ†’ Composite - โ†’ take ONE macrotask โ†’ run it - โ†’ drain microtask queue again - โ†’ ... repeat -``` - ---- -# ๐ŸŽž requestAnimationFrame - -`requestAnimationFrame(cb)` asks the browser to *"run this right before the next frame is painted"*. It's not a timer and gives no guarantee about exact milliseconds โ€” it's tied to the actual screen refresh cycle (~60/sec). - -Ordering, with rAF in the mix: - -```js -Promise.resolve().then(() => console.log('promise')); -requestAnimationFrame(() => console.log('raf')); -setTimeout(() => console.log('timeout'), 0); - -// promise โ†’ raf โ†’ timeout -``` - ---- -# โ„๏ธ Why infinite Promise.then() freezes the tab, but infinite rAF doesn't - -Not a coincidence โ€” the two queues work on fundamentally different mechanics. - -**The microtask queue is checked dynamically.** Before every step, the Event Loop asks "is the queue empty?". If the microtask currently running enqueues a new one, that new one joins the queue and runs **in this same pass**. For an infinite chain, the exit condition ("empty") never arrives: - -```js -function loop() { - Promise.resolve().then(loop); // every .then() spawns the next one -} -loop(); -// the Event Loop never reaches rendering, macrotasks, or clicks โ€” the tab is dead -``` - -**The rAF queue for a frame is a snapshot (batch), fixed at the start of that frame's processing.** Anything registered via `requestAnimationFrame(...)` *during* the current batch's execution physically cannot land in that same batch โ€” only in the next frame: - -```js -function animate() { - x++; - requestAnimationFrame(animate); // goes into the NEXT frame, not this one -} -requestAnimationFrame(animate); -// Render (Layout โ†’ Paint โ†’ Composite) is guaranteed to happen between frames -``` - -So infinite recursion through rAF doesn't block the browser: a render always lands between iterations. The key distinction isn't about how fast either callback runs โ€” it's that the microtask queue has no snapshot boundary, and the rAF batch does. - ---- -# ๐Ÿง  In one sentence - -> The Event Loop's exit condition for the microtask queue is "empty" โ€” a self-refilling queue never reaches it. The rAF queue instead exits by *snapshot*: what gets added during a batch is deferred to the next one no matter how fast it runs. - -[[browser/Event Loop/index|Event Loop & Rendering]] -[[browser/Event Loop/Rendering Pipeline|Rendering Pipeline โ€” what happens after the microtask queue drains]] -#browser diff --git a/content/browser/Event Loop/Rendering Pipeline.md b/content/browser/Event Loop/Rendering Pipeline.md deleted file mode 100644 index 73b162cbbe9c..000000000000 --- a/content/browser/Event Loop/Rendering Pipeline.md +++ /dev/null @@ -1,107 +0,0 @@ -# ๐Ÿ–ผ Rendering Pipeline: Parse โ†’ Style โ†’ Layout โ†’ Paint โ†’ Composite - -## ๐Ÿ’ก Core idea - -> Not every style change is equally expensive. What a CSS property triggers โ€” Layout, Paint, or just Composite โ€” decides whether an animation runs smoothly or drops frames. - ---- -# ๐Ÿงญ The full pipeline - -``` -Parse HTML โ†’ DOM -Parse CSS โ†’ CSSOM -DOM + CSSOM โ†’ Render Tree (excludes display:none) -Render Tree โ†’ Layout (geometry: x, y, width, height) -Layout โ†’ Paint (pixels: color, text, shadows) -Paint โ†’ Composite (GPU assembles layers) -``` - -`element.style.width = '100px'` does **not** trigger layout immediately. The browser just flags the element (and often its subtree) as "dirty" and defers the recalculation to the next natural render point โ€” the step that sits right after the microtask queue drains and rAF callbacks run in the [[browser/Event Loop/Event Loop|Event Loop]]. - -Important distinction: **CSSOM** (parsed rules from `