# Data flow — lodash/lodash

> Canonical page: https://codevetter.com/unpack/lodash/data-flow

# Data flow — lodash/lodash

Scanned commit 2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8 (2026-09-11). Generated by codevetter codevetter 1.12.0 on 2026-09-22.

Two distinct flows exist. At library runtime, data enters as plain JS values through method arguments, is normalized by `castPath`/`toKey`/`baseIteratee`, mutated or cloned by `base*` internals, and exits either as a new value or — in chain mode — as a `LazyWrapper`/`lodash` wrapper holding `__wrapped__` and an `__actions__` queue that is only drained on `.value()`. At build time, the input boundary is `lodash.js` plus `fp/_mapping.js`; transforms are `fs.copy`, `uglify.minify`, `webpack`, `docdown` and `_.template`-compiled `.jst` files; the output boundary is the filesystem (`dist/`, `doc/`, or an arbitrary `target` from `process.argv`). The FP path is unusual: `_mapping.js` is pure data that is read three times — by `_baseConvert` at runtime, by `build-modules.js` to decide which template to emit, and by `build-doc.js` to render the wiki.
- Property paths are the main untrusted input boundary: `castPath` converts strings/arrays to key arrays and `toKey` normalizes each segment before any read or write in `baseGet`/`baseSet`/`baseUnset`. — [lodash.js#L4025-4033](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L4025-L4033) [lodash.js#L4376-4382](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L4376-L4382) [lodash.js#L6406-6422](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L6406-L6422)
- Writes funnel through `assignValue` → `baseAssignValue`, which special-cases the key `__proto__` by using `Object.defineProperty` with an own data descriptor rather than plain assignment, so it lands on the object instead of the prototype. — [lodash.js#L2597-2610](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L2597-L2610)
- Deep merge reads go through `safeGet`, which returns `undefined` for `__proto__` and for `constructor` when it resolves to a function — cutting the read side of the pollution chain. — [lodash.js#L6697-6715](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L6697-L6715)
- Chain state lives on the wrapper instance: `mixin` installs prototype methods that clone `__actions__` via `copyArray`, push `{func, args, thisArg}`, carry `__chain__` forward, and defer execution until `.value()`. — [lodash.js#L15840-15861](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L15840-L15861) [lodash.js#L17222-17226](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lodash.js#L17222-L17226)
- In `_baseConvert`, each method flows through a fixed transform pipeline — immutability wrapper → `castFixed` (arity cap or `flatSpread`) → `castRearg` (argument permutation) → `castCap` (iteratee arity cap) → `castCurry` — with `methodSpread[name].afterRearg` deciding whether fixed or rearg runs first. — [fp/_baseConvert.js#L468-512](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/fp/_baseConvert.js#L468-L512)
- The FP converter owns two state sources: a `pristine = func.runInContext()` snapshot used so `.convert()` re-derives from unconverted methods, and a `defaultHolder` placeholder that is stamped onto both the wrapped and original function as `.placeholder`. — [fp/_baseConvert.js#L160-165](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/fp/_baseConvert.js#L160-L165) [fp/_baseConvert.js#L388-400](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/fp/_baseConvert.js#L388-L400) [fp/_baseConvert.js#L512-516](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/fp/_baseConvert.js#L512-L516)
- Conversion output is assembled as `pairs` of `[name, wrappedFn]` — first for every name in `mapping.aryMethod[1..4]`, then for remaining own function keys — and only then assigned back onto `_`, deliberately leaving `_.prototype` untouched so chaining still works. — [fp/_baseConvert.js#L520-560](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/fp/_baseConvert.js#L520-L560)
- `_.set`-family immutability in FP is achieved by `cloneByPath`, which walks the resolved path cloning each level but skipping values that are functions, errors or WeakMaps. — [fp/_baseConvert.js#L348-368](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/fp/_baseConvert.js#L348-L368)
- Build data flows from `fp/_mapping.js` → `lib/common/mapping.js` (null-prototype Hash) → `lib/fp/build-modules.js`, where `_.union(mapping.aryMethod[1..4])` forms `aryMethods` and drives the `isThru` decision for every emitted module. — [lib/common/mapping.js#L3-9](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/common/mapping.js#L3-L9) [lib/fp/build-modules.js#L15-20](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/fp/build-modules.js#L15-L20) [lib/fp/build-modules.js#L76-103](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/fp/build-modules.js#L76-L103)
- `.jst` templates are compiled to functions at require time by `file.globTemplate`, which globs `*.jst`, keys them by basename, and runs each through `_.template` — so `template.module`, `template.alias`, `template.wiki` are lodash templates executed with `{name, mapping}` data. — [lib/common/file.js#L32-37](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/common/file.js#L32-L37) [lib/fp/build-modules.js#L12-13](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/fp/build-modules.js#L12-L13) [lib/fp/build-doc.js#L11-20](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/fp/build-doc.js#L11-L20)
- The doc HTML flow mutates markdown through five ordered regex rewrites (uncommenting docdown HTML hints, converting `[source]`/`[npm package]` links after `<h3>`) before Cheerio DOM passes `autoLink`, `renameLodashId`, `removeHorizontalRules`, `removeMarkyAttributes`, `repairMarkyHeaders`, `tidyHighlights`. — [lib/main/build-site.js#L182-218](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/main/build-site.js#L182-L218)
- The site build derives its output filename from the document itself — it removes the first `<h1>`, reads the version out of its `<span>`, and writes `doc/<version>.html`; if that span is missing the front matter records `version: null`. — [lib/main/build-site.js#L204-236](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/lib/main/build-site.js#L204-L236)
- In the browser harness, the build path is a URL query parameter: `test-ui.js` parses `?build=` and `?loader=`, maps them to file paths, and `test/index.html` `document.write`s those paths as script tags — the page loads whatever path the URL names, including a full remote URL (`ui.isForeign`). — [test/asset/test-ui.js#L8-11](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/test/asset/test-ui.js#L8-L11) [test/asset/test-ui.js#L109-137](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/test/asset/test-ui.js#L109-L137) [test/index.html#L191-207](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/test/index.html#L191-L207)
- Web Worker coverage round-trips the build path: `test.js` posts `ui.buildPath` to `test/asset/worker.js`, which `importScripts` it and posts back `_.VERSION` (or the caught error message stuffed into a fake `VERSION`), landing in `_._VERSION`. — [test/test.js#L730-738](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/test/test.js#L730-L738) [test/asset/worker.js#L5-17](https://github.com/lodash/lodash/blob/2b5e6f7399a7b48005140b5d5c6bc6c0e62919a8/test/asset/worker.js#L5-L17)

Every claim links to its cited files at the pinned commit. Citations identify source evidence; they do not establish runtime correctness. Independent CodeVetter scan — not reviewed by upstream maintainers.

## Public product links

- [CodeVetter](https://codevetter.com/)
- [Download](https://codevetter.com/download)
- [Documentation](https://codevetter.com/docs/)
- [Source](https://github.com/Codevetter/codevetter)
