[{"data":1,"prerenderedAt":3164},["ShallowReactive",2],{"page-\u002Fjs\u002F01-introduction-and-setup":3},{"id":4,"title":5,"body":6,"description":3157,"extension":3158,"meta":3159,"navigation":140,"path":3160,"seo":3161,"stem":3162,"__hash__":3163},"content\u002Fjs\u002F01-introduction-and-setup.md","JavaScript 01 — Engine Architecture, Runtime Model & Execution Pipeline",{"type":7,"value":8,"toc":3146},"minimark",[9,14,19,548,552,912,916,1419,1423,1717,1721,1975,1979,2324,2328,2672,2676,2975,2979,2983,3086,3142],[10,11,13],"h1",{"id":12},"_01-engine-architecture-runtime-model-execution-pipeline","01 — Engine Architecture, Runtime Model & Execution Pipeline",[15,16,18],"h2",{"id":17},"how-a-js-engine-executes-your-code","How a JS Engine Executes Your Code",[20,21,23],"code-wrapper",{"language":22},"javascript",[24,25,29],"pre",{"className":26,"code":27,"language":22,"meta":28,"style":28},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F ── The JavaScript execution pipeline (V8, SpiderMonkey, JSCore) ──\n\u002F\u002F\n\u002F\u002F 1. PARSE: Source code → AST (Abstract Syntax Tree)\n\u002F\u002F    - Lexer\u002Ftokenizer: characters → tokens (keywords, identifiers, literals)\n\u002F\u002F    - Parser: tokens → AST (nested node tree representing program structure)\n\u002F\u002F    - Early errors (syntax) are thrown here — before any code runs.\n\u002F\u002F\n\u002F\u002F 2. COMPILE (JIT): AST → bytecode (+ tiered optimization to machine code)\n\u002F\u002F    - Interpreter (Ignition in V8): AST → bytecode, executes immediately\n\u002F\u002F    - Profiler: watches \"hot\" functions (called many times)\n\u002F\u002F    - Optimizing compiler (TurboFan in V8): hot bytecode → optimized machine code\n\u002F\u002F    - Deoptimization: if assumptions break (type changes), falls back to bytecode\n\u002F\u002F\n\u002F\u002F 3. EXECUTE: bytecode\u002Fmachine code runs on the VM\n\u002F\u002F    - Call stack: LIFO stack of execution contexts (frames)\n\u002F\u002F    - Heap: memory allocation for objects, closures, references\n\u002F\u002F    - GC (Orinoco in V8): generational, mark-and-sweep garbage collector\n\n\u002F\u002F ── Execution context structure (created for each function call) ──\n\u002F\u002F Every execution context has:\n\u002F\u002F   1. Variable Environment: var declarations, function declarations (hoisted)\n\u002F\u002F   2. Lexical Environment: let\u002Fconst declarations (TDZ), closures\n\u002F\u002F   3. ThisBinding: the `this` value for this context\n\u002F\u002F   4. Outer: reference to the parent (outer) lexical environment (for scope chain)\n\n\u002F\u002F ── Hoisting: what actually happens during context creation ──\nconsole.log(typeof greet);    \u002F\u002F \"function\" — function declarations are fully hoisted\nconsole.log(typeof x);        \u002F\u002F \"undefined\" — var is hoisted and initialized to undefined\nconsole.log(typeof y);        \u002F\u002F \"ReferenceError\" — let\u002Fconst are hoisted but in TDZ\n\nfunction greet() { return \"hello\"; }  \u002F\u002F hoisted: declaration + body\nvar x = 10;                            \u002F\u002F hoisted: declaration only (x = undefined initially)\nlet y = 20;                           \u002F\u002F hoisted: declaration only, in TDZ until line executes\n\n\u002F\u002F ── The call stack (LIFO — Last In, First Out) ──\nfunction a() { b(); console.log(\"a\"); }  \u002F\u002F a pushes frame, calls b\nfunction b() { c(); console.log(\"b\"); }  \u002F\u002F b pushes frame, calls c\nfunction c() { console.log(\"c\"); }        \u002F\u002F c pushes frame, returns\n\na();\n\u002F\u002F Call stack during execution:\n\u002F\u002F [a] → [a, b] → [a, b, c] → c returns → [a, b] → b returns → [a] → a returns → []\n\u002F\u002F Output: \"c\", \"b\", \"a\" (LIFO — last called, first to complete)\n\n\u002F\u002F ── Stack overflow: no tail-call optimization in V8 (only Safari\u002FJSCore) ──\nfunction recurse(n) {\n    if (n === 0) return;\n    recurse(n - 1);  \u002F\u002F each call adds a frame — no TCO in Chrome\u002FNode\n}\nrecurse(10000);  \u002F\u002F RangeError: Maximum call stack size exceeded (in V8)\n\u002F\u002F Safari\u002FJSCore: supports TCO in strict mode — tail calls don't grow the stack\n\u002F\u002F 'use strict'; function tailRecurse(n, acc = 0) { return n === 0 ? acc : tailRecurse(n - 1, acc + n); }\n","",[30,31,32,41,47,53,59,65,71,76,82,88,94,100,106,111,117,123,129,135,142,148,154,160,166,172,178,183,189,213,230,247,252,277,299,319,324,330,359,386,410,415,424,430,436,442,447,453,470,493,514,520,536,542],"code",{"__ignoreMap":28},[33,34,37],"span",{"class":35,"line":36},"line",1,[33,38,40],{"class":39},"sdCPZ","\u002F\u002F ── The JavaScript execution pipeline (V8, SpiderMonkey, JSCore) ──\n",[33,42,44],{"class":35,"line":43},2,[33,45,46],{"class":39},"\u002F\u002F\n",[33,48,50],{"class":35,"line":49},3,[33,51,52],{"class":39},"\u002F\u002F 1. PARSE: Source code → AST (Abstract Syntax Tree)\n",[33,54,56],{"class":35,"line":55},4,[33,57,58],{"class":39},"\u002F\u002F    - Lexer\u002Ftokenizer: characters → tokens (keywords, identifiers, literals)\n",[33,60,62],{"class":35,"line":61},5,[33,63,64],{"class":39},"\u002F\u002F    - Parser: tokens → AST (nested node tree representing program structure)\n",[33,66,68],{"class":35,"line":67},6,[33,69,70],{"class":39},"\u002F\u002F    - Early errors (syntax) are thrown here — before any code runs.\n",[33,72,74],{"class":35,"line":73},7,[33,75,46],{"class":39},[33,77,79],{"class":35,"line":78},8,[33,80,81],{"class":39},"\u002F\u002F 2. COMPILE (JIT): AST → bytecode (+ tiered optimization to machine code)\n",[33,83,85],{"class":35,"line":84},9,[33,86,87],{"class":39},"\u002F\u002F    - Interpreter (Ignition in V8): AST → bytecode, executes immediately\n",[33,89,91],{"class":35,"line":90},10,[33,92,93],{"class":39},"\u002F\u002F    - Profiler: watches \"hot\" functions (called many times)\n",[33,95,97],{"class":35,"line":96},11,[33,98,99],{"class":39},"\u002F\u002F    - Optimizing compiler (TurboFan in V8): hot bytecode → optimized machine code\n",[33,101,103],{"class":35,"line":102},12,[33,104,105],{"class":39},"\u002F\u002F    - Deoptimization: if assumptions break (type changes), falls back to bytecode\n",[33,107,109],{"class":35,"line":108},13,[33,110,46],{"class":39},[33,112,114],{"class":35,"line":113},14,[33,115,116],{"class":39},"\u002F\u002F 3. EXECUTE: bytecode\u002Fmachine code runs on the VM\n",[33,118,120],{"class":35,"line":119},15,[33,121,122],{"class":39},"\u002F\u002F    - Call stack: LIFO stack of execution contexts (frames)\n",[33,124,126],{"class":35,"line":125},16,[33,127,128],{"class":39},"\u002F\u002F    - Heap: memory allocation for objects, closures, references\n",[33,130,132],{"class":35,"line":131},17,[33,133,134],{"class":39},"\u002F\u002F    - GC (Orinoco in V8): generational, mark-and-sweep garbage collector\n",[33,136,138],{"class":35,"line":137},18,[33,139,141],{"emptyLinePlaceholder":140},true,"\n",[33,143,145],{"class":35,"line":144},19,[33,146,147],{"class":39},"\u002F\u002F ── Execution context structure (created for each function call) ──\n",[33,149,151],{"class":35,"line":150},20,[33,152,153],{"class":39},"\u002F\u002F Every execution context has:\n",[33,155,157],{"class":35,"line":156},21,[33,158,159],{"class":39},"\u002F\u002F   1. Variable Environment: var declarations, function declarations (hoisted)\n",[33,161,163],{"class":35,"line":162},22,[33,164,165],{"class":39},"\u002F\u002F   2. Lexical Environment: let\u002Fconst declarations (TDZ), closures\n",[33,167,169],{"class":35,"line":168},23,[33,170,171],{"class":39},"\u002F\u002F   3. ThisBinding: the `this` value for this context\n",[33,173,175],{"class":35,"line":174},24,[33,176,177],{"class":39},"\u002F\u002F   4. Outer: reference to the parent (outer) lexical environment (for scope chain)\n",[33,179,181],{"class":35,"line":180},25,[33,182,141],{"emptyLinePlaceholder":140},[33,184,186],{"class":35,"line":185},26,[33,187,188],{"class":39},"\u002F\u002F ── Hoisting: what actually happens during context creation ──\n",[33,190,192,196,200,203,207,210],{"class":35,"line":191},27,[33,193,195],{"class":194},"ssxIu","console.",[33,197,199],{"class":198},"sIsaT","log",[33,201,202],{"class":194},"(",[33,204,206],{"class":205},"svdQ7","typeof",[33,208,209],{"class":194}," greet);    ",[33,211,212],{"class":39},"\u002F\u002F \"function\" — function declarations are fully hoisted\n",[33,214,216,218,220,222,224,227],{"class":35,"line":215},28,[33,217,195],{"class":194},[33,219,199],{"class":198},[33,221,202],{"class":194},[33,223,206],{"class":205},[33,225,226],{"class":194}," x);        ",[33,228,229],{"class":39},"\u002F\u002F \"undefined\" — var is hoisted and initialized to undefined\n",[33,231,233,235,237,239,241,244],{"class":35,"line":232},29,[33,234,195],{"class":194},[33,236,199],{"class":198},[33,238,202],{"class":194},[33,240,206],{"class":205},[33,242,243],{"class":194}," y);        ",[33,245,246],{"class":39},"\u002F\u002F \"ReferenceError\" — let\u002Fconst are hoisted but in TDZ\n",[33,248,250],{"class":35,"line":249},30,[33,251,141],{"emptyLinePlaceholder":140},[33,253,255,258,261,264,267,271,274],{"class":35,"line":254},31,[33,256,257],{"class":205},"function",[33,259,260],{"class":198}," greet",[33,262,263],{"class":194},"() { ",[33,265,266],{"class":205},"return",[33,268,270],{"class":269},"sJ6F3"," \"hello\"",[33,272,273],{"class":194},"; }  ",[33,275,276],{"class":39},"\u002F\u002F hoisted: declaration + body\n",[33,278,280,283,286,289,293,296],{"class":35,"line":279},32,[33,281,282],{"class":205},"var",[33,284,285],{"class":194}," x ",[33,287,288],{"class":205},"=",[33,290,292],{"class":291},"snvgF"," 10",[33,294,295],{"class":194},";                            ",[33,297,298],{"class":39},"\u002F\u002F hoisted: declaration only (x = undefined initially)\n",[33,300,302,305,308,310,313,316],{"class":35,"line":301},33,[33,303,304],{"class":205},"let",[33,306,307],{"class":194}," y ",[33,309,288],{"class":205},[33,311,312],{"class":291}," 20",[33,314,315],{"class":194},";                           ",[33,317,318],{"class":39},"\u002F\u002F hoisted: declaration only, in TDZ until line executes\n",[33,320,322],{"class":35,"line":321},34,[33,323,141],{"emptyLinePlaceholder":140},[33,325,327],{"class":35,"line":326},35,[33,328,329],{"class":39},"\u002F\u002F ── The call stack (LIFO — Last In, First Out) ──\n",[33,331,333,335,338,340,343,346,348,350,353,356],{"class":35,"line":332},36,[33,334,257],{"class":205},[33,336,337],{"class":198}," a",[33,339,263],{"class":194},[33,341,342],{"class":198},"b",[33,344,345],{"class":194},"(); console.",[33,347,199],{"class":198},[33,349,202],{"class":194},[33,351,352],{"class":269},"\"a\"",[33,354,355],{"class":194},"); }  ",[33,357,358],{"class":39},"\u002F\u002F a pushes frame, calls b\n",[33,360,362,364,367,369,372,374,376,378,381,383],{"class":35,"line":361},37,[33,363,257],{"class":205},[33,365,366],{"class":198}," b",[33,368,263],{"class":194},[33,370,371],{"class":198},"c",[33,373,345],{"class":194},[33,375,199],{"class":198},[33,377,202],{"class":194},[33,379,380],{"class":269},"\"b\"",[33,382,355],{"class":194},[33,384,385],{"class":39},"\u002F\u002F b pushes frame, calls c\n",[33,387,389,391,394,397,399,401,404,407],{"class":35,"line":388},38,[33,390,257],{"class":205},[33,392,393],{"class":198}," c",[33,395,396],{"class":194},"() { console.",[33,398,199],{"class":198},[33,400,202],{"class":194},[33,402,403],{"class":269},"\"c\"",[33,405,406],{"class":194},"); }        ",[33,408,409],{"class":39},"\u002F\u002F c pushes frame, returns\n",[33,411,413],{"class":35,"line":412},39,[33,414,141],{"emptyLinePlaceholder":140},[33,416,418,421],{"class":35,"line":417},40,[33,419,420],{"class":198},"a",[33,422,423],{"class":194},"();\n",[33,425,427],{"class":35,"line":426},41,[33,428,429],{"class":39},"\u002F\u002F Call stack during execution:\n",[33,431,433],{"class":35,"line":432},42,[33,434,435],{"class":39},"\u002F\u002F [a] → [a, b] → [a, b, c] → c returns → [a, b] → b returns → [a] → a returns → []\n",[33,437,439],{"class":35,"line":438},43,[33,440,441],{"class":39},"\u002F\u002F Output: \"c\", \"b\", \"a\" (LIFO — last called, first to complete)\n",[33,443,445],{"class":35,"line":444},44,[33,446,141],{"emptyLinePlaceholder":140},[33,448,450],{"class":35,"line":449},45,[33,451,452],{"class":39},"\u002F\u002F ── Stack overflow: no tail-call optimization in V8 (only Safari\u002FJSCore) ──\n",[33,454,456,458,461,463,467],{"class":35,"line":455},46,[33,457,257],{"class":205},[33,459,460],{"class":198}," recurse",[33,462,202],{"class":194},[33,464,466],{"class":465},"sCrzJ","n",[33,468,469],{"class":194},") {\n",[33,471,473,476,479,482,485,488,490],{"class":35,"line":472},47,[33,474,475],{"class":205},"    if",[33,477,478],{"class":194}," (n ",[33,480,481],{"class":205},"===",[33,483,484],{"class":291}," 0",[33,486,487],{"class":194},") ",[33,489,266],{"class":205},[33,491,492],{"class":194},";\n",[33,494,496,499,502,505,508,511],{"class":35,"line":495},48,[33,497,498],{"class":198},"    recurse",[33,500,501],{"class":194},"(n ",[33,503,504],{"class":205},"-",[33,506,507],{"class":291}," 1",[33,509,510],{"class":194},");  ",[33,512,513],{"class":39},"\u002F\u002F each call adds a frame — no TCO in Chrome\u002FNode\n",[33,515,517],{"class":35,"line":516},49,[33,518,519],{"class":194},"}\n",[33,521,523,526,528,531,533],{"class":35,"line":522},50,[33,524,525],{"class":198},"recurse",[33,527,202],{"class":194},[33,529,530],{"class":291},"10000",[33,532,510],{"class":194},[33,534,535],{"class":39},"\u002F\u002F RangeError: Maximum call stack size exceeded (in V8)\n",[33,537,539],{"class":35,"line":538},51,[33,540,541],{"class":39},"\u002F\u002F Safari\u002FJSCore: supports TCO in strict mode — tail calls don't grow the stack\n",[33,543,545],{"class":35,"line":544},52,[33,546,547],{"class":39},"\u002F\u002F 'use strict'; function tailRecurse(n, acc = 0) { return n === 0 ? acc : tailRecurse(n - 1, acc + n); }\n",[15,549,551],{"id":550},"anti-pattern-blocking-the-main-thread","Anti-Pattern: Blocking the Main Thread",[20,553,554],{"language":22},[24,555,557],{"className":26,"code":556,"language":22,"meta":28,"style":28},"\u002F\u002F ❌ NAIVE — synchronous heavy computation blocks the event loop\n\u002F\u002F JS is single-threaded: one call stack, one event loop, one heap.\n\u002F\u002F While this runs, NOTHING else can: no UI updates, no timers, no I\u002FO callbacks.\n\nfunction blockingFibonacci(n) {\n    return n \u003C= 1 ? n : blockingFibonacci(n - 1) + blockingFibonacci(n - 2);\n}\n\u002F\u002F blockingFibonacci(45);  \u002F\u002F ~5 seconds of frozen UI — the entire main thread is blocked\n\n\u002F\u002F ✅ CORRECT — chunk work with setTimeout\u002Fscheduler to yield to the event loop\n\u002F\u002F Each chunk runs, then yields control back so the event loop can process other tasks.\nasync function chunkedFibonacci(n, chunkSize = 1000) {\n    return new Promise(resolve => {\n        let a = 0n, b = 1n, i = 0;\n\n        function chunk() {\n            const end = Math.min(i + chunkSize, n);\n            for (; i \u003C end; i++) {\n                [a, b] = [b, a + b];  \u002F\u002F BigInt — no precision loss for large numbers\n            }\n            if (i \u003C n) {\n                setTimeout(chunk, 0);  \u002F\u002F yield to event loop — other callbacks can run\n            } else {\n                resolve(a.toString());\n            }\n        }\n        chunk();\n    });\n}\n\u002F\u002F chunkedFibonacci(100000).then(r => console.log(r));  \u002F\u002F UI stays responsive\n",[30,558,559,564,569,574,578,591,637,641,649,653,658,663,692,713,745,749,760,784,803,821,826,839,855,865,879,883,888,895,900,904],{"__ignoreMap":28},[33,560,561],{"class":35,"line":36},[33,562,563],{"class":39},"\u002F\u002F ❌ NAIVE — synchronous heavy computation blocks the event loop\n",[33,565,566],{"class":35,"line":43},[33,567,568],{"class":39},"\u002F\u002F JS is single-threaded: one call stack, one event loop, one heap.\n",[33,570,571],{"class":35,"line":49},[33,572,573],{"class":39},"\u002F\u002F While this runs, NOTHING else can: no UI updates, no timers, no I\u002FO callbacks.\n",[33,575,576],{"class":35,"line":55},[33,577,141],{"emptyLinePlaceholder":140},[33,579,580,582,585,587,589],{"class":35,"line":61},[33,581,257],{"class":205},[33,583,584],{"class":198}," blockingFibonacci",[33,586,202],{"class":194},[33,588,466],{"class":465},[33,590,469],{"class":194},[33,592,593,596,599,602,604,607,609,612,614,616,618,620,622,625,627,629,631,634],{"class":35,"line":67},[33,594,595],{"class":205},"    return",[33,597,598],{"class":194}," n ",[33,600,601],{"class":205},"\u003C=",[33,603,507],{"class":291},[33,605,606],{"class":205}," ?",[33,608,598],{"class":194},[33,610,611],{"class":205},":",[33,613,584],{"class":198},[33,615,501],{"class":194},[33,617,504],{"class":205},[33,619,507],{"class":291},[33,621,487],{"class":194},[33,623,624],{"class":205},"+",[33,626,584],{"class":198},[33,628,501],{"class":194},[33,630,504],{"class":205},[33,632,633],{"class":291}," 2",[33,635,636],{"class":194},");\n",[33,638,639],{"class":35,"line":73},[33,640,519],{"class":194},[33,642,643,646],{"class":35,"line":78},[33,644,645],{"class":39},"\u002F\u002F blockingFibonacci(45);",[33,647,648],{"class":39},"  \u002F\u002F ~5 seconds of frozen UI — the entire main thread is blocked\n",[33,650,651],{"class":35,"line":84},[33,652,141],{"emptyLinePlaceholder":140},[33,654,655],{"class":35,"line":90},[33,656,657],{"class":39},"\u002F\u002F ✅ CORRECT — chunk work with setTimeout\u002Fscheduler to yield to the event loop\n",[33,659,660],{"class":35,"line":96},[33,661,662],{"class":39},"\u002F\u002F Each chunk runs, then yields control back so the event loop can process other tasks.\n",[33,664,665,668,671,674,676,678,681,684,687,690],{"class":35,"line":102},[33,666,667],{"class":205},"async",[33,669,670],{"class":205}," function",[33,672,673],{"class":198}," chunkedFibonacci",[33,675,202],{"class":194},[33,677,466],{"class":465},[33,679,680],{"class":194},", ",[33,682,683],{"class":465},"chunkSize",[33,685,686],{"class":205}," =",[33,688,689],{"class":291}," 1000",[33,691,469],{"class":194},[33,693,694,696,699,702,704,707,710],{"class":35,"line":108},[33,695,595],{"class":205},[33,697,698],{"class":205}," new",[33,700,701],{"class":291}," Promise",[33,703,202],{"class":194},[33,705,706],{"class":465},"resolve",[33,708,709],{"class":205}," =>",[33,711,712],{"class":194}," {\n",[33,714,715,718,721,723,725,727,730,732,734,736,739,741,743],{"class":35,"line":113},[33,716,717],{"class":205},"        let",[33,719,720],{"class":194}," a ",[33,722,288],{"class":205},[33,724,484],{"class":291},[33,726,466],{"class":205},[33,728,729],{"class":194},", b ",[33,731,288],{"class":205},[33,733,507],{"class":291},[33,735,466],{"class":205},[33,737,738],{"class":194},", i ",[33,740,288],{"class":205},[33,742,484],{"class":291},[33,744,492],{"class":194},[33,746,747],{"class":35,"line":119},[33,748,141],{"emptyLinePlaceholder":140},[33,750,751,754,757],{"class":35,"line":125},[33,752,753],{"class":205},"        function",[33,755,756],{"class":198}," chunk",[33,758,759],{"class":194},"() {\n",[33,761,762,765,768,770,773,776,779,781],{"class":35,"line":131},[33,763,764],{"class":205},"            const",[33,766,767],{"class":291}," end",[33,769,686],{"class":205},[33,771,772],{"class":194}," Math.",[33,774,775],{"class":198},"min",[33,777,778],{"class":194},"(i ",[33,780,624],{"class":205},[33,782,783],{"class":194}," chunkSize, n);\n",[33,785,786,789,792,795,798,801],{"class":35,"line":137},[33,787,788],{"class":205},"            for",[33,790,791],{"class":194}," (; i ",[33,793,794],{"class":205},"\u003C",[33,796,797],{"class":194}," end; i",[33,799,800],{"class":205},"++",[33,802,469],{"class":194},[33,804,805,808,810,813,815,818],{"class":35,"line":144},[33,806,807],{"class":194},"                [a, b] ",[33,809,288],{"class":205},[33,811,812],{"class":194}," [b, a ",[33,814,624],{"class":205},[33,816,817],{"class":194}," b];  ",[33,819,820],{"class":39},"\u002F\u002F BigInt — no precision loss for large numbers\n",[33,822,823],{"class":35,"line":150},[33,824,825],{"class":194},"            }\n",[33,827,828,831,834,836],{"class":35,"line":156},[33,829,830],{"class":205},"            if",[33,832,833],{"class":194}," (i ",[33,835,794],{"class":205},[33,837,838],{"class":194}," n) {\n",[33,840,841,844,847,850,852],{"class":35,"line":162},[33,842,843],{"class":198},"                setTimeout",[33,845,846],{"class":194},"(chunk, ",[33,848,849],{"class":291},"0",[33,851,510],{"class":194},[33,853,854],{"class":39},"\u002F\u002F yield to event loop — other callbacks can run\n",[33,856,857,860,863],{"class":35,"line":168},[33,858,859],{"class":194},"            } ",[33,861,862],{"class":205},"else",[33,864,712],{"class":194},[33,866,867,870,873,876],{"class":35,"line":174},[33,868,869],{"class":198},"                resolve",[33,871,872],{"class":194},"(a.",[33,874,875],{"class":198},"toString",[33,877,878],{"class":194},"());\n",[33,880,881],{"class":35,"line":180},[33,882,825],{"class":194},[33,884,885],{"class":35,"line":185},[33,886,887],{"class":194},"        }\n",[33,889,890,893],{"class":35,"line":191},[33,891,892],{"class":198},"        chunk",[33,894,423],{"class":194},[33,896,897],{"class":35,"line":215},[33,898,899],{"class":194},"    });\n",[33,901,902],{"class":35,"line":232},[33,903,519],{"class":194},[33,905,906,909],{"class":35,"line":249},[33,907,908],{"class":39},"\u002F\u002F chunkedFibonacci(100000).then(r => console.log(r));",[33,910,911],{"class":39},"  \u002F\u002F UI stays responsive\n",[15,913,915],{"id":914},"v8s-tiered-compilation-pipeline","V8's Tiered Compilation Pipeline",[20,917,918],{"language":22},[24,919,921],{"className":26,"code":920,"language":22,"meta":28,"style":28},"\u002F\u002F ── V8's JIT pipeline (Ignition + TurboFan) ──\n\u002F\u002F\n\u002F\u002F Source → AST → Ignition (bytecode interpreter)\n\u002F\u002F                    ↓ (hot function detected)\n\u002F\u002F              TurboFan (optimizing compiler)\n\u002F\u002F                    ↓ (assumptions broken)\n\u002F\u002F              Deoptimize → back to bytecode\n\n\u002F\u002F ── Type speculation: TurboFan optimizes based on observed types ──\nfunction add(a, b) { return a + b; }\n\nadd(1, 2);       \u002F\u002F TurboFan sees: always numbers → compiles to integer add\nadd(1, 2);       \u002F\u002F hot function — optimized machine code (fast path)\nadd(1, 2);\nadd(\"x\", \"y\");   \u002F\u002F ✗ type changed to string! → DEOPTIMIZE → falls back to bytecode\n\u002F\u002F After deopt, V8 may re-optimize with a more general (slower) version.\n\n\u002F\u002F ── Hidden classes (Shapes\u002FMaps): V8's object layout optimization ──\n\u002F\u002F V8 assigns objects a \"hidden class\" (internal shape) based on their properties.\n\u002F\u002F Same property order → same hidden class → fast property access (inline caches).\n\nfunction Point(x, y) {\n    this.x = x;  \u002F\u002F Point class created with {x}\n    this.y = y;  \u002F\u002F class transitioned to {x, y}\n}\nconst p1 = new Point(1, 2);  \u002F\u002F hidden class: Point{x, y}\nconst p2 = new Point(3, 4);  \u002F\u002F same hidden class: Point{x, y} → fast!\n\n\u002F\u002F ❌ Property order matters — this creates a DIFFERENT hidden class:\nfunction BadPoint(x, y) {\n    this.y = y;  \u002F\u002F BadPoint class created with {y} — different transition path\n    this.x = x;  \u002F\u002F transitioned to {y, x} — different from Point{x, y}\n}\nconst p3 = new BadPoint(1, 2);  \u002F\u002F hidden class: BadPoint{y, x} — NOT same as Point\n\n\u002F\u002F ❌ Adding properties after construction causes class transitions (slow):\nconst p4 = new Point(5, 6);\np4.z = 7;  \u002F\u002F class transition: Point{x, y} → Point{x, y, z} (new hidden class)\n\u002F\u002F All future Point instances still use Point{x, y} — p4 is a different shape now.\n\n\u002F\u002F ✅ Declare all properties in the constructor for consistent hidden classes:\nfunction FastPoint(x, y, z = 0) {\n    this.x = x;\n    this.y = y;\n    this.z = z;  \u002F\u002F all properties declared upfront — single hidden class\n}\n",[30,922,923,928,932,937,942,947,952,957,961,966,993,997,1018,1035,1049,1069,1074,1078,1083,1088,1093,1097,1116,1132,1147,1151,1178,1206,1210,1215,1232,1245,1258,1262,1288,1292,1297,1322,1338,1343,1347,1352,1378,1389,1400,1415],{"__ignoreMap":28},[33,924,925],{"class":35,"line":36},[33,926,927],{"class":39},"\u002F\u002F ── V8's JIT pipeline (Ignition + TurboFan) ──\n",[33,929,930],{"class":35,"line":43},[33,931,46],{"class":39},[33,933,934],{"class":35,"line":49},[33,935,936],{"class":39},"\u002F\u002F Source → AST → Ignition (bytecode interpreter)\n",[33,938,939],{"class":35,"line":55},[33,940,941],{"class":39},"\u002F\u002F                    ↓ (hot function detected)\n",[33,943,944],{"class":35,"line":61},[33,945,946],{"class":39},"\u002F\u002F              TurboFan (optimizing compiler)\n",[33,948,949],{"class":35,"line":67},[33,950,951],{"class":39},"\u002F\u002F                    ↓ (assumptions broken)\n",[33,953,954],{"class":35,"line":73},[33,955,956],{"class":39},"\u002F\u002F              Deoptimize → back to bytecode\n",[33,958,959],{"class":35,"line":78},[33,960,141],{"emptyLinePlaceholder":140},[33,962,963],{"class":35,"line":84},[33,964,965],{"class":39},"\u002F\u002F ── Type speculation: TurboFan optimizes based on observed types ──\n",[33,967,968,970,973,975,977,979,981,984,986,988,990],{"class":35,"line":90},[33,969,257],{"class":205},[33,971,972],{"class":198}," add",[33,974,202],{"class":194},[33,976,420],{"class":465},[33,978,680],{"class":194},[33,980,342],{"class":465},[33,982,983],{"class":194},") { ",[33,985,266],{"class":205},[33,987,720],{"class":194},[33,989,624],{"class":205},[33,991,992],{"class":194}," b; }\n",[33,994,995],{"class":35,"line":96},[33,996,141],{"emptyLinePlaceholder":140},[33,998,999,1002,1004,1007,1009,1012,1015],{"class":35,"line":102},[33,1000,1001],{"class":198},"add",[33,1003,202],{"class":194},[33,1005,1006],{"class":291},"1",[33,1008,680],{"class":194},[33,1010,1011],{"class":291},"2",[33,1013,1014],{"class":194},");       ",[33,1016,1017],{"class":39},"\u002F\u002F TurboFan sees: always numbers → compiles to integer add\n",[33,1019,1020,1022,1024,1026,1028,1030,1032],{"class":35,"line":108},[33,1021,1001],{"class":198},[33,1023,202],{"class":194},[33,1025,1006],{"class":291},[33,1027,680],{"class":194},[33,1029,1011],{"class":291},[33,1031,1014],{"class":194},[33,1033,1034],{"class":39},"\u002F\u002F hot function — optimized machine code (fast path)\n",[33,1036,1037,1039,1041,1043,1045,1047],{"class":35,"line":113},[33,1038,1001],{"class":198},[33,1040,202],{"class":194},[33,1042,1006],{"class":291},[33,1044,680],{"class":194},[33,1046,1011],{"class":291},[33,1048,636],{"class":194},[33,1050,1051,1053,1055,1058,1060,1063,1066],{"class":35,"line":119},[33,1052,1001],{"class":198},[33,1054,202],{"class":194},[33,1056,1057],{"class":269},"\"x\"",[33,1059,680],{"class":194},[33,1061,1062],{"class":269},"\"y\"",[33,1064,1065],{"class":194},");   ",[33,1067,1068],{"class":39},"\u002F\u002F ✗ type changed to string! → DEOPTIMIZE → falls back to bytecode\n",[33,1070,1071],{"class":35,"line":125},[33,1072,1073],{"class":39},"\u002F\u002F After deopt, V8 may re-optimize with a more general (slower) version.\n",[33,1075,1076],{"class":35,"line":131},[33,1077,141],{"emptyLinePlaceholder":140},[33,1079,1080],{"class":35,"line":137},[33,1081,1082],{"class":39},"\u002F\u002F ── Hidden classes (Shapes\u002FMaps): V8's object layout optimization ──\n",[33,1084,1085],{"class":35,"line":144},[33,1086,1087],{"class":39},"\u002F\u002F V8 assigns objects a \"hidden class\" (internal shape) based on their properties.\n",[33,1089,1090],{"class":35,"line":150},[33,1091,1092],{"class":39},"\u002F\u002F Same property order → same hidden class → fast property access (inline caches).\n",[33,1094,1095],{"class":35,"line":156},[33,1096,141],{"emptyLinePlaceholder":140},[33,1098,1099,1101,1104,1106,1109,1111,1114],{"class":35,"line":162},[33,1100,257],{"class":205},[33,1102,1103],{"class":198}," Point",[33,1105,202],{"class":194},[33,1107,1108],{"class":465},"x",[33,1110,680],{"class":194},[33,1112,1113],{"class":465},"y",[33,1115,469],{"class":194},[33,1117,1118,1121,1124,1126,1129],{"class":35,"line":168},[33,1119,1120],{"class":291},"    this",[33,1122,1123],{"class":194},".x ",[33,1125,288],{"class":205},[33,1127,1128],{"class":194}," x;  ",[33,1130,1131],{"class":39},"\u002F\u002F Point class created with {x}\n",[33,1133,1134,1136,1139,1141,1144],{"class":35,"line":174},[33,1135,1120],{"class":291},[33,1137,1138],{"class":194},".y ",[33,1140,288],{"class":205},[33,1142,1143],{"class":194}," y;  ",[33,1145,1146],{"class":39},"\u002F\u002F class transitioned to {x, y}\n",[33,1148,1149],{"class":35,"line":180},[33,1150,519],{"class":194},[33,1152,1153,1156,1159,1161,1163,1165,1167,1169,1171,1173,1175],{"class":35,"line":185},[33,1154,1155],{"class":205},"const",[33,1157,1158],{"class":291}," p1",[33,1160,686],{"class":205},[33,1162,698],{"class":205},[33,1164,1103],{"class":198},[33,1166,202],{"class":194},[33,1168,1006],{"class":291},[33,1170,680],{"class":194},[33,1172,1011],{"class":291},[33,1174,510],{"class":194},[33,1176,1177],{"class":39},"\u002F\u002F hidden class: Point{x, y}\n",[33,1179,1180,1182,1185,1187,1189,1191,1193,1196,1198,1201,1203],{"class":35,"line":191},[33,1181,1155],{"class":205},[33,1183,1184],{"class":291}," p2",[33,1186,686],{"class":205},[33,1188,698],{"class":205},[33,1190,1103],{"class":198},[33,1192,202],{"class":194},[33,1194,1195],{"class":291},"3",[33,1197,680],{"class":194},[33,1199,1200],{"class":291},"4",[33,1202,510],{"class":194},[33,1204,1205],{"class":39},"\u002F\u002F same hidden class: Point{x, y} → fast!\n",[33,1207,1208],{"class":35,"line":215},[33,1209,141],{"emptyLinePlaceholder":140},[33,1211,1212],{"class":35,"line":232},[33,1213,1214],{"class":39},"\u002F\u002F ❌ Property order matters — this creates a DIFFERENT hidden class:\n",[33,1216,1217,1219,1222,1224,1226,1228,1230],{"class":35,"line":249},[33,1218,257],{"class":205},[33,1220,1221],{"class":198}," BadPoint",[33,1223,202],{"class":194},[33,1225,1108],{"class":465},[33,1227,680],{"class":194},[33,1229,1113],{"class":465},[33,1231,469],{"class":194},[33,1233,1234,1236,1238,1240,1242],{"class":35,"line":254},[33,1235,1120],{"class":291},[33,1237,1138],{"class":194},[33,1239,288],{"class":205},[33,1241,1143],{"class":194},[33,1243,1244],{"class":39},"\u002F\u002F BadPoint class created with {y} — different transition path\n",[33,1246,1247,1249,1251,1253,1255],{"class":35,"line":279},[33,1248,1120],{"class":291},[33,1250,1123],{"class":194},[33,1252,288],{"class":205},[33,1254,1128],{"class":194},[33,1256,1257],{"class":39},"\u002F\u002F transitioned to {y, x} — different from Point{x, y}\n",[33,1259,1260],{"class":35,"line":301},[33,1261,519],{"class":194},[33,1263,1264,1266,1269,1271,1273,1275,1277,1279,1281,1283,1285],{"class":35,"line":321},[33,1265,1155],{"class":205},[33,1267,1268],{"class":291}," p3",[33,1270,686],{"class":205},[33,1272,698],{"class":205},[33,1274,1221],{"class":198},[33,1276,202],{"class":194},[33,1278,1006],{"class":291},[33,1280,680],{"class":194},[33,1282,1011],{"class":291},[33,1284,510],{"class":194},[33,1286,1287],{"class":39},"\u002F\u002F hidden class: BadPoint{y, x} — NOT same as Point\n",[33,1289,1290],{"class":35,"line":326},[33,1291,141],{"emptyLinePlaceholder":140},[33,1293,1294],{"class":35,"line":332},[33,1295,1296],{"class":39},"\u002F\u002F ❌ Adding properties after construction causes class transitions (slow):\n",[33,1298,1299,1301,1304,1306,1308,1310,1312,1315,1317,1320],{"class":35,"line":361},[33,1300,1155],{"class":205},[33,1302,1303],{"class":291}," p4",[33,1305,686],{"class":205},[33,1307,698],{"class":205},[33,1309,1103],{"class":198},[33,1311,202],{"class":194},[33,1313,1314],{"class":291},"5",[33,1316,680],{"class":194},[33,1318,1319],{"class":291},"6",[33,1321,636],{"class":194},[33,1323,1324,1327,1329,1332,1335],{"class":35,"line":388},[33,1325,1326],{"class":194},"p4.z ",[33,1328,288],{"class":205},[33,1330,1331],{"class":291}," 7",[33,1333,1334],{"class":194},";  ",[33,1336,1337],{"class":39},"\u002F\u002F class transition: Point{x, y} → Point{x, y, z} (new hidden class)\n",[33,1339,1340],{"class":35,"line":412},[33,1341,1342],{"class":39},"\u002F\u002F All future Point instances still use Point{x, y} — p4 is a different shape now.\n",[33,1344,1345],{"class":35,"line":417},[33,1346,141],{"emptyLinePlaceholder":140},[33,1348,1349],{"class":35,"line":426},[33,1350,1351],{"class":39},"\u002F\u002F ✅ Declare all properties in the constructor for consistent hidden classes:\n",[33,1353,1354,1356,1359,1361,1363,1365,1367,1369,1372,1374,1376],{"class":35,"line":432},[33,1355,257],{"class":205},[33,1357,1358],{"class":198}," FastPoint",[33,1360,202],{"class":194},[33,1362,1108],{"class":465},[33,1364,680],{"class":194},[33,1366,1113],{"class":465},[33,1368,680],{"class":194},[33,1370,1371],{"class":465},"z",[33,1373,686],{"class":205},[33,1375,484],{"class":291},[33,1377,469],{"class":194},[33,1379,1380,1382,1384,1386],{"class":35,"line":438},[33,1381,1120],{"class":291},[33,1383,1123],{"class":194},[33,1385,288],{"class":205},[33,1387,1388],{"class":194}," x;\n",[33,1390,1391,1393,1395,1397],{"class":35,"line":444},[33,1392,1120],{"class":291},[33,1394,1138],{"class":194},[33,1396,288],{"class":205},[33,1398,1399],{"class":194}," y;\n",[33,1401,1402,1404,1407,1409,1412],{"class":35,"line":449},[33,1403,1120],{"class":291},[33,1405,1406],{"class":194},".z ",[33,1408,288],{"class":205},[33,1410,1411],{"class":194}," z;  ",[33,1413,1414],{"class":39},"\u002F\u002F all properties declared upfront — single hidden class\n",[33,1416,1417],{"class":35,"line":455},[33,1418,519],{"class":194},[15,1420,1422],{"id":1421},"nodejs-vs-browser-runtime","Node.js vs Browser Runtime",[20,1424,1425],{"language":22},[24,1426,1428],{"className":26,"code":1427,"language":22,"meta":28,"style":28},"\u002F\u002F ── Browser runtime model ──\n\u002F\u002F   ┌──────────────────┐     ┌───────────────────┐\n\u002F\u002F   │  JS Engine (V8)  │     │  Web APIs (C++)   │\n\u002F\u002F   │  Call Stack       │     │  DOM, fetch,      │\n\u002F\u002F   │  Heap (GC)       │     │  setTimeout, XHR  │\n\u002F\u002F   └────────┬─────────┘     └─────────┬─────────┘\n\u002F\u002F            │                          │\n\u002F\u002F            │   ┌──────────────────────┘\n\u002F\u002F            │   │\n\u002F\u002F   ┌────────▼───▼────────┐\n\u002F\u002F   │   Event Loop        │\n\u002F\u002F   │   (libuv in Node,   │\n\u002F\u002F    │   browser-native)  │\n\u002F\u002F   │                     │\n\u002F\u002F   │   ┌───────────────┐ │\n\u002F\u002F   │   │ Microtask Q    │ │ ← Promise.then, queueMicrotask, MutationObserver\n\u002F\u002F   │   │ (drained fully)│ │    (runs AFTER each macrotask, before next)\n\u002F\u002F   │   └───────────────┘ │\n\u002F\u002F   │   ┌───────────────┐ │\n\u002F\u002F   │   │ Macrotask Q    │ │ ← setTimeout, setInterval, I\u002FO, UI events\n\u002F\u002F   │   │ (one per tick) │ │    (one macrotask per event loop tick)\n\u002F\u002F   │   └───────────────┘ │\n\u002F\u002F   └─────────────────────┘\n\n\u002F\u002F ── Node.js runtime model ──\n\u002F\u002F   Same V8 engine, but different host environment:\n\u002F\u002F   - No DOM, no window, no document\n\u002F\u002F   - Has: process, Buffer, __dirname, __filename, require()\n\u002F\u002F   - libuv provides the event loop (cross-platform async I\u002FO)\n\u002F\u002F   - Timers: setTimeout\u002FsetInterval (from Node, not window)\n\u002F\u002F   - Microtasks: process.nextTick (Node-specific, higher priority than Promises)\n\n\u002F\u002F ── Node-specific APIs (not available in browser) ──\nconst fs = require('fs');          \u002F\u002F file system\nconst http = require('http');      \u002F\u002F HTTP server\u002Fclient\nconst path = require('path');      \u002F\u002F path manipulation\nconst { Worker } = require('worker_threads');  \u002F\u002F true parallelism\n\n\u002F\u002F ── Browser-specific APIs (not available in Node) ──\n\u002F\u002F window, document, localStorage, fetch (Node 18+ has fetch)\n\u002F\u002F DOM manipulation, CSS, Canvas, Web Audio, etc.\n\n\u002F\u002F ── Shared: the language is the same, the platform APIs differ ──\n\u002F\u002F Pure JS (Array methods, Promises, closures, classes) works identically in both.\n",[30,1429,1430,1435,1440,1445,1450,1455,1460,1465,1470,1475,1480,1485,1490,1495,1500,1505,1510,1515,1520,1524,1529,1534,1538,1543,1547,1552,1557,1562,1567,1572,1577,1582,1586,1591,1614,1636,1657,1684,1688,1693,1698,1703,1707,1712],{"__ignoreMap":28},[33,1431,1432],{"class":35,"line":36},[33,1433,1434],{"class":39},"\u002F\u002F ── Browser runtime model ──\n",[33,1436,1437],{"class":35,"line":43},[33,1438,1439],{"class":39},"\u002F\u002F   ┌──────────────────┐     ┌───────────────────┐\n",[33,1441,1442],{"class":35,"line":49},[33,1443,1444],{"class":39},"\u002F\u002F   │  JS Engine (V8)  │     │  Web APIs (C++)   │\n",[33,1446,1447],{"class":35,"line":55},[33,1448,1449],{"class":39},"\u002F\u002F   │  Call Stack       │     │  DOM, fetch,      │\n",[33,1451,1452],{"class":35,"line":61},[33,1453,1454],{"class":39},"\u002F\u002F   │  Heap (GC)       │     │  setTimeout, XHR  │\n",[33,1456,1457],{"class":35,"line":67},[33,1458,1459],{"class":39},"\u002F\u002F   └────────┬─────────┘     └─────────┬─────────┘\n",[33,1461,1462],{"class":35,"line":73},[33,1463,1464],{"class":39},"\u002F\u002F            │                          │\n",[33,1466,1467],{"class":35,"line":78},[33,1468,1469],{"class":39},"\u002F\u002F            │   ┌──────────────────────┘\n",[33,1471,1472],{"class":35,"line":84},[33,1473,1474],{"class":39},"\u002F\u002F            │   │\n",[33,1476,1477],{"class":35,"line":90},[33,1478,1479],{"class":39},"\u002F\u002F   ┌────────▼───▼────────┐\n",[33,1481,1482],{"class":35,"line":96},[33,1483,1484],{"class":39},"\u002F\u002F   │   Event Loop        │\n",[33,1486,1487],{"class":35,"line":102},[33,1488,1489],{"class":39},"\u002F\u002F   │   (libuv in Node,   │\n",[33,1491,1492],{"class":35,"line":108},[33,1493,1494],{"class":39},"\u002F\u002F    │   browser-native)  │\n",[33,1496,1497],{"class":35,"line":113},[33,1498,1499],{"class":39},"\u002F\u002F   │                     │\n",[33,1501,1502],{"class":35,"line":119},[33,1503,1504],{"class":39},"\u002F\u002F   │   ┌───────────────┐ │\n",[33,1506,1507],{"class":35,"line":125},[33,1508,1509],{"class":39},"\u002F\u002F   │   │ Microtask Q    │ │ ← Promise.then, queueMicrotask, MutationObserver\n",[33,1511,1512],{"class":35,"line":131},[33,1513,1514],{"class":39},"\u002F\u002F   │   │ (drained fully)│ │    (runs AFTER each macrotask, before next)\n",[33,1516,1517],{"class":35,"line":137},[33,1518,1519],{"class":39},"\u002F\u002F   │   └───────────────┘ │\n",[33,1521,1522],{"class":35,"line":144},[33,1523,1504],{"class":39},[33,1525,1526],{"class":35,"line":150},[33,1527,1528],{"class":39},"\u002F\u002F   │   │ Macrotask Q    │ │ ← setTimeout, setInterval, I\u002FO, UI events\n",[33,1530,1531],{"class":35,"line":156},[33,1532,1533],{"class":39},"\u002F\u002F   │   │ (one per tick) │ │    (one macrotask per event loop tick)\n",[33,1535,1536],{"class":35,"line":162},[33,1537,1519],{"class":39},[33,1539,1540],{"class":35,"line":168},[33,1541,1542],{"class":39},"\u002F\u002F   └─────────────────────┘\n",[33,1544,1545],{"class":35,"line":174},[33,1546,141],{"emptyLinePlaceholder":140},[33,1548,1549],{"class":35,"line":180},[33,1550,1551],{"class":39},"\u002F\u002F ── Node.js runtime model ──\n",[33,1553,1554],{"class":35,"line":185},[33,1555,1556],{"class":39},"\u002F\u002F   Same V8 engine, but different host environment:\n",[33,1558,1559],{"class":35,"line":191},[33,1560,1561],{"class":39},"\u002F\u002F   - No DOM, no window, no document\n",[33,1563,1564],{"class":35,"line":215},[33,1565,1566],{"class":39},"\u002F\u002F   - Has: process, Buffer, __dirname, __filename, require()\n",[33,1568,1569],{"class":35,"line":232},[33,1570,1571],{"class":39},"\u002F\u002F   - libuv provides the event loop (cross-platform async I\u002FO)\n",[33,1573,1574],{"class":35,"line":249},[33,1575,1576],{"class":39},"\u002F\u002F   - Timers: setTimeout\u002FsetInterval (from Node, not window)\n",[33,1578,1579],{"class":35,"line":254},[33,1580,1581],{"class":39},"\u002F\u002F   - Microtasks: process.nextTick (Node-specific, higher priority than Promises)\n",[33,1583,1584],{"class":35,"line":279},[33,1585,141],{"emptyLinePlaceholder":140},[33,1587,1588],{"class":35,"line":301},[33,1589,1590],{"class":39},"\u002F\u002F ── Node-specific APIs (not available in browser) ──\n",[33,1592,1593,1595,1598,1600,1603,1605,1608,1611],{"class":35,"line":321},[33,1594,1155],{"class":205},[33,1596,1597],{"class":291}," fs",[33,1599,686],{"class":205},[33,1601,1602],{"class":198}," require",[33,1604,202],{"class":194},[33,1606,1607],{"class":269},"'fs'",[33,1609,1610],{"class":194},");          ",[33,1612,1613],{"class":39},"\u002F\u002F file system\n",[33,1615,1616,1618,1621,1623,1625,1627,1630,1633],{"class":35,"line":326},[33,1617,1155],{"class":205},[33,1619,1620],{"class":291}," http",[33,1622,686],{"class":205},[33,1624,1602],{"class":198},[33,1626,202],{"class":194},[33,1628,1629],{"class":269},"'http'",[33,1631,1632],{"class":194},");      ",[33,1634,1635],{"class":39},"\u002F\u002F HTTP server\u002Fclient\n",[33,1637,1638,1640,1643,1645,1647,1649,1652,1654],{"class":35,"line":332},[33,1639,1155],{"class":205},[33,1641,1642],{"class":291}," path",[33,1644,686],{"class":205},[33,1646,1602],{"class":198},[33,1648,202],{"class":194},[33,1650,1651],{"class":269},"'path'",[33,1653,1632],{"class":194},[33,1655,1656],{"class":39},"\u002F\u002F path manipulation\n",[33,1658,1659,1661,1664,1667,1670,1672,1674,1676,1679,1681],{"class":35,"line":361},[33,1660,1155],{"class":205},[33,1662,1663],{"class":194}," { ",[33,1665,1666],{"class":291},"Worker",[33,1668,1669],{"class":194}," } ",[33,1671,288],{"class":205},[33,1673,1602],{"class":198},[33,1675,202],{"class":194},[33,1677,1678],{"class":269},"'worker_threads'",[33,1680,510],{"class":194},[33,1682,1683],{"class":39},"\u002F\u002F true parallelism\n",[33,1685,1686],{"class":35,"line":388},[33,1687,141],{"emptyLinePlaceholder":140},[33,1689,1690],{"class":35,"line":412},[33,1691,1692],{"class":39},"\u002F\u002F ── Browser-specific APIs (not available in Node) ──\n",[33,1694,1695],{"class":35,"line":417},[33,1696,1697],{"class":39},"\u002F\u002F window, document, localStorage, fetch (Node 18+ has fetch)\n",[33,1699,1700],{"class":35,"line":426},[33,1701,1702],{"class":39},"\u002F\u002F DOM manipulation, CSS, Canvas, Web Audio, etc.\n",[33,1704,1705],{"class":35,"line":432},[33,1706,141],{"emptyLinePlaceholder":140},[33,1708,1709],{"class":35,"line":438},[33,1710,1711],{"class":39},"\u002F\u002F ── Shared: the language is the same, the platform APIs differ ──\n",[33,1713,1714],{"class":35,"line":444},[33,1715,1716],{"class":39},"\u002F\u002F Pure JS (Array methods, Promises, closures, classes) works identically in both.\n",[15,1718,1720],{"id":1719},"the-event-loop-microtasks-vs-macrotasks","The Event Loop: Microtasks vs Macrotasks",[20,1722,1723],{"language":22},[24,1724,1726],{"className":26,"code":1725,"language":22,"meta":28,"style":28},"\u002F\u002F ── Event loop tick (one iteration) ──\n\u002F\u002F 1. Execute one macrotask (setTimeout callback, I\u002FO callback, event handler)\n\u002F\u002F 2. Drain the microtask queue (ALL microtasks: Promise.then, queueMicrotask)\n\u002F\u002F    - Microtasks run to completion before the next macrotask\n\u002F\u002F    - New microtasks added during step 2 also run in the same drain\n\u002F\u002F 3. Render (browser only: requestAnimationFrame callbacks, layout, paint)\n\u002F\u002F 4. Repeat\n\nconsole.log(\"1: sync\");\n\nsetTimeout(() => console.log(\"4: macrotask\"), 0);\n\nPromise.resolve().then(() => console.log(\"3: microtask\"));\n\nconsole.log(\"2: sync\");\n\n\u002F\u002F Output: 1, 2, 3, 4\n\u002F\u002F 1: synchronous code runs first (script is itself a macrotask)\n\u002F\u002F 2: continues synchronously\n\u002F\u002F 3: microtask runs after current script (drained before next macrotask)\n\u002F\u002F 4: macrotask (setTimeout) runs after all microtasks are drained\n\n\u002F\u002F ── Microtask starvation: microtasks can block macrotasks ──\n\u002F\u002F If a microtask keeps adding more microtasks, macrotasks NEVER run:\n\u002F\u002F (Don't run this — it blocks forever)\n\u002F\u002F function infiniteMicrotasks() {\n\u002F\u002F     Promise.resolve().then(infiniteMicrotasks);\n\u002F\u002F }\n\u002F\u002F infiniteMicrotasks();  \u002F\u002F setTimeout callbacks never run — microtask queue never empties\n\n\u002F\u002F ── Node.js: process.nextTick vs Promise.then ──\n\u002F\u002F process.nextTick has HIGHER priority than Promise microtasks:\n\u002F\u002F Node only:\n\u002F\u002F process.nextTick(() => console.log(\"nextTick\"));\n\u002F\u002F Promise.resolve().then(() => console.log(\"promise\"));\n\u002F\u002F console.log(\"sync\");\n\u002F\u002F Output: sync, nextTick, promise (nextTick drains before Promise microtasks)\n",[30,1727,1728,1733,1738,1743,1748,1753,1758,1763,1767,1780,1784,1812,1816,1848,1852,1865,1869,1874,1879,1884,1889,1894,1898,1903,1908,1913,1918,1923,1928,1936,1940,1945,1950,1955,1960,1965,1970],{"__ignoreMap":28},[33,1729,1730],{"class":35,"line":36},[33,1731,1732],{"class":39},"\u002F\u002F ── Event loop tick (one iteration) ──\n",[33,1734,1735],{"class":35,"line":43},[33,1736,1737],{"class":39},"\u002F\u002F 1. Execute one macrotask (setTimeout callback, I\u002FO callback, event handler)\n",[33,1739,1740],{"class":35,"line":49},[33,1741,1742],{"class":39},"\u002F\u002F 2. Drain the microtask queue (ALL microtasks: Promise.then, queueMicrotask)\n",[33,1744,1745],{"class":35,"line":55},[33,1746,1747],{"class":39},"\u002F\u002F    - Microtasks run to completion before the next macrotask\n",[33,1749,1750],{"class":35,"line":61},[33,1751,1752],{"class":39},"\u002F\u002F    - New microtasks added during step 2 also run in the same drain\n",[33,1754,1755],{"class":35,"line":67},[33,1756,1757],{"class":39},"\u002F\u002F 3. Render (browser only: requestAnimationFrame callbacks, layout, paint)\n",[33,1759,1760],{"class":35,"line":73},[33,1761,1762],{"class":39},"\u002F\u002F 4. Repeat\n",[33,1764,1765],{"class":35,"line":78},[33,1766,141],{"emptyLinePlaceholder":140},[33,1768,1769,1771,1773,1775,1778],{"class":35,"line":84},[33,1770,195],{"class":194},[33,1772,199],{"class":198},[33,1774,202],{"class":194},[33,1776,1777],{"class":269},"\"1: sync\"",[33,1779,636],{"class":194},[33,1781,1782],{"class":35,"line":90},[33,1783,141],{"emptyLinePlaceholder":140},[33,1785,1786,1789,1792,1795,1798,1800,1802,1805,1808,1810],{"class":35,"line":96},[33,1787,1788],{"class":198},"setTimeout",[33,1790,1791],{"class":194},"(() ",[33,1793,1794],{"class":205},"=>",[33,1796,1797],{"class":194}," console.",[33,1799,199],{"class":198},[33,1801,202],{"class":194},[33,1803,1804],{"class":269},"\"4: macrotask\"",[33,1806,1807],{"class":194},"), ",[33,1809,849],{"class":291},[33,1811,636],{"class":194},[33,1813,1814],{"class":35,"line":102},[33,1815,141],{"emptyLinePlaceholder":140},[33,1817,1818,1821,1824,1826,1829,1832,1834,1836,1838,1840,1842,1845],{"class":35,"line":108},[33,1819,1820],{"class":291},"Promise",[33,1822,1823],{"class":194},".",[33,1825,706],{"class":198},[33,1827,1828],{"class":194},"().",[33,1830,1831],{"class":198},"then",[33,1833,1791],{"class":194},[33,1835,1794],{"class":205},[33,1837,1797],{"class":194},[33,1839,199],{"class":198},[33,1841,202],{"class":194},[33,1843,1844],{"class":269},"\"3: microtask\"",[33,1846,1847],{"class":194},"));\n",[33,1849,1850],{"class":35,"line":113},[33,1851,141],{"emptyLinePlaceholder":140},[33,1853,1854,1856,1858,1860,1863],{"class":35,"line":119},[33,1855,195],{"class":194},[33,1857,199],{"class":198},[33,1859,202],{"class":194},[33,1861,1862],{"class":269},"\"2: sync\"",[33,1864,636],{"class":194},[33,1866,1867],{"class":35,"line":125},[33,1868,141],{"emptyLinePlaceholder":140},[33,1870,1871],{"class":35,"line":131},[33,1872,1873],{"class":39},"\u002F\u002F Output: 1, 2, 3, 4\n",[33,1875,1876],{"class":35,"line":137},[33,1877,1878],{"class":39},"\u002F\u002F 1: synchronous code runs first (script is itself a macrotask)\n",[33,1880,1881],{"class":35,"line":144},[33,1882,1883],{"class":39},"\u002F\u002F 2: continues synchronously\n",[33,1885,1886],{"class":35,"line":150},[33,1887,1888],{"class":39},"\u002F\u002F 3: microtask runs after current script (drained before next macrotask)\n",[33,1890,1891],{"class":35,"line":156},[33,1892,1893],{"class":39},"\u002F\u002F 4: macrotask (setTimeout) runs after all microtasks are drained\n",[33,1895,1896],{"class":35,"line":162},[33,1897,141],{"emptyLinePlaceholder":140},[33,1899,1900],{"class":35,"line":168},[33,1901,1902],{"class":39},"\u002F\u002F ── Microtask starvation: microtasks can block macrotasks ──\n",[33,1904,1905],{"class":35,"line":174},[33,1906,1907],{"class":39},"\u002F\u002F If a microtask keeps adding more microtasks, macrotasks NEVER run:\n",[33,1909,1910],{"class":35,"line":180},[33,1911,1912],{"class":39},"\u002F\u002F (Don't run this — it blocks forever)\n",[33,1914,1915],{"class":35,"line":185},[33,1916,1917],{"class":39},"\u002F\u002F function infiniteMicrotasks() {\n",[33,1919,1920],{"class":35,"line":191},[33,1921,1922],{"class":39},"\u002F\u002F     Promise.resolve().then(infiniteMicrotasks);\n",[33,1924,1925],{"class":35,"line":215},[33,1926,1927],{"class":39},"\u002F\u002F }\n",[33,1929,1930,1933],{"class":35,"line":232},[33,1931,1932],{"class":39},"\u002F\u002F infiniteMicrotasks();",[33,1934,1935],{"class":39},"  \u002F\u002F setTimeout callbacks never run — microtask queue never empties\n",[33,1937,1938],{"class":35,"line":249},[33,1939,141],{"emptyLinePlaceholder":140},[33,1941,1942],{"class":35,"line":254},[33,1943,1944],{"class":39},"\u002F\u002F ── Node.js: process.nextTick vs Promise.then ──\n",[33,1946,1947],{"class":35,"line":279},[33,1948,1949],{"class":39},"\u002F\u002F process.nextTick has HIGHER priority than Promise microtasks:\n",[33,1951,1952],{"class":35,"line":301},[33,1953,1954],{"class":39},"\u002F\u002F Node only:\n",[33,1956,1957],{"class":35,"line":321},[33,1958,1959],{"class":39},"\u002F\u002F process.nextTick(() => console.log(\"nextTick\"));\n",[33,1961,1962],{"class":35,"line":326},[33,1963,1964],{"class":39},"\u002F\u002F Promise.resolve().then(() => console.log(\"promise\"));\n",[33,1966,1967],{"class":35,"line":332},[33,1968,1969],{"class":39},"\u002F\u002F console.log(\"sync\");\n",[33,1971,1972],{"class":35,"line":361},[33,1973,1974],{"class":39},"\u002F\u002F Output: sync, nextTick, promise (nextTick drains before Promise microtasks)\n",[15,1976,1978],{"id":1977},"memory-model-stack-vs-heap","Memory Model: Stack vs Heap",[20,1980,1981],{"language":22},[24,1982,1984],{"className":26,"code":1983,"language":22,"meta":28,"style":28},"\u002F\u002F ── Stack: primitive values, function frames, references ──\n\u002F\u002F ── Heap: objects, arrays, functions, closures (reference types) ──\n\nlet a = 42;        \u002F\u002F 42 stored on the stack (primitive)\nlet b = a;         \u002F\u002F copy: b gets its own 42 on the stack (pass by value)\na = 99;            \u002F\u002F a is 99, b is still 42 (independent copies)\n\nconst obj1 = { x: 1 };  \u002F\u002F {x:1} allocated on the heap; obj1 is a reference on the stack\nconst obj2 = obj1;       \u002F\u002F obj2 copies the REFERENCE (points to same heap object)\nobj1.x = 99;            \u002F\u002F mutates the shared heap object\nconsole.log(obj2.x);     \u002F\u002F 99 — obj2 sees the change (same object)\n\n\u002F\u002F ── Garbage collection (GC) ──\n\u002F\u002F V8 uses a generational mark-and-sweep GC:\n\u002F\u002F   - Young generation (nursery): new objects, short-lived. Scavenged (copied) frequently.\n\u002F\u002F   - Old generation: survived objects, long-lived. Mark-and-swept less frequently.\n\u002F\u002F An object is collected when no references to it remain on the stack or in other heap objects.\n\nfunction createLeak() {\n    const huge = new Array(1_000_000).fill(\"*\");  \u002F\u002F allocated on heap\n    \u002F\u002F If `huge` is captured by a closure or stored globally, it can't be GC'd.\n    return () => huge.length;  \u002F\u002F closure captures `huge` — keeps it alive\n}\nconst leak = createLeak();  \u002F\u002F huge array stays alive as long as `leak` exists\nleak = null;  \u002F\u002F NOW the huge array can be GC'd (no more references)\n\n\u002F\u002F ── WeakRef: hold a reference without preventing GC ──\nconst target = { data: \"important\" };\nconst weakRef = new WeakRef(target);\n\u002F\u002F weakRef.deref() returns the object if still alive, or undefined if GC'd\nconsole.log(weakRef.deref());  \u002F\u002F { data: \"important\" } or undefined if GC'd\n\u002F\u002F Use case: caches that shouldn't prevent garbage collection\n",[30,1985,1986,1991,1996,2000,2017,2032,2048,2052,2072,2087,2101,2113,2117,2122,2127,2132,2137,2142,2146,2155,2191,2196,2216,2220,2237,2252,2256,2261,2279,2296,2301,2319],{"__ignoreMap":28},[33,1987,1988],{"class":35,"line":36},[33,1989,1990],{"class":39},"\u002F\u002F ── Stack: primitive values, function frames, references ──\n",[33,1992,1993],{"class":35,"line":43},[33,1994,1995],{"class":39},"\u002F\u002F ── Heap: objects, arrays, functions, closures (reference types) ──\n",[33,1997,1998],{"class":35,"line":49},[33,1999,141],{"emptyLinePlaceholder":140},[33,2001,2002,2004,2006,2008,2011,2014],{"class":35,"line":55},[33,2003,304],{"class":205},[33,2005,720],{"class":194},[33,2007,288],{"class":205},[33,2009,2010],{"class":291}," 42",[33,2012,2013],{"class":194},";        ",[33,2015,2016],{"class":39},"\u002F\u002F 42 stored on the stack (primitive)\n",[33,2018,2019,2021,2024,2026,2029],{"class":35,"line":61},[33,2020,304],{"class":205},[33,2022,2023],{"class":194}," b ",[33,2025,288],{"class":205},[33,2027,2028],{"class":194}," a;         ",[33,2030,2031],{"class":39},"\u002F\u002F copy: b gets its own 42 on the stack (pass by value)\n",[33,2033,2034,2037,2039,2042,2045],{"class":35,"line":67},[33,2035,2036],{"class":194},"a ",[33,2038,288],{"class":205},[33,2040,2041],{"class":291}," 99",[33,2043,2044],{"class":194},";            ",[33,2046,2047],{"class":39},"\u002F\u002F a is 99, b is still 42 (independent copies)\n",[33,2049,2050],{"class":35,"line":73},[33,2051,141],{"emptyLinePlaceholder":140},[33,2053,2054,2056,2059,2061,2064,2066,2069],{"class":35,"line":78},[33,2055,1155],{"class":205},[33,2057,2058],{"class":291}," obj1",[33,2060,686],{"class":205},[33,2062,2063],{"class":194}," { x: ",[33,2065,1006],{"class":291},[33,2067,2068],{"class":194}," };  ",[33,2070,2071],{"class":39},"\u002F\u002F {x:1} allocated on the heap; obj1 is a reference on the stack\n",[33,2073,2074,2076,2079,2081,2084],{"class":35,"line":84},[33,2075,1155],{"class":205},[33,2077,2078],{"class":291}," obj2",[33,2080,686],{"class":205},[33,2082,2083],{"class":194}," obj1;       ",[33,2085,2086],{"class":39},"\u002F\u002F obj2 copies the REFERENCE (points to same heap object)\n",[33,2088,2089,2092,2094,2096,2098],{"class":35,"line":90},[33,2090,2091],{"class":194},"obj1.x ",[33,2093,288],{"class":205},[33,2095,2041],{"class":291},[33,2097,2044],{"class":194},[33,2099,2100],{"class":39},"\u002F\u002F mutates the shared heap object\n",[33,2102,2103,2105,2107,2110],{"class":35,"line":96},[33,2104,195],{"class":194},[33,2106,199],{"class":198},[33,2108,2109],{"class":194},"(obj2.x);     ",[33,2111,2112],{"class":39},"\u002F\u002F 99 — obj2 sees the change (same object)\n",[33,2114,2115],{"class":35,"line":102},[33,2116,141],{"emptyLinePlaceholder":140},[33,2118,2119],{"class":35,"line":108},[33,2120,2121],{"class":39},"\u002F\u002F ── Garbage collection (GC) ──\n",[33,2123,2124],{"class":35,"line":113},[33,2125,2126],{"class":39},"\u002F\u002F V8 uses a generational mark-and-sweep GC:\n",[33,2128,2129],{"class":35,"line":119},[33,2130,2131],{"class":39},"\u002F\u002F   - Young generation (nursery): new objects, short-lived. Scavenged (copied) frequently.\n",[33,2133,2134],{"class":35,"line":125},[33,2135,2136],{"class":39},"\u002F\u002F   - Old generation: survived objects, long-lived. Mark-and-swept less frequently.\n",[33,2138,2139],{"class":35,"line":131},[33,2140,2141],{"class":39},"\u002F\u002F An object is collected when no references to it remain on the stack or in other heap objects.\n",[33,2143,2144],{"class":35,"line":137},[33,2145,141],{"emptyLinePlaceholder":140},[33,2147,2148,2150,2153],{"class":35,"line":144},[33,2149,257],{"class":205},[33,2151,2152],{"class":198}," createLeak",[33,2154,759],{"class":194},[33,2156,2157,2160,2163,2165,2167,2170,2172,2175,2178,2181,2183,2186,2188],{"class":35,"line":150},[33,2158,2159],{"class":205},"    const",[33,2161,2162],{"class":291}," huge",[33,2164,686],{"class":205},[33,2166,698],{"class":205},[33,2168,2169],{"class":198}," Array",[33,2171,202],{"class":194},[33,2173,2174],{"class":291},"1_000_000",[33,2176,2177],{"class":194},").",[33,2179,2180],{"class":198},"fill",[33,2182,202],{"class":194},[33,2184,2185],{"class":269},"\"*\"",[33,2187,510],{"class":194},[33,2189,2190],{"class":39},"\u002F\u002F allocated on heap\n",[33,2192,2193],{"class":35,"line":156},[33,2194,2195],{"class":39},"    \u002F\u002F If `huge` is captured by a closure or stored globally, it can't be GC'd.\n",[33,2197,2198,2200,2203,2205,2208,2211,2213],{"class":35,"line":162},[33,2199,595],{"class":205},[33,2201,2202],{"class":194}," () ",[33,2204,1794],{"class":205},[33,2206,2207],{"class":194}," huge.",[33,2209,2210],{"class":291},"length",[33,2212,1334],{"class":194},[33,2214,2215],{"class":39},"\u002F\u002F closure captures `huge` — keeps it alive\n",[33,2217,2218],{"class":35,"line":168},[33,2219,519],{"class":194},[33,2221,2222,2224,2227,2229,2231,2234],{"class":35,"line":174},[33,2223,1155],{"class":205},[33,2225,2226],{"class":291}," leak",[33,2228,686],{"class":205},[33,2230,2152],{"class":198},[33,2232,2233],{"class":194},"();  ",[33,2235,2236],{"class":39},"\u002F\u002F huge array stays alive as long as `leak` exists\n",[33,2238,2239,2242,2244,2247,2249],{"class":35,"line":180},[33,2240,2241],{"class":194},"leak ",[33,2243,288],{"class":205},[33,2245,2246],{"class":291}," null",[33,2248,1334],{"class":194},[33,2250,2251],{"class":39},"\u002F\u002F NOW the huge array can be GC'd (no more references)\n",[33,2253,2254],{"class":35,"line":185},[33,2255,141],{"emptyLinePlaceholder":140},[33,2257,2258],{"class":35,"line":191},[33,2259,2260],{"class":39},"\u002F\u002F ── WeakRef: hold a reference without preventing GC ──\n",[33,2262,2263,2265,2268,2270,2273,2276],{"class":35,"line":215},[33,2264,1155],{"class":205},[33,2266,2267],{"class":291}," target",[33,2269,686],{"class":205},[33,2271,2272],{"class":194}," { data: ",[33,2274,2275],{"class":269},"\"important\"",[33,2277,2278],{"class":194}," };\n",[33,2280,2281,2283,2286,2288,2290,2293],{"class":35,"line":232},[33,2282,1155],{"class":205},[33,2284,2285],{"class":291}," weakRef",[33,2287,686],{"class":205},[33,2289,698],{"class":205},[33,2291,2292],{"class":198}," WeakRef",[33,2294,2295],{"class":194},"(target);\n",[33,2297,2298],{"class":35,"line":249},[33,2299,2300],{"class":39},"\u002F\u002F weakRef.deref() returns the object if still alive, or undefined if GC'd\n",[33,2302,2303,2305,2307,2310,2313,2316],{"class":35,"line":254},[33,2304,195],{"class":194},[33,2306,199],{"class":198},[33,2308,2309],{"class":194},"(weakRef.",[33,2311,2312],{"class":198},"deref",[33,2314,2315],{"class":194},"());  ",[33,2317,2318],{"class":39},"\u002F\u002F { data: \"important\" } or undefined if GC'd\n",[33,2320,2321],{"class":35,"line":279},[33,2322,2323],{"class":39},"\u002F\u002F Use case: caches that shouldn't prevent garbage collection\n",[15,2325,2327],{"id":2326},"tips-tricks","💡 Tips & Tricks",[20,2329,2330],{"language":22},[24,2331,2333],{"className":26,"code":2332,"language":22,"meta":28,"style":28},"\u002F\u002F ── Check your runtime (browser vs Node) ──\nconst isNode = typeof process !== \"undefined\" && process.versions?.node;\nconst isBrowser = typeof window !== \"undefined\";\nconst isWorker = typeof self !== \"undefined\" && typeof window === \"undefined\";\n\n\u002F\u002F ── Feature-detect without UA sniffing ──\nconst supportsWeakRef = typeof WeakRef !== \"undefined\";\nconst supportsTopLevelAwait = true;  \u002F\u002F ES2022+ — check by trying\n\n\u002F\u002F ── Use scheduler.yield() (Chrome 129+) to yield without setTimeout ──\n\u002F\u002F Modern alternative to setTimeout(fn, 0) for yielding:\nasync function yieldToEventLoop() {\n    if (typeof scheduler !== \"undefined\" && scheduler.yield) {\n        await scheduler.yield();  \u002F\u002F higher-priority than setTimeout\n    } else {\n        await new Promise(r => setTimeout(r, 0));  \u002F\u002F fallback\n    }\n}\n\n\u002F\u002F ── Measure engine performance with performance.now() ──\nconst start = performance.now();\n\u002F\u002F ... code to measure ...\nconst elapsed = performance.now() - start;  \u002F\u002F milliseconds with sub-ms precision\n\u002F\u002F performance.now() is monotonic (never goes backwards) and high-resolution.\n\n\u002F\u002F ── Detect JIT deoptimization (V8) with %GetOptimizationStatus ──\n\u002F\u002F Requires: node --allow-natives-syntax\n\u002F\u002F function hot() { return 1 + 2; }\n\u002F\u002F hot(); hot(); hot();  \u002F\u002F warm up\n\u002F\u002F print(%GetOptimizationStatus(hot));  \u002F\u002F 1 = optimized, 0 = not optimized\n\u002F\u002F (Debug-only — don't use in production)\n",[30,2334,2335,2340,2367,2387,2417,2421,2426,2446,2463,2467,2472,2477,2488,2509,2525,2534,2563,2568,2572,2576,2581,2598,2603,2627,2632,2636,2641,2646,2651,2659,2667],{"__ignoreMap":28},[33,2336,2337],{"class":35,"line":36},[33,2338,2339],{"class":39},"\u002F\u002F ── Check your runtime (browser vs Node) ──\n",[33,2341,2342,2344,2347,2349,2352,2355,2358,2361,2364],{"class":35,"line":43},[33,2343,1155],{"class":205},[33,2345,2346],{"class":291}," isNode",[33,2348,686],{"class":205},[33,2350,2351],{"class":205}," typeof",[33,2353,2354],{"class":194}," process ",[33,2356,2357],{"class":205},"!==",[33,2359,2360],{"class":269}," \"undefined\"",[33,2362,2363],{"class":205}," &&",[33,2365,2366],{"class":194}," process.versions?.node;\n",[33,2368,2369,2371,2374,2376,2378,2381,2383,2385],{"class":35,"line":49},[33,2370,1155],{"class":205},[33,2372,2373],{"class":291}," isBrowser",[33,2375,686],{"class":205},[33,2377,2351],{"class":205},[33,2379,2380],{"class":194}," window ",[33,2382,2357],{"class":205},[33,2384,2360],{"class":269},[33,2386,492],{"class":194},[33,2388,2389,2391,2394,2396,2398,2401,2403,2405,2407,2409,2411,2413,2415],{"class":35,"line":55},[33,2390,1155],{"class":205},[33,2392,2393],{"class":291}," isWorker",[33,2395,686],{"class":205},[33,2397,2351],{"class":205},[33,2399,2400],{"class":194}," self ",[33,2402,2357],{"class":205},[33,2404,2360],{"class":269},[33,2406,2363],{"class":205},[33,2408,2351],{"class":205},[33,2410,2380],{"class":194},[33,2412,481],{"class":205},[33,2414,2360],{"class":269},[33,2416,492],{"class":194},[33,2418,2419],{"class":35,"line":61},[33,2420,141],{"emptyLinePlaceholder":140},[33,2422,2423],{"class":35,"line":67},[33,2424,2425],{"class":39},"\u002F\u002F ── Feature-detect without UA sniffing ──\n",[33,2427,2428,2430,2433,2435,2437,2440,2442,2444],{"class":35,"line":73},[33,2429,1155],{"class":205},[33,2431,2432],{"class":291}," supportsWeakRef",[33,2434,686],{"class":205},[33,2436,2351],{"class":205},[33,2438,2439],{"class":194}," WeakRef ",[33,2441,2357],{"class":205},[33,2443,2360],{"class":269},[33,2445,492],{"class":194},[33,2447,2448,2450,2453,2455,2458,2460],{"class":35,"line":78},[33,2449,1155],{"class":205},[33,2451,2452],{"class":291}," supportsTopLevelAwait",[33,2454,686],{"class":205},[33,2456,2457],{"class":291}," true",[33,2459,1334],{"class":194},[33,2461,2462],{"class":39},"\u002F\u002F ES2022+ — check by trying\n",[33,2464,2465],{"class":35,"line":84},[33,2466,141],{"emptyLinePlaceholder":140},[33,2468,2469],{"class":35,"line":90},[33,2470,2471],{"class":39},"\u002F\u002F ── Use scheduler.yield() (Chrome 129+) to yield without setTimeout ──\n",[33,2473,2474],{"class":35,"line":96},[33,2475,2476],{"class":39},"\u002F\u002F Modern alternative to setTimeout(fn, 0) for yielding:\n",[33,2478,2479,2481,2483,2486],{"class":35,"line":102},[33,2480,667],{"class":205},[33,2482,670],{"class":205},[33,2484,2485],{"class":198}," yieldToEventLoop",[33,2487,759],{"class":194},[33,2489,2490,2492,2495,2497,2500,2502,2504,2506],{"class":35,"line":108},[33,2491,475],{"class":205},[33,2493,2494],{"class":194}," (",[33,2496,206],{"class":205},[33,2498,2499],{"class":194}," scheduler ",[33,2501,2357],{"class":205},[33,2503,2360],{"class":269},[33,2505,2363],{"class":205},[33,2507,2508],{"class":194}," scheduler.yield) {\n",[33,2510,2511,2514,2517,2520,2522],{"class":35,"line":113},[33,2512,2513],{"class":205},"        await",[33,2515,2516],{"class":194}," scheduler.",[33,2518,2519],{"class":198},"yield",[33,2521,2233],{"class":194},[33,2523,2524],{"class":39},"\u002F\u002F higher-priority than setTimeout\n",[33,2526,2527,2530,2532],{"class":35,"line":119},[33,2528,2529],{"class":194},"    } ",[33,2531,862],{"class":205},[33,2533,712],{"class":194},[33,2535,2536,2538,2540,2542,2544,2547,2549,2552,2555,2557,2560],{"class":35,"line":125},[33,2537,2513],{"class":205},[33,2539,698],{"class":205},[33,2541,701],{"class":291},[33,2543,202],{"class":194},[33,2545,2546],{"class":465},"r",[33,2548,709],{"class":205},[33,2550,2551],{"class":198}," setTimeout",[33,2553,2554],{"class":194},"(r, ",[33,2556,849],{"class":291},[33,2558,2559],{"class":194},"));  ",[33,2561,2562],{"class":39},"\u002F\u002F fallback\n",[33,2564,2565],{"class":35,"line":131},[33,2566,2567],{"class":194},"    }\n",[33,2569,2570],{"class":35,"line":137},[33,2571,519],{"class":194},[33,2573,2574],{"class":35,"line":144},[33,2575,141],{"emptyLinePlaceholder":140},[33,2577,2578],{"class":35,"line":150},[33,2579,2580],{"class":39},"\u002F\u002F ── Measure engine performance with performance.now() ──\n",[33,2582,2583,2585,2588,2590,2593,2596],{"class":35,"line":156},[33,2584,1155],{"class":205},[33,2586,2587],{"class":291}," start",[33,2589,686],{"class":205},[33,2591,2592],{"class":194}," performance.",[33,2594,2595],{"class":198},"now",[33,2597,423],{"class":194},[33,2599,2600],{"class":35,"line":162},[33,2601,2602],{"class":39},"\u002F\u002F ... code to measure ...\n",[33,2604,2605,2607,2610,2612,2614,2616,2619,2621,2624],{"class":35,"line":168},[33,2606,1155],{"class":205},[33,2608,2609],{"class":291}," elapsed",[33,2611,686],{"class":205},[33,2613,2592],{"class":194},[33,2615,2595],{"class":198},[33,2617,2618],{"class":194},"() ",[33,2620,504],{"class":205},[33,2622,2623],{"class":194}," start;  ",[33,2625,2626],{"class":39},"\u002F\u002F milliseconds with sub-ms precision\n",[33,2628,2629],{"class":35,"line":174},[33,2630,2631],{"class":39},"\u002F\u002F performance.now() is monotonic (never goes backwards) and high-resolution.\n",[33,2633,2634],{"class":35,"line":180},[33,2635,141],{"emptyLinePlaceholder":140},[33,2637,2638],{"class":35,"line":185},[33,2639,2640],{"class":39},"\u002F\u002F ── Detect JIT deoptimization (V8) with %GetOptimizationStatus ──\n",[33,2642,2643],{"class":35,"line":191},[33,2644,2645],{"class":39},"\u002F\u002F Requires: node --allow-natives-syntax\n",[33,2647,2648],{"class":35,"line":215},[33,2649,2650],{"class":39},"\u002F\u002F function hot() { return 1 + 2; }\n",[33,2652,2653,2656],{"class":35,"line":232},[33,2654,2655],{"class":39},"\u002F\u002F hot(); hot(); hot();",[33,2657,2658],{"class":39},"  \u002F\u002F warm up\n",[33,2660,2661,2664],{"class":35,"line":249},[33,2662,2663],{"class":39},"\u002F\u002F print(%GetOptimizationStatus(hot));",[33,2665,2666],{"class":39},"  \u002F\u002F 1 = optimized, 0 = not optimized\n",[33,2668,2669],{"class":35,"line":254},[33,2670,2671],{"class":39},"\u002F\u002F (Debug-only — don't use in production)\n",[15,2673,2675],{"id":2674},"️-edge-cases-gotchas","⚠️ Edge Cases & Gotchas",[20,2677,2678],{"language":22},[24,2679,2681],{"className":26,"code":2680,"language":22,"meta":28,"style":28},"\u002F\u002F ── `instanceof` breaks across realms (iframes, Node worker_threads) ──\n\u002F\u002F Each realm has its own copy of built-in constructors.\n\u002F\u002F Node:\nconst { Worker } = require(\"worker_threads\");\n\u002F\u002F An array created in a Worker is NOT instanceof Array in the main thread:\n\u002F\u002F const w = new Worker('module.exports = new Array()');\n\u002F\u002F w.on('message', arr => console.log(arr instanceof Array));  \u002F\u002F false!\n\u002F\u002F (Each realm has its own Array constructor → different prototypes)\n\u002F\u002F Use Array.isArray(arr) instead — works across realms.\n\n\u002F\u002F ── `typeof null === \"object\"` is a legendary bug (not fixable — would break the web) ──\n\u002F\u002F In the original JS implementation, type tags used 3 bits:\n\u002F\u002F   000: object, 001: integer, 010: double, 100: string, 110: boolean\n\u002F\u002F null was represented as the NULL pointer (0x00), which looked like type tag 000 (object).\nconsole.log(typeof null);        \u002F\u002F \"object\" (bug, since 1995)\nconsole.log(null instanceof Object);  \u002F\u002F false (null is NOT an Object instance)\n\u002F\u002F Correct null check: val === null (strict equality)\n\n\u002F\u002F ── `[]` and `{}` are truthy (unlike Python where they're falsy) ──\nif ([]) console.log(\"empty array is truthy\");    \u002F\u002F prints!\nif ({}) console.log(\"empty object is truthy\");   \u002F\u002F prints!\nif (0) console.log(\"0 is falsy\");                 \u002F\u002F does NOT print\n\u002F\u002F Only 6 falsy values: false, 0, -0, 0n, \"\", null, undefined, NaN\n\u002F\u002F (Empty array\u002Fobject are NOT in the falsy list)\n\n\u002F\u002F ── `NaN` is the only value not equal to itself ──\nconsole.log(NaN === NaN);  \u002F\u002F false\nconsole.log(Number.isNaN(NaN));  \u002F\u002F true (correct way)\nconsole.log(Object.is(NaN, NaN));  \u002F\u002F true (Object.is handles NaN and -0)\n",[30,2682,2683,2688,2693,2698,2719,2724,2729,2737,2742,2747,2751,2756,2761,2766,2771,2789,2811,2816,2820,2825,2846,2864,2888,2893,2898,2902,2907,2929,2950],{"__ignoreMap":28},[33,2684,2685],{"class":35,"line":36},[33,2686,2687],{"class":39},"\u002F\u002F ── `instanceof` breaks across realms (iframes, Node worker_threads) ──\n",[33,2689,2690],{"class":35,"line":43},[33,2691,2692],{"class":39},"\u002F\u002F Each realm has its own copy of built-in constructors.\n",[33,2694,2695],{"class":35,"line":49},[33,2696,2697],{"class":39},"\u002F\u002F Node:\n",[33,2699,2700,2702,2704,2706,2708,2710,2712,2714,2717],{"class":35,"line":55},[33,2701,1155],{"class":205},[33,2703,1663],{"class":194},[33,2705,1666],{"class":291},[33,2707,1669],{"class":194},[33,2709,288],{"class":205},[33,2711,1602],{"class":198},[33,2713,202],{"class":194},[33,2715,2716],{"class":269},"\"worker_threads\"",[33,2718,636],{"class":194},[33,2720,2721],{"class":35,"line":61},[33,2722,2723],{"class":39},"\u002F\u002F An array created in a Worker is NOT instanceof Array in the main thread:\n",[33,2725,2726],{"class":35,"line":67},[33,2727,2728],{"class":39},"\u002F\u002F const w = new Worker('module.exports = new Array()');\n",[33,2730,2731,2734],{"class":35,"line":73},[33,2732,2733],{"class":39},"\u002F\u002F w.on('message', arr => console.log(arr instanceof Array));",[33,2735,2736],{"class":39},"  \u002F\u002F false!\n",[33,2738,2739],{"class":35,"line":78},[33,2740,2741],{"class":39},"\u002F\u002F (Each realm has its own Array constructor → different prototypes)\n",[33,2743,2744],{"class":35,"line":84},[33,2745,2746],{"class":39},"\u002F\u002F Use Array.isArray(arr) instead — works across realms.\n",[33,2748,2749],{"class":35,"line":90},[33,2750,141],{"emptyLinePlaceholder":140},[33,2752,2753],{"class":35,"line":96},[33,2754,2755],{"class":39},"\u002F\u002F ── `typeof null === \"object\"` is a legendary bug (not fixable — would break the web) ──\n",[33,2757,2758],{"class":35,"line":102},[33,2759,2760],{"class":39},"\u002F\u002F In the original JS implementation, type tags used 3 bits:\n",[33,2762,2763],{"class":35,"line":108},[33,2764,2765],{"class":39},"\u002F\u002F   000: object, 001: integer, 010: double, 100: string, 110: boolean\n",[33,2767,2768],{"class":35,"line":113},[33,2769,2770],{"class":39},"\u002F\u002F null was represented as the NULL pointer (0x00), which looked like type tag 000 (object).\n",[33,2772,2773,2775,2777,2779,2781,2783,2786],{"class":35,"line":119},[33,2774,195],{"class":194},[33,2776,199],{"class":198},[33,2778,202],{"class":194},[33,2780,206],{"class":205},[33,2782,2246],{"class":291},[33,2784,2785],{"class":194},");        ",[33,2787,2788],{"class":39},"\u002F\u002F \"object\" (bug, since 1995)\n",[33,2790,2791,2793,2795,2797,2800,2803,2806,2808],{"class":35,"line":125},[33,2792,195],{"class":194},[33,2794,199],{"class":198},[33,2796,202],{"class":194},[33,2798,2799],{"class":291},"null",[33,2801,2802],{"class":205}," instanceof",[33,2804,2805],{"class":198}," Object",[33,2807,510],{"class":194},[33,2809,2810],{"class":39},"\u002F\u002F false (null is NOT an Object instance)\n",[33,2812,2813],{"class":35,"line":131},[33,2814,2815],{"class":39},"\u002F\u002F Correct null check: val === null (strict equality)\n",[33,2817,2818],{"class":35,"line":137},[33,2819,141],{"emptyLinePlaceholder":140},[33,2821,2822],{"class":35,"line":144},[33,2823,2824],{"class":39},"\u002F\u002F ── `[]` and `{}` are truthy (unlike Python where they're falsy) ──\n",[33,2826,2827,2830,2833,2835,2837,2840,2843],{"class":35,"line":150},[33,2828,2829],{"class":205},"if",[33,2831,2832],{"class":194}," ([]) console.",[33,2834,199],{"class":198},[33,2836,202],{"class":194},[33,2838,2839],{"class":269},"\"empty array is truthy\"",[33,2841,2842],{"class":194},");    ",[33,2844,2845],{"class":39},"\u002F\u002F prints!\n",[33,2847,2848,2850,2853,2855,2857,2860,2862],{"class":35,"line":156},[33,2849,2829],{"class":205},[33,2851,2852],{"class":194}," ({}) console.",[33,2854,199],{"class":198},[33,2856,202],{"class":194},[33,2858,2859],{"class":269},"\"empty object is truthy\"",[33,2861,1065],{"class":194},[33,2863,2845],{"class":39},[33,2865,2866,2868,2870,2872,2875,2877,2879,2882,2885],{"class":35,"line":162},[33,2867,2829],{"class":205},[33,2869,2494],{"class":194},[33,2871,849],{"class":291},[33,2873,2874],{"class":194},") console.",[33,2876,199],{"class":198},[33,2878,202],{"class":194},[33,2880,2881],{"class":269},"\"0 is falsy\"",[33,2883,2884],{"class":194},");                 ",[33,2886,2887],{"class":39},"\u002F\u002F does NOT print\n",[33,2889,2890],{"class":35,"line":168},[33,2891,2892],{"class":39},"\u002F\u002F Only 6 falsy values: false, 0, -0, 0n, \"\", null, undefined, NaN\n",[33,2894,2895],{"class":35,"line":174},[33,2896,2897],{"class":39},"\u002F\u002F (Empty array\u002Fobject are NOT in the falsy list)\n",[33,2899,2900],{"class":35,"line":180},[33,2901,141],{"emptyLinePlaceholder":140},[33,2903,2904],{"class":35,"line":185},[33,2905,2906],{"class":39},"\u002F\u002F ── `NaN` is the only value not equal to itself ──\n",[33,2908,2909,2911,2913,2915,2918,2921,2924,2926],{"class":35,"line":191},[33,2910,195],{"class":194},[33,2912,199],{"class":198},[33,2914,202],{"class":194},[33,2916,2917],{"class":291},"NaN",[33,2919,2920],{"class":205}," ===",[33,2922,2923],{"class":291}," NaN",[33,2925,510],{"class":194},[33,2927,2928],{"class":39},"\u002F\u002F false\n",[33,2930,2931,2933,2935,2938,2941,2943,2945,2947],{"class":35,"line":215},[33,2932,195],{"class":194},[33,2934,199],{"class":198},[33,2936,2937],{"class":194},"(Number.",[33,2939,2940],{"class":198},"isNaN",[33,2942,202],{"class":194},[33,2944,2917],{"class":291},[33,2946,2559],{"class":194},[33,2948,2949],{"class":39},"\u002F\u002F true (correct way)\n",[33,2951,2952,2954,2956,2959,2962,2964,2966,2968,2970,2972],{"class":35,"line":232},[33,2953,195],{"class":194},[33,2955,199],{"class":198},[33,2957,2958],{"class":194},"(Object.",[33,2960,2961],{"class":198},"is",[33,2963,202],{"class":194},[33,2965,2917],{"class":291},[33,2967,680],{"class":194},[33,2969,2917],{"class":291},[33,2971,2559],{"class":194},[33,2973,2974],{"class":39},"\u002F\u002F true (Object.is handles NaN and -0)\n",[15,2976,2978],{"id":2977},"quick-quiz","🧠 Quick Quiz",[2980,2981,2982],"p",{},"What's the output order?",[20,2984,2985],{"language":22},[24,2986,2988],{"className":26,"code":2987,"language":22,"meta":28,"style":28},"console.log(\"A\");\nsetTimeout(() => console.log(\"B\"), 0);\nPromise.resolve().then(() => console.log(\"C\"));\nconsole.log(\"D\");\nqueueMicrotask(() => console.log(\"E\"));\n",[30,2989,2990,3003,3026,3053,3066],{"__ignoreMap":28},[33,2991,2992,2994,2996,2998,3001],{"class":35,"line":36},[33,2993,195],{"class":194},[33,2995,199],{"class":198},[33,2997,202],{"class":194},[33,2999,3000],{"class":269},"\"A\"",[33,3002,636],{"class":194},[33,3004,3005,3007,3009,3011,3013,3015,3017,3020,3022,3024],{"class":35,"line":43},[33,3006,1788],{"class":198},[33,3008,1791],{"class":194},[33,3010,1794],{"class":205},[33,3012,1797],{"class":194},[33,3014,199],{"class":198},[33,3016,202],{"class":194},[33,3018,3019],{"class":269},"\"B\"",[33,3021,1807],{"class":194},[33,3023,849],{"class":291},[33,3025,636],{"class":194},[33,3027,3028,3030,3032,3034,3036,3038,3040,3042,3044,3046,3048,3051],{"class":35,"line":49},[33,3029,1820],{"class":291},[33,3031,1823],{"class":194},[33,3033,706],{"class":198},[33,3035,1828],{"class":194},[33,3037,1831],{"class":198},[33,3039,1791],{"class":194},[33,3041,1794],{"class":205},[33,3043,1797],{"class":194},[33,3045,199],{"class":198},[33,3047,202],{"class":194},[33,3049,3050],{"class":269},"\"C\"",[33,3052,1847],{"class":194},[33,3054,3055,3057,3059,3061,3064],{"class":35,"line":55},[33,3056,195],{"class":194},[33,3058,199],{"class":198},[33,3060,202],{"class":194},[33,3062,3063],{"class":269},"\"D\"",[33,3065,636],{"class":194},[33,3067,3068,3071,3073,3075,3077,3079,3081,3084],{"class":35,"line":61},[33,3069,3070],{"class":198},"queueMicrotask",[33,3072,1791],{"class":194},[33,3074,1794],{"class":205},[33,3076,1797],{"class":194},[33,3078,199],{"class":198},[33,3080,202],{"class":194},[33,3082,3083],{"class":269},"\"E\"",[33,3085,1847],{"class":194},[3087,3088,3089,3093,3101,3135],"details",{},[3090,3091,3092],"summary",{},"Answer",[24,3094,3099],{"className":3095,"code":3097,"language":3098},[3096],"language-text","A\nD\nC\nE\nB\n","text",[30,3100,3097],{"__ignoreMap":28},[3102,3103,3104,3111,3117,3123,3129],"ol",{},[3105,3106,3107,3110],"li",{},[30,3108,3109],{},"A"," — synchronous (script is a macrotask, runs first)",[3105,3112,3113,3116],{},[30,3114,3115],{},"D"," — synchronous (continues)",[3105,3118,3119,3122],{},[30,3120,3121],{},"C"," — microtask (Promise.then, drained after script)",[3105,3124,3125,3128],{},[30,3126,3127],{},"E"," — microtask (queueMicrotask, same microtask drain)",[3105,3130,3131,3134],{},[30,3132,3133],{},"B"," — macrotask (setTimeout, runs after all microtasks drained)",[2980,3136,3137,3141],{},[3138,3139,3140],"strong",{},"The lesson",": all microtasks (Promise.then, queueMicrotask) run before the next macrotask (setTimeout). The microtask queue is fully drained before the event loop moves to the next macrotask.",[3143,3144,3145],"style",{},"html pre.shiki code .sdCPZ, html code.shiki .sdCPZ{--shiki-default:#6A737D;--shiki-github-dark:#6A737D}html pre.shiki code .ssxIu, html code.shiki .ssxIu{--shiki-default:#24292E;--shiki-github-dark:#E1E4E8}html pre.shiki code .sIsaT, html code.shiki .sIsaT{--shiki-default:#6F42C1;--shiki-github-dark:#B392F0}html pre.shiki code .svdQ7, html code.shiki .svdQ7{--shiki-default:#D73A49;--shiki-github-dark:#F97583}html pre.shiki code .sJ6F3, html code.shiki .sJ6F3{--shiki-default:#032F62;--shiki-github-dark:#9ECBFF}html pre.shiki code .snvgF, html code.shiki .snvgF{--shiki-default:#005CC5;--shiki-github-dark:#79B8FF}html pre.shiki code .sCrzJ, html code.shiki .sCrzJ{--shiki-default:#E36209;--shiki-github-dark:#FFAB70}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}html.github-dark .shiki span {color: var(--shiki-github-dark);background: var(--shiki-github-dark-bg);font-style: var(--shiki-github-dark-font-style);font-weight: var(--shiki-github-dark-font-weight);text-decoration: var(--shiki-github-dark-text-decoration);}",{"title":28,"searchDepth":43,"depth":43,"links":3147},[3148,3149,3150,3151,3152,3153,3154,3155,3156],{"id":17,"depth":43,"text":18},{"id":550,"depth":43,"text":551},{"id":914,"depth":43,"text":915},{"id":1421,"depth":43,"text":1422},{"id":1719,"depth":43,"text":1720},{"id":1977,"depth":43,"text":1978},{"id":2326,"depth":43,"text":2327},{"id":2674,"depth":43,"text":2675},{"id":2977,"depth":43,"text":2978},"Deep-dive into JavaScript engine internals: V8\u002FSpiderMonkey\u002FJSCore architecture, the call stack and heap, event loop phases, JIT compilation, and the Node.js vs browser runtime model. Code-first reference for mid-to-senior engineers.","md",{},"\u002Fjs\u002F01-introduction-and-setup",{"title":5,"description":3157},"js\u002F01-introduction-and-setup","P6Ba33cx0scgtFr1s8UKYOc60F0rk51mUYtYTa3B5WU",1789924648836]