WEB / WEB-10.03
JavaScript execution and the event loop
Separate synchronous code,Promise executor,microtasks and later tasks in a bounded ordering fixture.
1. Core · Mechanism
Read every scenario without motion
Task + microtasks
- Before synchronous start
The fixture is ready;callback logs and queue outcomes have not yet been produced.
- Synchronous stack
- Stack:empty
- Microtask checkpoint
- Microtasks:[]
- Later task
- Timer:not scheduled
- Presentation boundary
- Paint:not measured
- Executor runs now
Script start and the Promise executor run synchronously;the then callback has not run.
- Synchronous stack
- Log:start,executor
- Microtask checkpoint
- Reaction queued
- Later task
- Timer:not scheduled
- Presentation boundary
- Paint:not measured
- Synchronous prefix ends
queueMicrotask and timer are scheduled;script:end is logged before current code finishes.
- Synchronous stack
- Log:start,executor,end;stackempty
- Microtask checkpoint
- Microtasks:promise,microtask
- Later task
- Timer:requested0
- Presentation boundary
- Paint:not measured
- Promise reaction
The checkpoint processes the queued Promise reaction first;the timer does not interrupt the prefix.
- Synchronous stack
- Prefix complete
- Microtask checkpoint
- Log:+promise;queue:microtask
- Later task
- Timer:not processed
- Presentation boundary
- Paint:not measured
- Microtask adds one job
The selected microtask adds one nested job;the checkpoint continues until the queue empties.
- Synchronous stack
- Prefix complete
- Microtask checkpoint
- Log:+microtask;queue:nested
- Later task
- Timer:not processed
- Presentation boundary
- Paint:not measured
- Bounded checkpoint drains
The nested callback runs;the microtask queue is empty without establishing pixels.
- Synchronous stack
- Stack:empty
- Microtask checkpoint
- Log:+nested;queue:[]
- Later task
- Timer:pendingselection
- Presentation boundary
- Paint:not measured
- Later timer callback
The timer runs in a later task;exact elapsed time and its order relative to rAF are not fixed here.
- Synchronous stack
- Stack returns empty
- Microtask checkpoint
- Checkpoint drained
- Later task
- Log:+timer
- Presentation boundary
- Paint:not measured
Executor vs then
- Before Promise creation
The ordinary local script has started;executor and reaction results are not yet available.
- Synchronous stack
- Log:start
- Microtask checkpoint
- Reaction:absent
- Later task
- Timer:none
- Presentation boundary
- Paint:not measured
- Executor synchronous
The Promise constructor calls its executor now;fulfilled state is not callback execution.
- Synchronous stack
- Log:start,executor
- Microtask checkpoint
- Promise:fulfilled;reactionpending
- Later task
- Timer:none
- Presentation boundary
- Paint:not measured
- Caller continues
The constructor returns and the caller logs end;the then reaction does not interrupt the prefix.
- Synchronous stack
- Log:start,executor,end
- Microtask checkpoint
- Reaction:queued
- Later task
- Timer:none
- Presentation boundary
- Paint:not measured
- Reaction later
The checkpoint runs the reaction;executor and reaction have different completion boundaries.
- Synchronous stack
- Stack:empty
- Microtask checkpoint
- Log:+reaction;queueempty
- Later task
- Timer:none
- Presentation boundary
- Paint:not measured
Await continuation
- Caller starts
The caller is ready to invoke an async function;no independent thread is created.
- Synchronous stack
- Caller active
- Microtask checkpoint
- Microtasks:[]
- Later task
- Await:absent
- Presentation boundary
- Paint:not measured
- Before await logs
The async function runs synchronously up to await and records before-await.
- Synchronous stack
- Log:before-await
- Microtask checkpoint
- Continuation:pending
- Later task
- LocalPromise:fulfilled
- Presentation boundary
- Paint:not measured
- Caller keeps running
While the await continuation is deferred,the caller logs after-call before the function resumes.
- Synchronous stack
- Log:before-await,after-call
- Microtask checkpoint
- Continuation:queued
- Later task
- No network operation
- Presentation boundary
- Paint:not measured
- Continuation resumes
The appropriate reaction work records after-await;ordering does not establish CPU parallelism.
- Synchronous stack
- Prefix complete
- Microtask checkpoint
- Log:+after-await
- Later task
- LocalPromise consumed
- Presentation boundary
- Paint:not measured
- Boundary retained
The local continuation is complete;neither a server transaction nor frame receipt follows from this result.
- Synchronous stack
- Stack:empty
- Microtask checkpoint
- Bounded fixture complete
- Later task
- Network:not executed
- Presentation boundary
- Pixels:not captured
ACTORS · STATE · DATA FLOW
Engine,host and browser are distinct
A JavaScript engine parses and evaluates ECMAScript code and may use implementation techniques such as bytecode or JIT. DOM,fetch and timers are web APIs supplied by the browser host. Language semantics can be explained without assuming a particular optimization. JavaScript executing does not establish completion of a network request or creation of the DOM.
Distinguish language objects such as Array and Promise from document and Window.setTimeout. The same language can run with different host APIs in another runtime. Node timer observations are not browser-scheduler evidence here. A small ordering fixture will use actual Chrome,while the pure scene models selected semantic dependencies.
Execution context and call stack
An execution context is the ECMAScript specification’s model for tracking evaluation progress. Function,Realm and environment relationships belong to it; it need not exist as a context object script can inspect. The running context is the top of the context stack. Nested calls transfer control through contexts,but exceptions and async suspension mean every transition is not identical to a simple drawing.
When A calls B,A’s next synchronous line waits for B to return. The lesson uses a call stack to explain that dependency. Its A:start,B,A:end callTrace is an observation,not a capture of engine-internal stack memory. An empty stack also leaves possible pending callbacks,microtasks and host work.
An event loop schedules callback work
The HTML event loop coordinates scripts,user interaction,networking and rendering. One loop can have several task queues with scheduler choices between task sources. A single global FIFO for every network,click and timer callback is therefore misleading. The microtask queue is also distinct from an ordinary task queue.
The ordinary fixture schedules a timer and two microtask sources during one synchronous start. Delay0 asks for a callback that can become runnable later; it does not interrupt current code. This small fixture cannot establish general network/user-event ordering. The scene retains dependencies between the selected jobs without generating milliseconds or FPS results.
Promise executor is synchronous;reaction is a microtask
new Promise(executor) invokes its executor synchronously during creation. resolve may fulfill the Promise,but a then reaction does not interrupt current synchronous statements;it runs as microtask work at an appropriate checkpoint. Treating everything inside a Promise as async confuses executor and reaction.
The fixture prefix is script:start,executor,script:end,followed by the promise reaction. queueMicrotask retains queue order and a checkpoint continues until the queue is empty. The selected callback adds one nested microtask that runs within the same checkpoint. The model stays bounded and supplies no infinite enqueue or browser-locking code.
Await suspends control rather than creating a thread
An async function can run synchronously until its await point. Continuation proceeds through later reaction work even for a fulfilled Promise,while the caller can continue its synchronous work. Await creates no independent CPU thread. Parallel work in another agent or worker needs its own mechanism and communication boundary.
The selected await fixture orders before-await,after-call,after-await around local Promise.resolve("Atlas"). It performs no fetch or server commit. The observation explains continuation timing rather than transaction atomicity or approval for a resource action. A learner can identify which function’s continuation was deferred instead of assuming every async line runs in parallel.
A DOM update is not a frame receipt
A callback can change DOM state,and a rendering opportunity can turn that state into a new view. The current HTML processing model schedules window rendering work through the rendering task source. Do not assume every task forces a paint or every callback is followed by a fixed refresh. Hidden documents and unnecessary rendering also affect updates.
requestAnimationFrame provides a callback before repaint;it is one-shot and generally pauses for hidden/background contexts. This lesson makes no universal ordering claim between a timer and rAF. The artifact deliberately records paintCaptured=false: log order and current DOM text do not measure pixel presentation.
2. Red · Trust & Impact
Read every scenario without motion
Executor/reaction
- The executor appeared in the synchronous prefix
The Promise constructor runs its executor synchronously after script:start and resolves. expectedLog places executor before script:end. Resolution does not imply simultaneous execution of its reaction callback.
- Callback observations
- script:start / executor / script:end
- Continuation gate
- Scheduling pending
- Application completion
- Outcome unknown
- The reaction ran after current work finished
The promise callback runs at the checkpoint after the synchronous prefix, followed by microtask and nested. Work readiness and callback execution are different states. Local scheduling is not network receipt.
- Callback observations
- script:start / executor / script:end
- Continuation gate
- Reaction after script:end / checkpoint order
- Application completion
- Outcome unknown
- The work represented by fulfillment remained explicit
Promise fulfillment describes only its represented work. Data received, body consumed, validation, DOM updates and server commit may have other completion boundaries. This ordinary callback fixture does not measure application persistence.
- Callback observations
- script:start / executor / script:end
- Continuation gate
- Reaction after script:end / checkpoint order
- Application completion
- Callback known / application commit unmeasured
- A nested microtask joined the bounded checkpoint
The microtask callback adds a nested microtask. expectedLog orders promise, microtask, nested and then timer. This finite example does not define all ordering among other task sources or responsiveness timing.
- Callback observations
- promise→microtask→nested→timer
- Continuation gate
- Reaction after script:end / checkpoint order
- Application completion
- Callback known / application commit unmeasured
- Timer scheduling was not an execution deadline
timerDelayArgument is 0 while elapsedMillisecondsExpected remains null. The timer cannot interrupt synchronous work and has no exact-zero-ms guarantee. Callback order and timer latency are different evidence.
- Callback observations
- promise→microtask→nested→timer
- Continuation gate
- Delay argument0 / exact latency not measured
- Application completion
- Callback known / application commit unmeasured
- Control was tied to the correct completion invariant
UI should not derive business success from a done-like log label alone. If the work contract requires validation or commit, those stages must be awaited separately. Network and paint are false here, leaving broader action outcomes UNKNOWN.
- Callback observations
- promise→microtask→nested→timer
- Continuation gate
- Delay argument0 / exact latency not measured
- Application completion
- Define completion contract / do not infer business success
Await boundary
- The async function selected a separate continuation
expectedAwaitTrace is before-await, after-call, after-await. Await does not suspend the caller’s entire execution; the caller can progress while the continuation is deferred. Async does not automatically move CPU work to another thread.
- Callback observations
- before-await / after-call / after-await
- Continuation gate
- Scheduling pending
- Application completion
- Outcome unknown
- The deferred continuation was interpreted as a dependency
after-call does not establish completion of the async work. Product state must explicitly wait for the continuation or outcome on which it depends. Caller progress and successful awaited work are different predicates.
- Callback observations
- before-await / after-call / after-await
- Continuation gate
- Caller progressed / awaited outcome separate
- Application completion
- Outcome unknown
- The async keyword did not guarantee responsiveness
Long synchronous CPU work can delay main-thread work. An async function alone creates no parallelism. Bounded work or appropriate worker design is a separate control; this fixture measures no stall time or device performance.
- Callback observations
- before-await / after-call / after-await
- Continuation gate
- Caller progressed / awaited outcome separate
- Application completion
- Async ≠ automatic CPU parallelism
- The call trace retained its specification-alias scope
expectedCallTrace is A:start, B, A:end. Execution-context diagrams are specification models, not engine-memory captures or native context objects accessible to script. Error stacks may have different representations.
- Callback observations
- A:start→B→A:end / spec aliases
- Continuation gate
- Caller progressed / awaited outcome separate
- Application completion
- Async ≠ automatic CPU parallelism
- Lifecycle and cancellation remained separate predicates
A pending callback is not assumed to run in the same Document throughout its lifetime. Navigation and cancellation are separate predicates. The selected await trace does not simulate every dispatch edge case or document lifetime.
- Callback observations
- A:start→B→A:end / spec aliases
- Continuation gate
- Continuation order known / lifecycle separate
- Application completion
- Async ≠ automatic CPU parallelism
- Await scope was not confused with business outcomes
The story explains continuation order and caller progress without evidence of server mutation, persisted state or UI pixels. Correct async interpretation provides a sound mental model without claiming unperformed runtime work.
- Callback observations
- A:start→B→A:end / spec aliases
- Continuation gate
- Continuation order known / lifecycle separate
- Application completion
- Continuation known / broader outcomes unmeasured
ASSUMPTION · BOUNDARY · CONTROL
Do not confuse ordering with timing
For an authorized review,log order verifies a small dependency,while a0ms timer label does not verify execution at exactly0ms. Network panels,console output and DOM snapshots also have different observation owners. A callback invocation alone does not prove a whole response body was consumed or persistent action committed.
Before running the ordinary branch,predict its synchronous prefix and microtask order. Explain why a timer cannot interrupt that prefix and where the one nested microtask appears in the bounded checkpoint. This is a normal scheduling exercise rather than a way to trigger an attack race. Do not generalize ordering for other task sources from these logs.
A context drawing is not an engine capture
Stack aliases explain function boundaries. Error stacks or performance samples need not show the same representation: optimization,source maps and async-stack tooling differ. Record which source version matches an observed frame instead of turning three drawn boxes into a native-memory claim.
The await branch lets the caller proceed while an async continuation is deferred. A pending callback is also not guaranteed to run in the same Document for its entire lifetime;navigation and cancellation have separate conditions. This lesson does not simulate every dispatch/lifecycle edge case. Keep findings bounded to the supplied continuation fixture.
3. Blue · Secure development & defense
Read every scenario without motion
Order review
- The expected synchronous prefix was tied to source
The selected synchronous code, Promise reaction, queueMicrotask callback and timer callback produce log labels. expectedLog is the expected order, not the console record of a new execution. A callback label identifies its own completed work; this fixture produces no body-consumption, server-commit or DOM/pixel result. expectedLog starts with script:start, executor and script:end. The executor is synchronous constructor work; the then reaction is a scheduled continuation. The observer distinguishes their roles rather than merging log labels.
- Order ledger
- Synchronous prefix: start/executor/end
- Callback comparison
- Scheduling pending
- Evidence verdict
- Outcome unknown
- Checkpoint order was built from finite enqueue order
promise and microtask are already queued; nested is added inside the microtask. The expected suffix is promise, microtask, nested. This concrete order is the fixture’s dependency, not arbitrary task-source ordering.
- Order ledger
- Synchronous prefix: start/executor/end
- Callback comparison
- Checkpoint: promise/microtask/nested
- Evidence verdict
- Outcome unknown
- The timer label was related to queue order
Timer is the last expected label. Argument 0 is not measured elapsed time. Without DOM or pixel observations, seeing the timer label is not a timestamp of a presented update.
- Order ledger
- Timer after checkpoint / latency unknown
- Callback comparison
- Checkpoint: promise/microtask/nested
- Evidence verdict
- Outcome unknown
- Call and await controls checked distinct invariants
A:start/B/A:end is ordinary synchronous call order. before-await/after-call/after-await separates caller progress from continuation. The traces are not correlated as though they share an identical queue/stack record.
- Order ledger
- Timer after checkpoint / latency unknown
- Callback comparison
- Call trace and await trace separately consistent
- Evidence verdict
- Outcome unknown
- Order consistency was not a browser-performance claim
Finite local callbacks can demonstrate expected ordering without measuring timer latency, rAF relationships, networks, worker concurrency or paint. Correct ordinary ordering does not establish responsiveness or action completion.
- Order ledger
- Timer after checkpoint / latency unknown
- Callback comparison
- Call trace and await trace separately consistent
- Evidence verdict
- Ordering supported / performance unmeasured
- Regression was bounded to the needed milestone
Checks separately verify the synchronous prefix, microtask suffix and await continuation. Missing labels need coverage before cause is inferred. Bounded nonsensitive labels may suffice; application commit needs separate observation.
- Order ledger
- Timer after checkpoint / latency unknown
- Callback comparison
- Call trace and await trace separately consistent
- Evidence verdict
- Recheck prefix/checkpoint/continuation separately
Presentation gap
- Log completeness was separated from paint records
The selected synchronous code, Promise reaction, queueMicrotask callback and timer callback produce log labels. expectedLog is the expected order, not the console record of a new execution. A callback label identifies its own completed work; this fixture produces no body-consumption, server-commit or DOM/pixel result. Seven expected labels are supplied and paintCaptured is false. Knowing callbacks executed does not establish painted or presented text. renderOrderingWithTimer is unspecified in this fixture.
- Order ledger
- Seven expected labels / paint capture absent
- Callback comparison
- Scheduling pending
- Evidence verdict
- Outcome unknown
- No guessed ordering was added for timer and rendering
The ledger places timer after the checkpoint but supplies no universal order between rAF and timers. Boxes in an event-loop animation are not an actual compositor timeline. Rendering-opportunity timing needs its own observation.
- Order ledger
- Seven expected labels / paint capture absent
- Callback comparison
- No rAF/timer order claim
- Evidence verdict
- Outcome unknown
- A missing callback event did not explain its cause
If an alternative trace lacks nested, it does not automatically prove a faulty queue. Logging coverage, selected source and document lifetime are needed separately. The complete fixture log cannot replace the missing observation.
- Order ledger
- Missing label / coverage and lifecycle needed
- Callback comparison
- No rAF/timer order claim
- Evidence verdict
- Outcome unknown
- The required completion contract was tied to evidence
DOM updates need DOM observations, presented pixels need captures and server commit needs server-side records. A Promise-reaction label is not common proof of all three. Review identifies the required outcome first.
- Order ledger
- Missing label / coverage and lifecycle needed
- Callback comparison
- Outcome-specific observations required
- Evidence verdict
- Outcome unknown
- Paint and timing verdicts remained unknown
Exact timer latency and presented pixels remain UNKNOWN. A missing capture does not establish rendering failure; complete callback order does not establish first-pixel success. Observation families remain distinct.
- Order ledger
- Missing label / coverage and lifecycle needed
- Callback comparison
- Outcome-specific observations required
- Evidence verdict
- UNKNOWN: latency and presented pixels
- New evidence was requested only within the question’s scope
Further review needs scoped timestamps and the required DOM/presentation record, not full page data or user identity. Callback-order results are not relabeled as measured timing.
- Order ledger
- Missing label / coverage and lifecycle needed
- Callback comparison
- Outcome-specific observations required
- Evidence verdict
- Needed: scoped timing/presentation observations
IMPLEMENTATION · SECURITY CONTROL · VERIFICATION
Give async work an explicit completion contract
The selected synchronous code, Promise reaction, queueMicrotask callback and timer callback produce log labels. expectedLog is the expected order, not the console record of a new execution. A callback label identifies its own completed work; this fixture produces no body-consumption, server-commit or DOM/pixel result. Application code should state what each callback completes. Data received,body consumed,validated,DOM updated and server committed are different events. Choose the right completion boundary before advancing UI state. A fulfilled Promise describes the work that Promise represents;additional product-contract work needs its own steps.
The ordinary example separates executor from reaction. Log labels let an observer distinguish job ready from callback processed as two records. That small distinction also makes errors and cancellation easier to explain. This lesson adds no real application request or credential processing;it builds reliable local semantics first.
Evaluate responsiveness and evidence separately
Long main-thread work can delay user interaction and rendering work. An async keyword does not move CPU cost to another thread;bounded work or appropriate worker design needs separate evaluation. This lesson supplies no stall-duration,device-speed or universal-refresh guarantee. Its native fixture uses short,finite callbacks.
Follow the synchronous prefix, microtask order and await continuation by identifying which callback runs at each phase. A completion label must name the completed operation. Resolving a Promise does not mean its dependent reaction executed at that moment; retain task and microtask ordering separately.
NOW APPLY IT TO THE CASE
What distinct completion boundaries belong to executors, microtasks, await continuations and timers?
The finite example starts with script:start, executor and script:end; promise, microtask and nested run at the checkpoint, followed by timer. Await does not prevent caller progress. This order measures neither exact latency, painted pixels nor business commit.
Order response receipt, parsing, callbacks and visible DOM outcome in the case. Try explaining the retained old title through this lesson’s browser-state distinctions.
Open the related case file ↗READ THE EXAMPLE TOGETHER
Bounded callback-order ledger
Select a field and examine what it supports and where the evidence ends.
Read the raw artifact and field explanations
{
"normalCode": "const log=[];log.push(\"script:start\");new Promise(resolve=>{log.push(\"executor\");resolve();}).then(()=>log.push(\"promise\"));queueMicrotask(()=>{log.push(\"microtask\");queueMicrotask(()=>log.push(\"nested\"));});setTimeout(()=>log.push(\"timer\"),0);log.push(\"script:end\");",
"expectedLog": [
"script:start",
"executor",
"script:end",
"promise",
"microtask",
"nested",
"timer"
],
"expectedCallTrace": [
"A:start",
"B",
"A:end"
],
"expectedAwaitTrace": [
"before-await",
"after-call",
"after-await"
],
"executionContextModel": "Instructional specification aliases,not engine memory/stack capture",
"timerDelayArgument": 0,
"elapsedMillisecondsExpected": null,
"microtasksAddedByMicrotask": 1,
"renderOrderingWithTimer": "unspecified in this fixture",
"paintCaptured": false,
"networkExecuted": false
}- expectedLog
- Ordering for one ordinary synchronous start and bounded checkpoint.
- timerDelayArgument
- Scheduling request,not a measured callback execution time.
- executionContextModel
- Specification aliases,not a native context object accessible to script.
- paintCaptured
- False:callback ordering does not establish presentation timing.
Ordinary finite browser fixture. No timer-latency,rAF/timer-order,network,engine-memory,worker-concurrency or pixel capture. Scene queues are selected semantic aliases.
Two reality checks
All code inside a Promise runs asynchronously.
The constructor invokes its executor synchronously;the then reaction runs later at an appropriate checkpoint.
A timer0runs immediately,and every task is followed by a paint.
A timer does not interrupt current code;rendering has separate task/opportunity conditions.Ordering is not timing measurement.
YOUR TURN
Work through this story.
Predict the outcome, find the evidence boundary, and explain it in your own words.
What is the order of the Promise executor, script:end and the .then callback?
- promise → executor → script:end; a Promise creates a new thread.
- executor → script:end → promise.
Read the explained answer
executor → script:end → promise. — The new Promise executor runs in the current job; the then reaction is processed at a checkpoint after the current script finishes.
Why is setTimeout(..., 0) not evidence of execution at exactly 0 ms here?
Selected lesson artifact fields; teaching example
- expectedLog
- ["script:start","executor","script:end","promise","microtask","nested","timer"]
- timerDelayArgument
- 0
- elapsedMillisecondsExpected
- null
- The timer task follows microtasks in the selected log; elapsed time is not supplied.
- Argument 0 guarantees execution in the middle of the script at exactly 0 ms.
Read the explained answer
The timer task follows microtasks in the selected log; elapsed time is not supplied. — elapsedMillisecondsExpected=null; pending jobs/checkpoints and scheduling time remain distinct from the delay argument.
Why does before-await, after-call, after-await ordering not imply a new thread? What does it not establish about paint?
Read the explained answer
await suspends a function continuation and permits the caller to progress; the reaction resumes through later job/microtask scheduling. This trace is not an engine-thread/memory capture. DOM or callback completion supplies no pixels or raf-timer ordering guarantee beyond paintCaptured=false.
□ I did not count continuation scheduling as thread creation.
□ I did not count log order as a paint measurement.
Open the application console · request / response / browser
Also open request, URL, cookie and DOM examples
MANUAL LAB
Browser Observation Lab
Predict Document, DOM/CSS, and event-loop results in 18 fields, record native Browser observations, and explain why.
Open the prediction → observation → explanation workbook ↗Source on GitHub ↗Sources and scope
- ECMAScript: Execution contexts and agents9.4 Execution Contexts; 9.6 Agents; specification device not directly observable
- WHATWG HTML: event loops8.1.7.1 Definitions; 8.1.7.2 Queuing tasks; 8.1.7.3 Processing model; perform a microtask checkpoint; rendering task source
- WHATWG HTML: timers and microtask queuing8.6 Timers; 8.7 Microtask queuing
- MDN: Using microtasksTasks vs microtasks; Microtasks; queueMicrotask
- Promise constructorDescription:executor called synchronously; fulfilled reaction asynchronous
- Window requestAnimationFrameDescription:before repaint, one-shot, background pause
- Window setTimeoutReasons for delays longer than specified; Late timeouts; Nested timeouts
- Chromium RenderingNG architectureThreads; main-thread script and rendering; compositor separation