( mod, moduleGraph, depth, SideEffectDep, ctx )
| 417 | * @returns {ConnectionState} the side-effects connection state |
| 418 | */ |
| 419 | const walkSideEffectsRecursive = ( |
| 420 | mod, |
| 421 | moduleGraph, |
| 422 | depth, |
| 423 | SideEffectDep, |
| 424 | ctx |
| 425 | ) => { |
| 426 | // Interleaved `[mod, linearDep, mod, linearDep, …]` for the linear |
| 427 | // chain head; `null` until the first descent. |
| 428 | /** @type {(NormalModule | Dependency)[] | null} */ |
| 429 | let linearAncestors = null; |
| 430 | |
| 431 | // Walk the linear-chain head iteratively. Every loop iteration peels |
| 432 | // off one module without consuming a V8 stack frame. |
| 433 | while (true) { |
| 434 | if (mod._sideEffectsStateGraph === moduleGraph) { |
| 435 | return propagateLinearResult( |
| 436 | linearAncestors, |
| 437 | /** @type {ConnectionState} */ (mod._sideEffectsStateValue), |
| 438 | moduleGraph, |
| 439 | ctx |
| 440 | ); |
| 441 | } |
| 442 | |
| 443 | if (mod.factoryMeta !== undefined) { |
| 444 | if (mod.factoryMeta.sideEffectFree) { |
| 445 | return propagateLinearResult(linearAncestors, false, moduleGraph, ctx); |
| 446 | } |
| 447 | if (mod.factoryMeta.sideEffectFree === false) { |
| 448 | return propagateLinearResult(linearAncestors, true, moduleGraph, ctx); |
| 449 | } |
| 450 | } |
| 451 | if (!(mod.buildMeta !== undefined && mod.buildMeta.sideEffectFree)) { |
| 452 | return propagateLinearResult(linearAncestors, true, moduleGraph, ctx); |
| 453 | } |
| 454 | if (mod._isEvaluatingSideEffects) { |
| 455 | ctx.circular = true; |
| 456 | return propagateLinearResult( |
| 457 | linearAncestors, |
| 458 | ModuleGraphConnection.CIRCULAR_CONNECTION, |
| 459 | moduleGraph, |
| 460 | ctx |
| 461 | ); |
| 462 | } |
| 463 | |
| 464 | // A real ESM module's `dependencies` typically include one |
| 465 | // `HarmonyImportSideEffectDependency` plus several non-recursive deps |
| 466 | // (export specifiers, const dependencies, …) that report |
| 467 | // `false`/`CIRCULAR_CONNECTION` from |
| 468 | // `getModuleEvaluationSideEffectsState`. Walk the deps in order |
| 469 | // here: as long as at most one is a `SideEffectDep` and no |
| 470 | // non-recursive dep triggers a bailout or contributes a non-`false` |
| 471 | // state, we can still tail-call iteratively through that one |
| 472 | // `SideEffectDep` — no V8 frame needed. This is what keeps the |
| 473 | // 1300-module cyclic chain from #20986 from overflowing V8's stack |
| 474 | // even though each generated module has multiple `dependencies`. |
| 475 | const deps = mod.dependencies; |
| 476 | /** @type {Dependency | null} */ |
no test coverage detected