Skip to content

Maintenance: give the 4.x branch its CI, its version and its row in the README - #3291

Merged
lahma merged 1 commit into
sebastienros:4.xfrom
lahma:maint/4.x-branch-housekeeping
Aug 23, 2026
Merged

lahma merged 1 commit into
sebastienros:4.xfrom
lahma:maint/4.x-branch-housekeeping

Conversation

@lahma

@lahma lahma commented Aug 23, 2026 •

Copy link
Copy Markdown
Collaborator

The 4.x branch was just cut at e73c0ab92 ("Warm the stack-guard recovery test before it measures depth", #3080) so that main can become 5.x development. This PR is the housekeeping the branch needs in order to behave like a maintenance branch.

Why that commit is the branch point

e73c0ab92 is the last commit before two things that change what a default engine is, and therefore belong to a major version rather than to a patch line:

What is in here

  • .github/workflows/build.yml — the push trigger filtered on [ main, 3.x ], so a push to 4.x built nothing and published no preview package. 4.x joins the list. pr.yml needs no change: it deliberately carries no branches: filter (a base-branch filter used to skip CI on every layer of a stacked PR except the bottom one), so a pull request based on 4.x already gets the full matrix.
  • Directory.Build.props — VersionPrefix moves to 4.16.1. This numbers the MyGet preview stream coming off the branch; it is not what a release carries. release.yml derives the released version from the pushed vX.Y.Z tag and passes it to dotnet pack, so the tag remains the single source of truth.
  • README.md — the "Branches and releases" section described main alone, which was accurate while main was the only branch anyone was asked to target. It now has a row per live branch (main = 5.x development, 4.x = 4.16.x maintenance, 3.x = the Esprima-era line) and says how a release is actually cut.

What is deliberately left out

  • The AGENTS.md split (Docs: split AGENTS.md so it stops being silently truncated #3284). main recently broke its single AGENTS.md into a root index plus co-located files. The maintenance branch keeps its single pre-split AGENTS.md on purpose: backporting the reorganisation would make every future cherry-pick from main conflict on documentation layout, for no benefit to a branch that only receives fixes.
  • Any code change. The conformance and correctness backports for 4.16.1 are a separate PR onto this same branch.

Note on the README: #3294 landed the same "Branches and releases" table on main while this was open, so the two branches now carry identical wording (minus main's pointer to docs/v5-migration.md, which does not exist here). That is deliberate — a reader should get the same answer whichever branch they are looking at.

Verified with dotnet build -c Release on the solution: 0 errors.

🤖 Generated with Claude Code

https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S

…he README

The 4.x branch exists now, cut at the last commit before the opt-in Web API
foundation and the security-defaults stack — both of which change what a default
engine is and therefore belong to 5.x, not to a maintenance line. Three pieces of
housekeeping follow from the branch existing at all.

`build.yml` filtered its push trigger to `[ main, 3.x ]`, so a push to 4.x built
nothing and published no preview package. 4.x joins the list. `pr.yml` needs no
change: it deliberately carries no `branches:` filter, so a pull request based on
4.x already gets the full matrix.

`VersionPrefix` moves to 4.16.1, which is what the MyGet preview stream coming off
this branch should be numbered. It is not what a release will carry — `release.yml`
derives that from the pushed `vX.Y.Z` tag and passes it to `dotnet pack`, so the
property only ever names the preview feed's version.

The README's "Branches and releases" section described `main` alone, which was true
when `main` was the only branch anyone was asked to target. It now says what each of
the three live branches is for and how a release is actually cut.

What is deliberately *not* here: the AGENTS.md split (sebastienros#3284). The maintenance branch
keeps its single pre-split AGENTS.md, so a backport cherry-picked from main never
conflicts on documentation layout.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S
@lahma
lahma merged commit cc98b80 into sebastienros:4.x Aug 23, 2026
5 checks passed
lahma added a commit to lahma/jint that referenced this pull request Aug 23, 2026
…lly has

Main has moved 181 commits past v4.16.0 and nothing records what an embedder
has to react to. Most of it is invisible to a compiler: every entry below still
compiles exactly as it did in 4.16 and behaves differently at run time, and six
of them flip a default.

`docs/v5-migration.md` is the artefact those entries go in. It is deliberately
not a second README: a table per change, before/after code where it helps, and
the rationale left in the pull request it cites.

Seeded from git history, every claim checked against the tree rather than
against the pull request title:

  * sebastienros#3054 `Interop.AllowWrite` true -> false. A projected CLR write is now
    silently ignored in sloppy mode and a TypeError in strict mode.
  * sebastienros#3056 `Interop.ArrayConversion` LiveView -> Copy. `Array.isArray` flips to
    true, `push`/`length` stop throwing, and CLR-side mutations after the
    crossing stop being visible.
  * sebastienros#3057 `Constraints.StackOverflowGuard` false -> true. RangeError instead of
    a process that ends with no exception in the log.
  * sebastienros#3058 `AgentCanSuspend` true -> false. `Atomics.wait` is a TypeError before
    a waiter is registered; `waitAsync` is untouched.
  * sebastienros#3052 namespace type discovery loses its implicit fallback to
    `Assembly.GetCallingAssembly()` / `GetExecutingAssembly()` /
    `Type.GetType(name)` and becomes the `AllowedAssemblies` allow-list.
  * sebastienros#3051 host exception, module-load and CLR-resolution messages are redacted
    from script; `ExposeDetailedErrors()` restores all three.
  * sebastienros#3035 concurrent `Engine` use fails fast, and an engine stays reserved for
    the lifetime of a returned async Task.
  * sebastienros#3036 `LimitMemory` charges allocations across async continuations, so a
    budget can now trip where one synchronous segment never reached it.
  * sebastienros#3252 every `*Async` entry reports the operation's failures through the
    task and only a usage error out of the call.
  * sebastienros#3248 an array-like `length` above 2^32-1 stops answering differently per
    target framework.
  * sebastienros#3037, sebastienros#3045, sebastienros#3046 add parser, module-graph and result bounds that all
    default to unlimited, so they change nothing until configured; sebastienros#3059 and
    sebastienros#3060 add the diagnostics and the hardened profile on top.

Two entries the prompt for this work had slightly differently, both checked and
written as the tree has them: the stack-overflow guard raises a catchable
`RangeError`, not a `RecursionDepthOverflowException`, and `ArrayOperations` is
internal, so sebastienros#3248 removes no public member — its break is what a script sees.

Sections 2, 3 and 6 (removed API, renamed API, AOT) are explicit empty
placeholders. Nothing public has been removed or renamed since v4.16.0, and a
parallel task is measuring the AOT state.

The target-framework section is written and marked pending: `Jint.csproj` still
lists net462, and the net472 change is not on main yet.

`Jint/AGENTS.md` gains the rule that makes the guide stay current — a change to
anything in its public-contract table is a row in the guide, in the same pull
request, including a change that breaks nothing at compile time. The root
`AGENTS.md` is untouched; it is at 23 KB against a 24 KiB budget.

README's "Branches and releases" described `main` alone and did not mention the
`3.x` branch at all. It now has a row per live branch, in the same wording
sebastienros#3291 gives the 4.x branch's own copy, plus a pointer to the guide.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S
lahma added a commit to lahma/jint that referenced this pull request Aug 23, 2026
…cting reality

sebastienros#3291 added `4.x` to the filter on the `4.x` branch, which is what actually governs a push there —
GitHub runs a push workflow from the file on the pushed ref, so `4.x` builds and publishes with or
without this line. `main`'s copy going on saying `[ main, 3.x ]` therefore changes nothing, and is
simply false: a reader of main's workflow would conclude the maintenance line is not built.

Keeping the two in agreement also removes a conflict every future backport that touches this file
would otherwise hit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S
lahma added a commit that referenced this pull request Aug 23, 2026
…lly has (#3294)

Main has moved 181 commits past v4.16.0 and nothing records what an embedder
has to react to. Most of it is invisible to a compiler: every entry below still
compiles exactly as it did in 4.16 and behaves differently at run time, and six
of them flip a default.

`docs/v5-migration.md` is the artefact those entries go in. It is deliberately
not a second README: a table per change, before/after code where it helps, and
the rationale left in the pull request it cites.

Seeded from git history, every claim checked against the tree rather than
against the pull request title:

  * #3054 `Interop.AllowWrite` true -> false. A projected CLR write is now
    silently ignored in sloppy mode and a TypeError in strict mode.
  * #3056 `Interop.ArrayConversion` LiveView -> Copy. `Array.isArray` flips to
    true, `push`/`length` stop throwing, and CLR-side mutations after the
    crossing stop being visible.
  * #3057 `Constraints.StackOverflowGuard` false -> true. RangeError instead of
    a process that ends with no exception in the log.
  * #3058 `AgentCanSuspend` true -> false. `Atomics.wait` is a TypeError before
    a waiter is registered; `waitAsync` is untouched.
  * #3052 namespace type discovery loses its implicit fallback to
    `Assembly.GetCallingAssembly()` / `GetExecutingAssembly()` /
    `Type.GetType(name)` and becomes the `AllowedAssemblies` allow-list.
  * #3051 host exception, module-load and CLR-resolution messages are redacted
    from script; `ExposeDetailedErrors()` restores all three.
  * #3035 concurrent `Engine` use fails fast, and an engine stays reserved for
    the lifetime of a returned async Task.
  * #3036 `LimitMemory` charges allocations across async continuations, so a
    budget can now trip where one synchronous segment never reached it.
  * #3252 every `*Async` entry reports the operation's failures through the
    task and only a usage error out of the call.
  * #3248 an array-like `length` above 2^32-1 stops answering differently per
    target framework.
  * #3037, #3045, #3046 add parser, module-graph and result bounds that all
    default to unlimited, so they change nothing until configured; #3059 and
    #3060 add the diagnostics and the hardened profile on top.

Two entries the prompt for this work had slightly differently, both checked and
written as the tree has them: the stack-overflow guard raises a catchable
`RangeError`, not a `RecursionDepthOverflowException`, and `ArrayOperations` is
internal, so #3248 removes no public member — its break is what a script sees.

Sections 2, 3 and 6 (removed API, renamed API, AOT) are explicit empty
placeholders. Nothing public has been removed or renamed since v4.16.0, and a
parallel task is measuring the AOT state.

The target-framework section is written and marked pending: `Jint.csproj` still
lists net462, and the net472 change is not on main yet.

`Jint/AGENTS.md` gains the rule that makes the guide stay current — a change to
anything in its public-contract table is a row in the guide, in the same pull
request, including a change that breaks nothing at compile time. The root
`AGENTS.md` is untouched; it is at 23 KB against a 24 KiB budget.

README's "Branches and releases" described `main` alone and did not mention the
`3.x` branch at all. It now has a row per live branch, in the same wording
#3291 gives the 4.x branch's own copy, plus a pointer to the guide.


Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
lahma added a commit that referenced this pull request Aug 23, 2026
…lter (#3292)

* Version: main develops 5.0.0, so its MyGet previews stop being outranked by 4.x

`Directory.Build.props` still carried `VersionPrefix` 4.16.0 on `main`, which was harmless while
`main` was the only branch `build.yml` published from. It stops being harmless the moment the `4.x`
maintenance branch joins that filter: `build.yml` packs every push with
`-p:VersionSuffix=preview-$GITHUB_RUN_NUMBER` and pushes it to MyGet, so `4.x` would publish
`4.16.1-preview-N` against `main`'s `4.16.0-preview-N`. SemVer orders those the wrong way round —
4.16.1-preview-5 sorts above 4.16.0-preview-9 — and anyone tracking the prerelease feed to follow
5.x development would silently be handed the maintenance build instead.

`main` is 5.x development, so it says so. The floor is only what the *prerelease* feed carries;
release versions are unaffected either way, because `release.yml` derives the package version from
the pushed `vX.Y.Z` tag and passes it explicitly, so `VersionPrefix` never reaches a released package.

Nothing asserts a version: the only `4.16.0` left in the tree is a prose reference in a
`DateTests` comment describing behaviour that changed, which is still accurate.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S

* Build: name 4.x in main's push filter too, so the file stops contradicting reality

#3291 added `4.x` to the filter on the `4.x` branch, which is what actually governs a push there —
GitHub runs a push workflow from the file on the pushed ref, so `4.x` builds and publishes with or
without this line. `main`'s copy going on saying `[ main, 3.x ]` therefore changes nothing, and is
simply false: a reader of main's workflow would conclude the maintenance line is not built.

Keeping the two in agreement also removes a conflict every future backport that touches this file
would otherwise hit.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014W5mbjGhyvgAS4pivXoc4S

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant