Commit daf76c5
feat: enhanced SEA mode with walker integration and VFS (#229)
* feat: enhanced SEA mode with walker integration and VFS (#204)
Evolves the --sea flag from a simple single-file wrapper into a full
packaging pipeline that reuses the walker for dependency discovery,
maps files as SEA assets, and provides a runtime VFS bootstrap using
@platformatic/vfs for transparent fs/require/import support.
- Add seaMode to walker: skips bytecode compilation and ESM-to-CJS
transform, but still discovers all dependencies via stepDetect
- Add sea-assets.ts: generates SEA asset map and manifest JSON from
walker output (directories, stats, symlinks, native addons)
- Add sea-bootstrap.js: runtime bootstrap with lazy SEAProvider,
native addon extraction, and process.pkg compatibility
- Add seaEnhanced() to sea.ts: walker → refiner → asset gen → blob →
bake pipeline with Node 25.5+ --build-sea detection
- Route --sea to enhanced mode when input has package.json and target
Node >= 22; falls back to simple mode otherwise
- Add 4 test suites: multi-file project, asset access, ESM (skipped
until node:vfs lands), and VFS fs operations
Closes #204
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: move @platformatic/vfs to optionalDependencies for Node 20 CI compat
@platformatic/vfs requires Node >= 22 but CI runs on Node 20. Since the
package is only needed at build time (esbuild bundles it into the
sea-bootstrap) and the bundle step is skipped on Node < 22, making it
optional prevents yarn install failures on older Node versions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: drop Node.js 20 support, require Node.js >= 22
Node.js 20 reached EOL in April 2026. This simplifies the project by
removing the Node 20 CI matrix, test scripts, and engine check. It also
allows @platformatic/vfs to be a regular dependency (requires Node 22+)
and removes the conditional build script for sea-bootstrap.
- Update engines to >=22.0.0 in package.json
- Remove node20 from CI matrix (ci.yml, test.yml)
- Update update-dep.yml to use Node 22
- Move @platformatic/vfs from optionalDependencies to dependencies
- Simplify build:sea-bootstrap script (no Node version check)
- Update README examples and SEA requirements
- Update @types/node to ^22.0.0
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore test-00-sea Node version guard to < 20
Simple SEA mode was introduced in Node 20, not Node 22. The guard
should reflect when the Node.js feature was added, not the project
minimum.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: restore assertSeaNodeVersion to check Node >= 20
The shared assertSeaNodeVersion() is used by both simple and enhanced
SEA modes. Simple SEA was introduced in Node 20 — the check should
reflect that. Enhanced mode's Node 22 requirement is enforced
separately by the routing logic in index.ts.
Also fixes README --sea description to explain both modes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* test: enhance SEA mode tests for pkg compatibility and error handling
* fix: improve error handling and conditionally remove Mach-O signature on macOS
* refactor: extract shared runtime code into bootstrap-shared.js
Move dlopen patching, child_process patching, and process.pkg setup
into a shared module used by both the traditional and SEA bootstraps.
This eliminates duplication and ensures both modes handle native
addons, subprocess spawning, and process.pkg identically.
- Replace copyFolderRecursiveSync with fs.cpSync (Node >= 22)
- Add REQUIRE_SHARED parameter to packer wrapper for traditional mode
- SEA bootstrap consumes shared module via esbuild bundling
- Remove dead code (ARGV0, homedir import, copyFolderRecursiveSync)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review feedback on SEA pipeline
- Handle non-numeric nodeRange (e.g. "latest") in enhanced SEA gating
- Bump assertSeaNodeVersion to require Node >= 22 matching engines
- Guard stepStrip in walker to only strip JS/ESM files in SEA mode,
preventing binary corruption of .node addons
- Replace blanket eslint-disable in sea-bootstrap.js with targeted
no-unused-vars override in eslint config
- Wire symlinks through to SEA manifest and bootstrap provider
- Document --build-sea Node 25 gating assumption
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: throw when JSON config targets Node < 22 in SEA mode
Instead of silently falling back to simple SEA mode when the input is a
package.json/config but targets are below Node 22, throw a clear error.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: normalize paths for Windows compatibility in SEA bootstrap
* docs: add technical architecture documentation
Detailed comparison of traditional pkg mode vs enhanced SEA mode
covering build pipelines, binary formats, runtime bootstraps, VFS
provider architecture, shared code, performance, and code protection.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: normalize all SEA provider paths to POSIX for Windows compatibility
The SEA manifest uses POSIX keys but VFS passes platform-native paths on
Windows. Normalize all paths to POSIX in the SEAProvider before manifest
lookups, SEA asset lookups, and MemoryProvider storage. Remove the now-
redundant symlink normalization block.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: mention --no-bytecode flag in architecture comparison
Explains that traditional mode with --no-bytecode produces a similar
code protection profile to enhanced SEA (plaintext source), while
still retaining compression and custom VFS format advantages.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review feedback for SEA enhanced mode
- Replace fs.cpSync with recursive copy using patched fs primitives
so native addon extraction works through VFS in SEA mode
- Use toPosixKey instead of snapshotify for symlink manifest keys
to match the key format used by directories/stats/assets
- Make assertSeaOutput log explicit skip on unsupported platforms
instead of silently passing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add DEBUG_PKG diagnostics to SEA mode, deduplicate diagnostic code
Move VFS tree dump and fs call tracing from prelude/diagnostic.js into
bootstrap-shared.js as installDiagnostic(). Both bootstraps now share
the same diagnostic implementation.
Security: diagnostics are only available when built with --debug / -d.
In SEA mode this is controlled via manifest.debug flag set at build
time; without it, installDiagnostic is never called.
- Delete prelude/diagnostic.js (replaced by shared installDiagnostic)
- Packer injects small DICT-dump snippet + shared call when --debug
- SEA bootstrap gates on manifest.debug before calling installDiagnostic
- Fix assertSeaNodeVersion: restore check to Node >= 20 (simple SEA)
- Fix withSeaTmpDir: restore tmpDir cleanup (was commented out)
- Update architecture docs with diagnostic usage
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address remaining Copilot review feedback
- Bump assertSeaNodeVersion minimum from Node 20 to 22 (consistent with engines)
- Extract generateSeaBlob() helper with --build-sea fallback for Node 25.x
- Accept separate defaultEntrypoint in setupProcessPkg for process.pkg compat
- Update ARCHITECTURE.md Simple SEA min Node from 20 to 22
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add worker thread support and fix SEA walker warnings
Worker thread support:
- Extract VFS setup into shared sea-vfs-setup.js (used by both main and
worker threads, no duplication)
- Bundle sea-worker-entry.js separately via esbuild — workers get the
same @platformatic/vfs module hooks as the main thread
- Monkey-patch Worker constructor to intercept /snapshot/ paths and
inject the bundled VFS bootstrap via eval mode
- Add test-90-sea-worker-threads test
Walker fix:
- Skip stepDetect (Babel parser) for non-JS files in SEA mode — only
run on .js/.cjs/.mjs files, matching the existing stepStrip guard.
Eliminates thousands of spurious warnings on .json, .d.ts, .md, .node
files in real-world projects.
Build:
- Extract build:sea-bootstrap into scripts/build-sea-bootstrap.js for
two-step bundling (worker entry → string, then main bootstrap)
TODO: Remove node_modules/@platformatic/vfs patches once
platformatic/vfs#9 is merged and released.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: update architecture documentation to include worker thread support details
* fix: mount VFS at POSIX /snapshot on all platforms for Windows compat
The VFS mount point must always be POSIX '/snapshot' because
@platformatic/vfs internally uses '/' as the path separator.
The Windows prototype patches convert C:\snapshot\... and V:\snapshot\...
to /snapshot/... before they reach the VFS.
This was broken during the sea-vfs-setup.js extraction where
SNAPSHOT_PREFIX was incorrectly set to 'C:\snapshot' on Windows.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use Module._compile for worker threads instead of raw eval
Worker threads in eval mode get a synthetic require() that doesn't
honour module.filename for relative path resolution. This caused
require('./lib/helper.js') to fail inside workers.
Fix by creating a proper CJS module context via Module._compile(),
which sets up the correct resolution base path from the worker's
snapshot filename.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: use postject JS API instead of npx to inject SEA blobs
Replace `npx postject` shell invocations with the postject JS API
(`inject()` function) imported as a direct dependency.
This fixes two CI issues:
1. "Text file busy" — concurrent npx invocations race on the shared
npx cache when building multiple platform targets in parallel
2. "Argument is not a constructor" — npx downloading an incompatible
postject version at runtime
Using the JS API is also faster (no npm download/extraction overhead)
and more reliable (deterministic version from package.json).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: avoid eager file loading and unnecessary temp files in SEA walker
- Narrow SEA mode read condition to JS/ESM files only, preventing
binary assets (.node, images) from being loaded into memory
- Add bodyModified flag to FileRecord to track intentional modifications
(patches, package.json rewrites) vs mere reads
- Use bodyModified in generateSeaAssets instead of body != null so
unmodified files reference source paths directly
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: pass defaultEntrypoint in SEA bootstrap for API consistency
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add snapshotify function to convert file paths to snapshot paths
* docs: fix version comments and Node 22 requirement notes
- Clarify --build-sea is available from Node 25.5+, not 25.0
- Add JSDoc note explaining why SEA requires Node 22+ despite node:sea
being stable from Node 20
- Clarify node:sea row in ARCHITECTURE.md ecosystem table
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: reuse replaceSlashes from common.ts instead of duplicate toPosixKey
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: handle VFS-incompatible fs calls in SEA bootstrap
Two fixes for the SEA runtime bootstrap:
1. Replace fs.copyFileSync with readFileSync+writeFileSync in the
dlopen patch's cpRecursive helper. copyFileSync is not routed
through the VFS in overlay mode, causing ENOENT when extracting
native addon packages from the snapshot.
2. Wrap fs.realpathSync in try-catch in the diagnostic dumpLevel
function. realpathSync can fail on VFS paths, crashing the
DEBUG_PKG tree dump.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: add SKILL.md for packaging performance benchmarks comparison
* perf: optimize SEA provider startup and add DEBUG_PKG_PERF instrumentation
Optimize the SEAProvider hot paths for large projects (~20% faster startup):
- Override internalModuleStat() with O(1) manifest lookup, bypassing the
MemoryProvider tree walk (~30K calls saved for zwave-js-ui)
- Override statSync() to return lightweight stat objects from the manifest
- Cache readFileSync() results in a flat Map, bypassing MemoryProvider
write+read roundtrip. Returns Buffer copies to prevent cache corruption.
- Override existsSync() with pure manifest lookup
Add DEBUG_PKG_PERF=1 runtime instrumentation (works on any SEA binary,
no --debug build required). Reports phase timings (manifest parse,
directory tree init, module loading) and provider counters (files loaded,
stat/exists/readdir calls, sea.getRawAsset cumulative time).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs: split project instructions into modular .claude/rules files
CLAUDE.md referenced .github/copilot-instructions.md via a markdown link,
but Claude Code doesn't follow links — it only auto-loads CLAUDE.md and
.claude/rules/*.md. Created 5 focused rule files with path-scoping so
Claude Code actually sees the project instructions. Copilot instructions
file is unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat: enhance SEA asset generation with single archive blob and offsets for zero-copy access
* docs: update README and ARCHITECTURE.md for single archive blob and refactored VFS
- README: fix stale node14 references, add dedicated SEA Mode section with
simple vs enhanced variants, link to ARCHITECTURE.md
- ARCHITECTURE: rewrite SEA binary format to document single __pkg_archive__
blob with offsets map instead of per-file assets, document sea-vfs-setup.js
as shared VFS core, rewrite worker thread section (workers now reuse same
@platformatic/vfs via sea-vfs-setup.js), fix all line counts, update
VFS provider diagram and performance/code-protection tables
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: enable model invocation for performances-compare skill
* refactor: replace @platformatic/vfs with @roberts_lando/vfs@0.3.0
Swap the VFS polyfill dependency from @platformatic/vfs to
@roberts_lando/vfs@0.3.0 across all source, prelude, scripts,
and documentation files.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: update Node.js version requirements and testing commands in documentation
* feat: track body modifications in stepStrip for enhanced record handling
* chore: update @roberts_lando/vfs to version 0.3.1 in package.json, package-lock.json, and yarn.lock
* chore: update @roberts_lando/vfs to version 0.3.2
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review — patchDlopen regression, SEA blob fallback, CRLF normalization
- Restore unconditional native addon copy in patchDlopen with per-file
SHA-256 checksums, matching original vercel/pkg behavior (PRs vercel#1492, vercel#1611).
The existsSync guard on destFolder was a regression — OS cleanup can
delete files inside the cache while leaving the directory intact.
- Narrow generateSeaBlob fallback to only catch unsupported --build-sea
flag errors (exit code 9 / "bad option"), rethrow real failures.
- Normalize CRLF in assertSeaOutput and test-00-sea for Windows compat.
Uncomment previously disabled Windows SEA assertion.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* refactor: use assertSeaOutput helper in test-00-sea
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: address Copilot review — dlopen VFS, docs, prettierignore
- bootstrap-shared.js: standalone addon branch now uses writeFileSync
with the already-read moduleContent (reuses hash too), so extraction
works through VFS in SEA mode instead of calling copyFileSync.
- bootstrap-shared.js: extract cpRecursive helper out of patchDlopen
for readability.
- docs/ARCHITECTURE.md: drop stale diagnostic.js reference and clarify
that installDiagnostic ships in the bundle but is only invoked when
the binary is built with --debug.
- .prettierignore: ignore generated prelude/sea-bootstrap.bundle.js so
post-build lint stays clean.
* feat(sea): support ESM entrypoints with top-level await
Split the SEA bootstrap into a shared core plus two thin wrappers so ESM
entrypoints work on any supported Node.js target:
- `sea-bootstrap-core.js` — VFS mount, shared patches, worker interception,
diagnostics. Exports `{ manifest, entrypoint }` with no entry execution.
- `sea-bootstrap.js` (CJS) — `Module.runMain()` for CJS entries; dynamic
`import(pathToFileURL(entry))` fallback for ESM entries on Node < 25.7.
- `sea-bootstrap-esm.js` (ESM) — static `import core` + top-level
`await import(entry)` for Node >= 25.7 with `mainFormat: "module"`.
`lib/sea.ts` picks the right bundle and sea-config based on entry format
and the smallest target Node major. When the ESM-on-old-Node fallback is
used, a build-time `log.warn` explains the limitations (one microtask
delay, no sync require of ESM-with-TLA deps) and points at Node 25.7+ as
the fix. No runtime warning is emitted.
Also refresh the symlink + read-once-Buffer improvements to `cpRecursive`
in bootstrap-shared.js (prevents infinite recursion and unwanted content
escape on addon packages with symlinks; halves I/O on the hash-mismatch
path).
Add tests:
- `test-91-sea-esm-entry` — ESM entry with relative `.mjs` imports
- `test-92-sea-tla` — ESM entry using top-level await
Update `docs/ARCHITECTURE.md` with the dual-wrapper layout, the
bootstrap-selection table, the TLA section, and the 3-step esbuild flow.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(readme): document ESM entry + top-level await in SEA mode
Clarify the enhanced SEA bullet list: ESM entries work on any supported
Node target (native on Node >= 25.7 via mainFormat:"module", dynamic
import() fallback on Node 22-25.6 with a build-time warning). Also note
that DEBUG_PKG diagnostics are available but only when built with --debug.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(sea): harden SEA pipeline — CJS bootstrap for ESM+TLA, blob generator selection, cross-plat
- Always use CJS bootstrap: Node 25.5+ embedder dynamic-import callback
only resolves builtins (nodejs/node#62726), so native ESM SEA main
cannot import the user entrypoint. ESM entries are dispatched through
a vm.Script compiled with USE_MAIN_CONTEXT_DEFAULT_LOADER, which routes
dynamic import() to the default ESM loader and supports top-level await.
Drop the now-unused sea-bootstrap-esm.js and its bundle step.
- Pick SEA blob generator binary by host/target major: use process.execPath
when host major matches minTargetMajor (works for cross-platform builds),
else the downloaded target binary (works cross-major when host can exec
it). Restores cross-platform same-major SEA builds.
- Split host/target node version checks: assertHostSeaNodeVersion covers
the pkg host, resolveMinTargetMajor validates targets separately.
- Reject useSnapshot:true in enhanced SEA mode — incompatible with the VFS
bootstrap (snapshot build has no __pkg_archive__ asset).
- Trust in-memory body in sea-assets when present: walker invariant
guarantees body equals shippable bytes in seaMode (ESM→CJS and
type:module rewrites are gated on !seaMode). Removes bodyModified flag
and a redundant disk re-read, and makes the build race-safe against
mid-build source edits.
- stepStrip leaves record.body untouched on no-op so Buffer identity is
preserved for the sea-assets reuse path.
- perf.finalize() moved into each bootstrap dispatcher's finally block so
module-loading timings reflect real entrypoint completion (including
async / top-level-await apps) and still print on thrown entrypoints.
Error paths set process.exitCode instead of process.exit() so the
finally runs.
- _resolveSymlink now throws ELOOP instead of returning the last hop,
matching fs semantics for broken symlink cycles.
- insideSnapshot refactored to a prefix table; behavior unchanged.
- Share public / no-dict / publicPackages WalkerParams between the SEA
and traditional pipelines in lib/index.ts.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(sea): self-review fixes — symlink fallback, archive bounds, short-write loop
- bootstrap-shared.js: cpRecursive() falls back to recursive copy when
symlinkSync throws EPERM/EACCES on Windows (no admin / dev mode), so
native addon extraction no longer aborts silently.
- sea-vfs-setup.js: validate manifest offsets before Buffer.subarray() —
corrupt or truncated manifests now throw instead of returning silently
truncated bytes. Also hoist MAX_SYMLINK_DEPTH to a named const and stop
reaching the module-scope provider from perf.finalize().
- sea-assets.ts: writeAll() helper loops on FileHandle.write bytesWritten
for both buffer and stream paths, keeping manifest offsets byte-exact
even under filesystem backpressure.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* docs(sea): align README + ARCHITECTURE with single-bootstrap dispatch
ESM/TLA now runs through one CJS wrapper using vm.Script +
USE_MAIN_CONTEXT_DEFAULT_LOADER on every Node >= 22 target. Native
ESM SEA main (mainFormat:"module") is not used — nodejs/node#62726
blocks embedder dynamic-import of the user entry. Also documents
useSnapshot incompatibility, --experimental-sea-config-only blob
generation, and the host/target blob generator picker. File
reference + ecosystem tables refreshed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* perf(sea): read SEA blob once and share buffer across targets
bake() previously reloaded the prep blob from disk per target inside
Promise.all, causing N redundant reads and N peak buffer copies on
multi-target builds. Read once before the loop and pass the shared
Buffer into bake().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix(sea): address copilot review — mixed-major guard, emitWarning leak, test cleanup
- lib/sea.ts: add assertSingleTargetMajor() and call from both sea() and
seaEnhanced(). SEA prep blobs are Node-major specific, so mixing majors
in one run (e.g. -t node22-linux-x64,node24-linux-x64) silently produced
broken executables. Reject up front instead.
- prelude/sea-bootstrap.js: restore the original process.emitWarning as
soon as the SEA loader warning is suppressed, so user code does not
observe a permanently wrapped emitWarning.
- test/utils.js: filesAfter() gains { tolerateWindowsEbusy } option that
only swallows EBUSY on win32 during cleanup.
- test/test-85..92: drop copy-pasted try/catch noop around filesAfter and
use the new option. test-91/92 also switch from inlined spawn+CRLF
logic to the shared assertSeaOutput helper.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent 95f4f63 commit daf76c5
68 files changed
Lines changed: 12962 additions & 1260 deletions
File tree
- .claude
- rules
- skills/performances-compare
- .github/workflows
- docs
- lib
- plans
- prelude
- scripts
- test
- test-00-sea
- test-85-sea-enhanced
- lib
- test-86-sea-assets
- test-87-sea-esm
- app
- lib
- test-89-sea-fs-ops
- test-90-sea-worker-threads
- lib
- test-91-sea-esm-entry
- app
- lib
- test-92-sea-tla
- app
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
0 commit comments