From c0ebf88feb4d02dd389240604903e1be2b46c14d Mon Sep 17 00:00:00 2001 From: pavlo45441 <141767996+pavlo45441@users.noreply.github.com> Date: Fri, 14 Aug 2026 03:54:07 +0300 Subject: [PATCH 1/3] fix: add Turbopack support for chunk discovery --- src/browser/BrowserFunc.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/browser/BrowserFunc.ts b/src/browser/BrowserFunc.ts index 2e5e7edd..673f9486 100644 --- a/src/browser/BrowserFunc.ts +++ b/src/browser/BrowserFunc.ts @@ -301,7 +301,7 @@ export default class BrowserFunc { try { const initialChunks = new Set() - const chunkRegex = /(?:\/_next\/)?(static\/chunks\/[\w\-./()]+?\.js)/g + const chunkRegex = /(?:\/_next\/)?(static\/(?:chunks|immutable|media)\/[\w\-./()]+?\.js)/g for (const html of htmls) { if (!html) continue for (const match of html.matchAll(chunkRegex)) { @@ -406,9 +406,10 @@ export default class BrowserFunc { return result } - private extractDynamicChunkPaths(js: string): string[] { +    private extractDynamicChunkPaths(js: string): string[] { const seen = new Set() + // Webpack builder const builder = /static\/chunks\/"\s*\+\s*\w+\s*\+\s*"([-.])"\s*\+\s*\{([\s\S]*?)\}\s*\[/g for (const match of js.matchAll(builder)) { const sep = match[1]! @@ -417,12 +418,16 @@ export default class BrowserFunc { } } - // If the builder shape changes, scan id:hash pairs globally - if (!seen.size) { - for (const [, id, hash] of js.matchAll(/\b(\d{2,6}):"([a-f0-9]{12,})"/g)) { - seen.add(`/_next/static/chunks/${id}-${hash}.js`) - seen.add(`/_next/static/chunks/${id}.${hash}.js`) - } + // Webpack fallback + for (const [, id, hash] of js.matchAll(/\b(\d{2,6}):"([a-f0-9]{12,})"/g)) { + seen.add(`/_next/static/chunks/${id}-${hash}.js`) + seen.add(`/_next/static/chunks/${id}.${hash}.js`) + } + + // NEW: Turbopack + const turbopackRegex = /"(static\/(?:immutable|chunks|media)\/[\w\-./()]+?\.js)"/g + for (const match of js.matchAll(turbopackRegex)) { + seen.add(`/_next/${match[1]}`) } return [...seen] From a8cfd1874997839924dd0e9d89c310cf39b35f41 Mon Sep 17 00:00:00 2001 From: pavlo45441 <141767996+pavlo45441@users.noreply.github.com> Date: Fri, 14 Aug 2026 03:54:36 +0300 Subject: [PATCH 2/3] fix: update Action ID extraction for Turbopack --- src/browser/ReactFunc.ts | 50 ++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/browser/ReactFunc.ts b/src/browser/ReactFunc.ts index e0eb8a6f..9ff9cb30 100644 --- a/src/browser/ReactFunc.ts +++ b/src/browser/ReactFunc.ts @@ -579,27 +579,40 @@ export default class ReactFunc { const HEX = '[a-f0-9]{40,64}' // Framework args that share the call shape but aren't the action name - const KNOWN_NON_NAMES = new Set(['callServer', 'findSourceMapURL', 'encodeFormAction']) + const KNOWN_NON_NAMES = new Set(['callServer', 'findSourceMapURL', 'encodeFormAction', 'default']) try { - // I hate this so much honestly - const callRegex = new RegExp(`createServerReference\\s*\\)?\\s*\\(\\s*"(${HEX})"([\\s\\S]{0,400}?)\\)`, 'g') + // Support for both formats: (createServerReference)(id) and createServerReference(id) + // The argument search window has been expanded to 800 characters for Turbopack + const createRegex = new RegExp(`createServerReference\\s*\\)?\\s*\\(\\s*"(${HEX})"([\\s\\S]{0,800}?)\\)`, 'g') + const registerRegex = new RegExp(`registerServerReference\\s*\\)?\\s*\\([^,]+,\\s*"(${HEX})"([\\s\\S]{0,800}?)\\)`, 'g') + const strLitRe = /"([A-Za-z_$][\w$]*)"/g - for (const m of jsText.matchAll(callRegex)) { - const id = m[1]! - const argsBlock = m[2] ?? '' - all.add(id) - - const candidates = [...argsBlock.matchAll(strLitRe)] - .map(x => x[1]!) - .filter(n => !KNOWN_NON_NAMES.has(n)) - if (candidates.length) byName[candidates[candidates.length - 1]!] = id + const processMatches = (matches: IterableIterator) => { + for (const m of matches) { + const id = m[1]! + const argsBlock = m[2] ?? '' + all.add(id) + + const candidates = [...argsBlock.matchAll(strLitRe)] + .map(x => x[1]!) + .filter(n => !KNOWN_NON_NAMES.has(n) && n.length > 3) + + if (candidates.length) { + byName[candidates[candidates.length - 1]!] = id + } + } } - // bare reference without a name arg, still record the id - const bareRegex = new RegExp(`createServerReference\\s*\\)?\\s*\\(\\s*"(${HEX})"`, 'g') - for (const m of jsText.matchAll(bareRegex)) all.add(m[1]!) + processMatches(jsText.matchAll(createRegex)) + processMatches(jsText.matchAll(registerRegex)) + + const bareCreateRegex = new RegExp(`createServerReference\\s*\\)?\\s*\\(\\s*"(${HEX})"`, 'g') + const bareRegisterRegex = new RegExp(`registerServerReference\\s*\\)?\\s*\\([^,]+,\\s*"(${HEX})"`, 'g') + + for (const m of jsText.matchAll(bareCreateRegex)) all.add(m[1]!) + for (const m of jsText.matchAll(bareRegisterRegex)) all.add(m[1]!) const actionIdRe = new RegExp(`\\$ACTION_ID_(${HEX})`, 'g') for (const m of jsText.matchAll(actionIdRe)) all.add(m[1]!) @@ -610,13 +623,6 @@ export default class ReactFunc { `Extracted action ids | named=${Object.keys(byName).length} | total=${all.size}` ) - if (all.size === 0) { - this.bot.logger.debug( - this.bot.isMobile, - 'REACT-PARSE', - 'No server-action ids found in JS chunk - wrong chunk, or bundler output changed' - ) - } } catch (error) { this.bot.logger.error( this.bot.isMobile, From 151ae2b89d78d3cd17974757d452e8346ee54eb5 Mon Sep 17 00:00:00 2001 From: pavlo45441 <141767996+pavlo45441@users.noreply.github.com> Date: Fri, 14 Aug 2026 04:01:35 +0300 Subject: [PATCH 3/3] fix: add Turbopack support for chunk discovery Removed unnecessary 'NEW:' comment from turbopack regex section. --- src/browser/BrowserFunc.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/browser/BrowserFunc.ts b/src/browser/BrowserFunc.ts index 673f9486..4af07c11 100644 --- a/src/browser/BrowserFunc.ts +++ b/src/browser/BrowserFunc.ts @@ -406,7 +406,7 @@ export default class BrowserFunc { return result } -    private extractDynamicChunkPaths(js: string): string[] { + private extractDynamicChunkPaths(js: string): string[] { const seen = new Set() // Webpack builder @@ -424,7 +424,7 @@ export default class BrowserFunc { seen.add(`/_next/static/chunks/${id}.${hash}.js`) } - // NEW: Turbopack + // Turbopack const turbopackRegex = /"(static\/(?:immutable|chunks|media)\/[\w\-./()]+?\.js)"/g for (const match of js.matchAll(turbopackRegex)) { seen.add(`/_next/${match[1]}`)