Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays - #2506

Merged
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable
Jun 19, 2026
Merged

Backport #2471: perf(core): cache compiled workflow-bundle vm.Script across replays#2506
pranaygp merged 1 commit into
stablefrom
backport/pr-2471-to-stable

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Automated backport of #2471 to stable (backport job run).

AI recommendation: This is a self-contained performance optimization that caches the compiled vm.Script for the workflow bundle in runWorkflow. The exact pre-change runInContext hot path it replaces exists identically on stable (packages/core/src/workflow.ts:699), and the new vm/script-cache.ts module has no dependency on any main-only APIs, so it should apply cleanly.

Merge conflicts were resolved by AI (opencode with anthropic/claude-opus-4.8). Please review the conflict resolution carefully before merging.

…2471)
* perf(core): cache compiled workflow-bundle vm.Script across replays
The inline replay loop calls runWorkflow on every iteration, and each call
re-parsed the entire workflow bundle string via vm.runInContext. For a bundle
containing many workflow definitions (the production shape: one workflow called
per replay), this re-scans every definition on every replay.
Cache the compiled vm.Script per process, keyed by (workflowCode, filename),
and run it against the fresh context instead of recompiling. Compilation is a
pure function of (code, filename), so the result is byte-identical to the
previous re-parse-every-time behaviour — determinism is preserved. filename is
part of the key because it drives source attribution in stack traces (consumed
by remapErrorStack).
Measured per-replay savings scale with bundle size (and multiply by replay
count): ~34% for a 50-workflow app, ~59% for 155 workflows, ~80% for 400.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* perf(core): bound script cache with LRU; soften determinism claim; add tests
Addresses review on #2471:
- Bound `scriptCache` to a small LRU (cap 8 bundle versions). Production
serves one bundle per process so the bound is never reached; it exists for
dev/watch mode, where each edit produces a new bundle string that would
otherwise be pinned forever (~0.8MB/edit, monotonic). Touch-on-access keeps
the latest bundle hot; evicting a `code` entry drops its per-filename scripts
together, restoring pre-cache GC behaviour.
- Document precisely why keying includes `filename` (intentional: drives
stack-trace attribution via `remapErrorStack`; NOT a dedupe key), and that
the whole bundle is compiled once per distinct filename.
- Soften the "byte-identical including thrown errors" claim to
same-workflow-function + same-`filename`-attribution, noting the one caveat:
a lookup-expression error's line number shifts to line 1 of the separate
lookup Script. Updated in both the code comment and the PR description.
- Add tests: cache-is-bounded regression (eviction past the cap), LRU recency
(hot bundle survives churn), and a realistic multi-workflow collision test
(distinct code/filename never returns the wrong Script, results carry their
own bundle marker).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
@changeset-bot

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 7d5a045

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 16 packages
NameType
@workflow/corePatch
@workflow/buildersPatch
@workflow/cliPatch
@workflow/nextPatch
@workflow/nitroPatch
@workflow/vitestPatch
@workflow/web-sharedPatch
@workflow/webPatch
workflowPatch
@workflow/world-testingPatch
@workflow/astroPatch
@workflow/nestPatch
@workflow/rollupPatch
@workflow/sveltekitPatch
@workflow/vitePatch
@workflow/nuxtPatch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@vercel

vercelBot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

@pranaygp
pranaygp merged commit 170ea96 into stableJun 19, 2026
21 checks passed
@pranaygp
pranaygp deleted the backport/pr-2471-to-stable branch June 19, 2026 16:18
Sign up for freeto 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

@pranaygp