@js-recon/js-recon 1.3.1-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.gitattributes +2 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- package/.github/ISSUE_TEMPLATE/new_tech_support_request.md +26 -0
- package/.github/workflows/build-and-prettify.yaml +121 -0
- package/.github/workflows/pr_checker.yml +22 -0
- package/.github/workflows/publish-js-recon.yml +169 -0
- package/.prettierignore +2 -0
- package/.prettierrc +6 -0
- package/CHANGELOG.md +692 -0
- package/CLAUDE.md +290 -0
- package/Dockerfile +34 -0
- package/LICENSE +21 -0
- package/README.md +101 -0
- package/SECURITY.md +37 -0
- package/build/analyze/engine/astEngine.js +224 -0
- package/build/analyze/engine/astEngine.js.map +1 -0
- package/build/analyze/engine/index.js +59 -0
- package/build/analyze/engine/index.js.map +1 -0
- package/build/analyze/engine/requestEngine.js +100 -0
- package/build/analyze/engine/requestEngine.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/findDirectAssignment.js +37 -0
- package/build/analyze/helpers/engineHelpers/findDirectAssignment.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js +29 -0
- package/build/analyze/helpers/engineHelpers/findMemberExpressionAssignment.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/resolveFunctionIdentifier.js +38 -0
- package/build/analyze/helpers/engineHelpers/resolveFunctionIdentifier.js.map +1 -0
- package/build/analyze/helpers/engineHelpers/taintFlow.js +250 -0
- package/build/analyze/helpers/engineHelpers/taintFlow.js.map +1 -0
- package/build/analyze/helpers/initRules.js +111 -0
- package/build/analyze/helpers/initRules.js.map +1 -0
- package/build/analyze/helpers/outputHelper.js +14 -0
- package/build/analyze/helpers/outputHelper.js.map +1 -0
- package/build/analyze/helpers/schemas.js +57 -0
- package/build/analyze/helpers/schemas.js.map +1 -0
- package/build/analyze/helpers/validate.js +89 -0
- package/build/analyze/helpers/validate.js.map +1 -0
- package/build/analyze/index.js +150 -0
- package/build/analyze/index.js.map +1 -0
- package/build/analyze/types/index.js +2 -0
- package/build/analyze/types/index.js.map +1 -0
- package/build/api_gateway/checkFeasibility.js +41 -0
- package/build/api_gateway/checkFeasibility.js.map +1 -0
- package/build/api_gateway/checkFireWallBlocking.js +33 -0
- package/build/api_gateway/checkFireWallBlocking.js.map +1 -0
- package/build/api_gateway/genReq.js +205 -0
- package/build/api_gateway/genReq.js.map +1 -0
- package/build/api_gateway/index.js +291 -0
- package/build/api_gateway/index.js.map +1 -0
- package/build/endpoints/gen_report/gen_json.js +30 -0
- package/build/endpoints/gen_report/gen_json.js.map +1 -0
- package/build/endpoints/gen_report/utility/iterate_n_store.js +64 -0
- package/build/endpoints/gen_report/utility/iterate_n_store.js.map +1 -0
- package/build/endpoints/index.js +101 -0
- package/build/endpoints/index.js.map +1 -0
- package/build/endpoints/next_js/client_jsFilesHref.js +100 -0
- package/build/endpoints/next_js/client_jsFilesHref.js.map +1 -0
- package/build/endpoints/next_js/client_jsonParse.js +89 -0
- package/build/endpoints/next_js/client_jsonParse.js.map +1 -0
- package/build/endpoints/next_js/client_mappedJsonFile.js +103 -0
- package/build/endpoints/next_js/client_mappedJsonFile.js.map +1 -0
- package/build/endpoints/next_js/client_subsequentRequests.js +211 -0
- package/build/endpoints/next_js/client_subsequentRequests.js.map +1 -0
- package/build/fingerprint/index.js +123 -0
- package/build/fingerprint/index.js.map +1 -0
- package/build/globalConfig.js +16 -0
- package/build/globalConfig.js.map +1 -0
- package/build/index.js +332 -0
- package/build/index.js.map +1 -0
- package/build/lazyLoad/angular/angular_getFromMainJs.js +55 -0
- package/build/lazyLoad/angular/angular_getFromMainJs.js.map +1 -0
- package/build/lazyLoad/angular/angular_getFromPageSource.js +43 -0
- package/build/lazyLoad/angular/angular_getFromPageSource.js.map +1 -0
- package/build/lazyLoad/downloadFilesUtil.js +127 -0
- package/build/lazyLoad/downloadFilesUtil.js.map +1 -0
- package/build/lazyLoad/downloadLoadedJsUtil.js +44 -0
- package/build/lazyLoad/downloadLoadedJsUtil.js.map +1 -0
- package/build/lazyLoad/downloadQueue.js +191 -0
- package/build/lazyLoad/downloadQueue.js.map +1 -0
- package/build/lazyLoad/globals.js +107 -0
- package/build/lazyLoad/globals.js.map +1 -0
- package/build/lazyLoad/index.js +377 -0
- package/build/lazyLoad/index.js.map +1 -0
- package/build/lazyLoad/next_js/NextJsCrawler.js +332 -0
- package/build/lazyLoad/next_js/NextJsCrawler.js.map +1 -0
- package/build/lazyLoad/next_js/next_GetJSScript.js +126 -0
- package/build/lazyLoad/next_js/next_GetJSScript.js.map +1 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js +83 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesBuildManifestJs.js.map +1 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js +222 -0
- package/build/lazyLoad/next_js/next_GetLazyResourcesWebpackJs.js.map +1 -0
- package/build/lazyLoad/next_js/next_SubsequentRequests.js +208 -0
- package/build/lazyLoad/next_js/next_SubsequentRequests.js.map +1 -0
- package/build/lazyLoad/next_js/next_bruteForceJsFiles.js +37 -0
- package/build/lazyLoad/next_js/next_bruteForceJsFiles.js.map +1 -0
- package/build/lazyLoad/next_js/next_buildId.js +55 -0
- package/build/lazyLoad/next_js/next_buildId.js.map +1 -0
- package/build/lazyLoad/next_js/next_getClientSidePaths.js +83 -0
- package/build/lazyLoad/next_js/next_getClientSidePaths.js.map +1 -0
- package/build/lazyLoad/next_js/next_globals.js +8 -0
- package/build/lazyLoad/next_js/next_globals.js.map +1 -0
- package/build/lazyLoad/next_js/next_parseLayoutJs.js +116 -0
- package/build/lazyLoad/next_js/next_parseLayoutJs.js.map +1 -0
- package/build/lazyLoad/next_js/next_promiseResolve.js +85 -0
- package/build/lazyLoad/next_js/next_promiseResolve.js.map +1 -0
- package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js +51 -0
- package/build/lazyLoad/next_js/next_scriptTagsSubsequentRequests.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_astParse.js +202 -0
- package/build/lazyLoad/nuxt_js/nuxt_astParse.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js +82 -0
- package/build/lazyLoad/nuxt_js/nuxt_getFromPageSource.js.map +1 -0
- package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js +108 -0
- package/build/lazyLoad/nuxt_js/nuxt_stringAnalysisJSFiles.js.map +1 -0
- package/build/lazyLoad/react/react_followImports.js +105 -0
- package/build/lazyLoad/react/react_followImports.js.map +1 -0
- package/build/lazyLoad/react/react_getScriptTags.js +52 -0
- package/build/lazyLoad/react/react_getScriptTags.js.map +1 -0
- package/build/lazyLoad/react/react_sourcemapUrls.js +44 -0
- package/build/lazyLoad/react/react_sourcemapUrls.js.map +1 -0
- package/build/lazyLoad/react/react_webpackChunkPaths.js +188 -0
- package/build/lazyLoad/react/react_webpackChunkPaths.js.map +1 -0
- package/build/lazyLoad/sourcemap.js +188 -0
- package/build/lazyLoad/sourcemap.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js +162 -0
- package/build/lazyLoad/svelte/svelte_discoverPagesFromJs.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_getFromPageSource.js +91 -0
- package/build/lazyLoad/svelte/svelte_getFromPageSource.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js +180 -0
- package/build/lazyLoad/svelte/svelte_recursivePageCrawl.js.map +1 -0
- package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js +123 -0
- package/build/lazyLoad/svelte/svelte_stringAnalysisJSFiles.js.map +1 -0
- package/build/lazyLoad/techDetect/checkAngularJS.js +70 -0
- package/build/lazyLoad/techDetect/checkAngularJS.js.map +1 -0
- package/build/lazyLoad/techDetect/checkNextJS.js +45 -0
- package/build/lazyLoad/techDetect/checkNextJS.js.map +1 -0
- package/build/lazyLoad/techDetect/checkNuxtJS.js +39 -0
- package/build/lazyLoad/techDetect/checkNuxtJS.js.map +1 -0
- package/build/lazyLoad/techDetect/checkReact.js +86 -0
- package/build/lazyLoad/techDetect/checkReact.js.map +1 -0
- package/build/lazyLoad/techDetect/checkSvelte.js +69 -0
- package/build/lazyLoad/techDetect/checkSvelte.js.map +1 -0
- package/build/lazyLoad/techDetect/checkVueJS.js +118 -0
- package/build/lazyLoad/techDetect/checkVueJS.js.map +1 -0
- package/build/lazyLoad/techDetect/index.js +161 -0
- package/build/lazyLoad/techDetect/index.js.map +1 -0
- package/build/lazyLoad/vue/vue_RuntimeJs.js +169 -0
- package/build/lazyLoad/vue/vue_RuntimeJs.js.map +1 -0
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js +102 -0
- package/build/lazyLoad/vue/vue_SingleJsFileOnHome.js.map +1 -0
- package/build/lazyLoad/vue/vue_discoverJsFiles.js +82 -0
- package/build/lazyLoad/vue/vue_discoverJsFiles.js.map +1 -0
- package/build/lazyLoad/vue/vue_getClientSidePaths.js +155 -0
- package/build/lazyLoad/vue/vue_getClientSidePaths.js.map +1 -0
- package/build/lazyLoad/vue/vue_jsImports.js +76 -0
- package/build/lazyLoad/vue/vue_jsImports.js.map +1 -0
- package/build/lazyLoad/vue/vue_pageSrc.js +60 -0
- package/build/lazyLoad/vue/vue_pageSrc.js.map +1 -0
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js +64 -0
- package/build/lazyLoad/vue/vue_reconstructSourceMaps.js.map +1 -0
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js +142 -0
- package/build/lazyLoad/vue/vue_recursiveClientSidePathDownload.js.map +1 -0
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js +57 -0
- package/build/lazyLoad/vue/vue_severalJsFilesHome.js.map +1 -0
- package/build/lazyLoad/vue/vue_sourcemapExtract.js +166 -0
- package/build/lazyLoad/vue/vue_sourcemapExtract.js.map +1 -0
- package/build/lazyLoad/vue/vue_stringJsFiles.js +148 -0
- package/build/lazyLoad/vue/vue_stringJsFiles.js.map +1 -0
- package/build/lazyLoad/vue/vue_viteMapDeps.js +89 -0
- package/build/lazyLoad/vue/vue_viteMapDeps.js.map +1 -0
- package/build/load/index.js +316 -0
- package/build/load/index.js.map +1 -0
- package/build/map/graphql/resolveGraphql.js +296 -0
- package/build/map/graphql/resolveGraphql.js.map +1 -0
- package/build/map/index.js +261 -0
- package/build/map/index.js.map +1 -0
- package/build/map/next_js/getAxiosInstances.js +64 -0
- package/build/map/next_js/getAxiosInstances.js.map +1 -0
- package/build/map/next_js/getExports.js +101 -0
- package/build/map/next_js/getExports.js.map +1 -0
- package/build/map/next_js/getFetchInstances.js +139 -0
- package/build/map/next_js/getFetchInstances.js.map +1 -0
- package/build/map/next_js/getTurbopackConnections.js +255 -0
- package/build/map/next_js/getTurbopackConnections.js.map +1 -0
- package/build/map/next_js/getWebpackConnections.js +235 -0
- package/build/map/next_js/getWebpackConnections.js.map +1 -0
- package/build/map/next_js/interactive.js +69 -0
- package/build/map/next_js/interactive.js.map +1 -0
- package/build/map/next_js/interactive_helpers/commandHandler.js +310 -0
- package/build/map/next_js/interactive_helpers/commandHandler.js.map +1 -0
- package/build/map/next_js/interactive_helpers/commandHelpers.js +245 -0
- package/build/map/next_js/interactive_helpers/commandHelpers.js.map +1 -0
- package/build/map/next_js/interactive_helpers/esqueryGen.js +370 -0
- package/build/map/next_js/interactive_helpers/esqueryGen.js.map +1 -0
- package/build/map/next_js/interactive_helpers/helpMenu.js +12 -0
- package/build/map/next_js/interactive_helpers/helpMenu.js.map +1 -0
- package/build/map/next_js/interactive_helpers/inputPatch.js +207 -0
- package/build/map/next_js/interactive_helpers/inputPatch.js.map +1 -0
- package/build/map/next_js/interactive_helpers/keybindings.js +90 -0
- package/build/map/next_js/interactive_helpers/keybindings.js.map +1 -0
- package/build/map/next_js/interactive_helpers/printer.js +23 -0
- package/build/map/next_js/interactive_helpers/printer.js.map +1 -0
- package/build/map/next_js/interactive_helpers/ui.js +88 -0
- package/build/map/next_js/interactive_helpers/ui.js.map +1 -0
- package/build/map/next_js/resolveAxios.js +152 -0
- package/build/map/next_js/resolveAxios.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/astNodeToJsonString.js +64 -0
- package/build/map/next_js/resolveAxiosHelpers/astNodeToJsonString.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/directCallsWithoutAssignment.js +48 -0
- package/build/map/next_js/resolveAxiosHelpers/directCallsWithoutAssignment.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js +34 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosClients.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js +39 -0
- package/build/map/next_js/resolveAxiosHelpers/findAxiosInstance.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js +312 -0
- package/build/map/next_js/resolveAxiosHelpers/findCrossChunkParams.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js +173 -0
- package/build/map/next_js/resolveAxiosHelpers/handleAxiosCreate.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js +261 -0
- package/build/map/next_js/resolveAxiosHelpers/handleZDotCreate.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/interceptorHeaders.js +206 -0
- package/build/map/next_js/resolveAxiosHelpers/interceptorHeaders.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js +168 -0
- package/build/map/next_js/resolveAxiosHelpers/processAxiosCall.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js +121 -0
- package/build/map/next_js/resolveAxiosHelpers/processDirectAxiosCall.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js +274 -0
- package/build/map/next_js/resolveAxiosHelpers/processExportedEndpoints.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js +518 -0
- package/build/map/next_js/resolveAxiosHelpers/traceAxiosInstanceExports.js.map +1 -0
- package/build/map/next_js/resolveAxiosHelpers/traceBody.js +913 -0
- package/build/map/next_js/resolveAxiosHelpers/traceBody.js.map +1 -0
- package/build/map/next_js/resolveFetch.js +533 -0
- package/build/map/next_js/resolveFetch.js.map +1 -0
- package/build/map/next_js/resolveNewRequest.js +749 -0
- package/build/map/next_js/resolveNewRequest.js.map +1 -0
- package/build/map/next_js/resolveServerActions.js +449 -0
- package/build/map/next_js/resolveServerActions.js.map +1 -0
- package/build/map/next_js/utils.js +1600 -0
- package/build/map/next_js/utils.js.map +1 -0
- package/build/map/react_js/getReactConnections.js +303 -0
- package/build/map/react_js/getReactConnections.js.map +1 -0
- package/build/map/react_js/interactive.js +4 -0
- package/build/map/react_js/interactive.js.map +1 -0
- package/build/map/react_js/react_resolveFetch.js +6 -0
- package/build/map/react_js/react_resolveFetch.js.map +1 -0
- package/build/map/svelte_js/interactive.js +58 -0
- package/build/map/svelte_js/interactive.js.map +1 -0
- package/build/map/svelte_js/interactive_helpers/commandHandler.js +4 -0
- package/build/map/svelte_js/interactive_helpers/commandHandler.js.map +1 -0
- package/build/map/vue_js/bodyResolver.js +477 -0
- package/build/map/vue_js/bodyResolver.js.map +1 -0
- package/build/map/vue_js/crossFileResolver.js +438 -0
- package/build/map/vue_js/crossFileResolver.js.map +1 -0
- package/build/map/vue_js/getViteConnections.js +343 -0
- package/build/map/vue_js/getViteConnections.js.map +1 -0
- package/build/map/vue_js/interactive.js +67 -0
- package/build/map/vue_js/interactive.js.map +1 -0
- package/build/map/vue_js/interactive_helpers/commandHandler.js +307 -0
- package/build/map/vue_js/interactive_helpers/commandHandler.js.map +1 -0
- package/build/map/vue_js/interactive_helpers/commandHelpers.js +39 -0
- package/build/map/vue_js/interactive_helpers/commandHelpers.js.map +1 -0
- package/build/map/vue_js/interactive_helpers/helpMenu.js +12 -0
- package/build/map/vue_js/interactive_helpers/helpMenu.js.map +1 -0
- package/build/map/vue_js/taint_utils.js +621 -0
- package/build/map/vue_js/taint_utils.js.map +1 -0
- package/build/map/vue_js/vue_resolveFetch.js +416 -0
- package/build/map/vue_js/vue_resolveFetch.js.map +1 -0
- package/build/map/vue_js/vue_resolveHttpClient.js +738 -0
- package/build/map/vue_js/vue_resolveHttpClient.js.map +1 -0
- package/build/map/vue_js/vue_resolveXhr.js +282 -0
- package/build/map/vue_js/vue_resolveXhr.js.map +1 -0
- package/build/mcp/chatOneShot.js +101 -0
- package/build/mcp/chatOneShot.js.map +1 -0
- package/build/mcp/claudeCodeCreds.js +150 -0
- package/build/mcp/claudeCodeCreds.js.map +1 -0
- package/build/mcp/cli.js +372 -0
- package/build/mcp/cli.js.map +1 -0
- package/build/mcp/commands.js +227 -0
- package/build/mcp/commands.js.map +1 -0
- package/build/mcp/config.js +68 -0
- package/build/mcp/config.js.map +1 -0
- package/build/mcp/index.js +50 -0
- package/build/mcp/index.js.map +1 -0
- package/build/mcp/intent.js +204 -0
- package/build/mcp/intent.js.map +1 -0
- package/build/mcp/jobs.js +199 -0
- package/build/mcp/jobs.js.map +1 -0
- package/build/mcp/mcpServer.js +241 -0
- package/build/mcp/mcpServer.js.map +1 -0
- package/build/mcp/providers.js +170 -0
- package/build/mcp/providers.js.map +1 -0
- package/build/mcp/skills.js +115 -0
- package/build/mcp/skills.js.map +1 -0
- package/build/mcp/tools.js +185 -0
- package/build/mcp/tools.js.map +1 -0
- package/build/refactor/index.js +85 -0
- package/build/refactor/index.js.map +1 -0
- package/build/refactor/next/index.js +109 -0
- package/build/refactor/next/index.js.map +1 -0
- package/build/refactor/react/index.js +636 -0
- package/build/refactor/react/index.js.map +1 -0
- package/build/report/index.js +68 -0
- package/build/report/index.js.map +1 -0
- package/build/report/utility/dataTables/genDataTablesPage.js +158 -0
- package/build/report/utility/dataTables/genDataTablesPage.js.map +1 -0
- package/build/report/utility/genHtml.js +516 -0
- package/build/report/utility/genHtml.js.map +1 -0
- package/build/report/utility/initReportDb.js +96 -0
- package/build/report/utility/initReportDb.js.map +1 -0
- package/build/report/utility/markdownGen/addAnalyze.js +53 -0
- package/build/report/utility/markdownGen/addAnalyze.js.map +1 -0
- package/build/report/utility/markdownGen/addMappedJson.js +33 -0
- package/build/report/utility/markdownGen/addMappedJson.js.map +1 -0
- package/build/report/utility/populateDb/populateAnalysisFindings.js +31 -0
- package/build/report/utility/populateDb/populateAnalysisFindings.js.map +1 -0
- package/build/report/utility/populateDb/populateEndpoints.js +50 -0
- package/build/report/utility/populateDb/populateEndpoints.js.map +1 -0
- package/build/report/utility/populateDb/populateMappedJson.js +31 -0
- package/build/report/utility/populateDb/populateMappedJson.js.map +1 -0
- package/build/report/utility/populateDb/populateMappedOpenapi.js +49 -0
- package/build/report/utility/populateDb/populateMappedOpenapi.js.map +1 -0
- package/build/run/index.js +446 -0
- package/build/run/index.js.map +1 -0
- package/build/run/interruptHandler.js +93 -0
- package/build/run/interruptHandler.js.map +1 -0
- package/build/strings/index.js +239 -0
- package/build/strings/index.js.map +1 -0
- package/build/strings/openapi.js +63 -0
- package/build/strings/openapi.js.map +1 -0
- package/build/strings/permutate.js +62 -0
- package/build/strings/permutate.js.map +1 -0
- package/build/strings/secrets.js +102 -0
- package/build/strings/secrets.js.map +1 -0
- package/build/utility/ai.js +97 -0
- package/build/utility/ai.js.map +1 -0
- package/build/utility/configureSandbox.js +14 -0
- package/build/utility/configureSandbox.js.map +1 -0
- package/build/utility/globals.js +322 -0
- package/build/utility/globals.js.map +1 -0
- package/build/utility/interfaces.js +2 -0
- package/build/utility/interfaces.js.map +1 -0
- package/build/utility/makeReq.js +448 -0
- package/build/utility/makeReq.js.map +1 -0
- package/build/utility/openapiGenerator.js +254 -0
- package/build/utility/openapiGenerator.js.map +1 -0
- package/build/utility/postmanGenerator.js +216 -0
- package/build/utility/postmanGenerator.js.map +1 -0
- package/build/utility/progressLog.js +50 -0
- package/build/utility/progressLog.js.map +1 -0
- package/build/utility/puppeteerInstance.js +5 -0
- package/build/utility/puppeteerInstance.js.map +1 -0
- package/build/utility/replaceUrlPlaceholders.js +48 -0
- package/build/utility/replaceUrlPlaceholders.js.map +1 -0
- package/build/utility/resolvePath.js +44 -0
- package/build/utility/resolvePath.js.map +1 -0
- package/build/utility/runSandboxed.js +42 -0
- package/build/utility/runSandboxed.js.map +1 -0
- package/build/utility/urlUtils.js +21 -0
- package/build/utility/urlUtils.js.map +1 -0
- package/contributing/nextjs.md +410 -0
- package/package.json +75 -0
|
@@ -0,0 +1,1600 @@
|
|
|
1
|
+
import parser from "@babel/parser";
|
|
2
|
+
import _traverse from "@babel/traverse";
|
|
3
|
+
const traverse = _traverse.default;
|
|
4
|
+
/**
|
|
5
|
+
* Builds a dotted identifier path from a chain of MemberExpression nodes
|
|
6
|
+
* rooted at an Identifier. Returns null when the chain contains computed
|
|
7
|
+
* properties, non-Identifier nodes, or anything we can't render as `a.b.c`.
|
|
8
|
+
*/
|
|
9
|
+
export const memberChainToString = (node) => {
|
|
10
|
+
var _a;
|
|
11
|
+
if (!node)
|
|
12
|
+
return null;
|
|
13
|
+
if (node.type === "Identifier")
|
|
14
|
+
return node.name;
|
|
15
|
+
if (node.type === "MemberExpression" && !node.computed && ((_a = node.property) === null || _a === void 0 ? void 0 : _a.type) === "Identifier") {
|
|
16
|
+
const obj = memberChainToString(node.object);
|
|
17
|
+
if (!obj)
|
|
18
|
+
return null;
|
|
19
|
+
return `${obj}.${node.property.name}`;
|
|
20
|
+
}
|
|
21
|
+
return null;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Produces a short human-readable label for a spread argument we couldn't fully
|
|
25
|
+
* resolve. Identifiers keep their name; member chains collapse into `a.b.c`;
|
|
26
|
+
* call expressions show their callee name with `()`. Anything else falls back
|
|
27
|
+
* to the AST node type so the placeholder still signals *something* was there.
|
|
28
|
+
*/
|
|
29
|
+
const describeSpreadArg = (arg) => {
|
|
30
|
+
var _a, _b, _c, _d;
|
|
31
|
+
if (!arg)
|
|
32
|
+
return "unknown";
|
|
33
|
+
if (arg.type === "Identifier")
|
|
34
|
+
return arg.name;
|
|
35
|
+
if (arg.type === "MemberExpression") {
|
|
36
|
+
const parts = [];
|
|
37
|
+
let walker = arg;
|
|
38
|
+
while (walker &&
|
|
39
|
+
walker.type === "MemberExpression" &&
|
|
40
|
+
!walker.computed &&
|
|
41
|
+
((_a = walker.property) === null || _a === void 0 ? void 0 : _a.type) === "Identifier") {
|
|
42
|
+
parts.unshift(walker.property.name);
|
|
43
|
+
walker = walker.object;
|
|
44
|
+
}
|
|
45
|
+
if (walker && walker.type === "Identifier")
|
|
46
|
+
parts.unshift(walker.name);
|
|
47
|
+
if (parts.length > 0)
|
|
48
|
+
return parts.join(".");
|
|
49
|
+
return "member";
|
|
50
|
+
}
|
|
51
|
+
if (arg.type === "CallExpression") {
|
|
52
|
+
if (((_b = arg.callee) === null || _b === void 0 ? void 0 : _b.type) === "Identifier")
|
|
53
|
+
return `${arg.callee.name}()`;
|
|
54
|
+
if (((_c = arg.callee) === null || _c === void 0 ? void 0 : _c.type) === "MemberExpression" && ((_d = arg.callee.property) === null || _d === void 0 ? void 0 : _d.type) === "Identifier") {
|
|
55
|
+
return `${arg.callee.property.name}()`;
|
|
56
|
+
}
|
|
57
|
+
return "call()";
|
|
58
|
+
}
|
|
59
|
+
return arg.type;
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Resolves a variable in a chunk by finding its declaration/assignment.
|
|
63
|
+
*
|
|
64
|
+
* @param varName - The name of the variable to resolve
|
|
65
|
+
* @param chunkCode - The source code of the chunk
|
|
66
|
+
* @param depth - Current recursion depth to prevent infinite loops
|
|
67
|
+
* @returns The resolved value or a placeholder if unresolved
|
|
68
|
+
*/
|
|
69
|
+
/**
|
|
70
|
+
* Returns true if the given path is nested inside a loop statement.
|
|
71
|
+
* Used to skip loop-internal variable assignments that would shadow the
|
|
72
|
+
* top-level declaration we are interested in.
|
|
73
|
+
*/
|
|
74
|
+
const isInsideLoop = (p) => {
|
|
75
|
+
let current = p.parentPath;
|
|
76
|
+
while (current) {
|
|
77
|
+
if (current.isForStatement() ||
|
|
78
|
+
current.isForInStatement() ||
|
|
79
|
+
current.isForOfStatement() ||
|
|
80
|
+
current.isWhileStatement() ||
|
|
81
|
+
current.isDoWhileStatement()) {
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
// Don't cross function boundaries
|
|
85
|
+
if (current.isFunction())
|
|
86
|
+
break;
|
|
87
|
+
current = current.parentPath;
|
|
88
|
+
}
|
|
89
|
+
return false;
|
|
90
|
+
};
|
|
91
|
+
export const resolveVariableInChunk = (varName, chunkCode, depth = 0) => {
|
|
92
|
+
if (depth > 5) {
|
|
93
|
+
return `[max recursion depth for ${varName}]`;
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
const ast = parser.parse(chunkCode, {
|
|
97
|
+
sourceType: "module",
|
|
98
|
+
plugins: ["jsx", "typescript"],
|
|
99
|
+
errorRecovery: true,
|
|
100
|
+
});
|
|
101
|
+
let resolvedValue = null;
|
|
102
|
+
traverse(ast, {
|
|
103
|
+
// Find variable declarations: let/const/var varName = ...
|
|
104
|
+
VariableDeclarator(path) {
|
|
105
|
+
// Skip declarations that are inside loops — they are loop counters or
|
|
106
|
+
// temporaries and would shadow the top-level variable we care about.
|
|
107
|
+
if (isInsideLoop(path))
|
|
108
|
+
return;
|
|
109
|
+
if (path.node.id.type === "Identifier" && path.node.id.name === varName && path.node.init) {
|
|
110
|
+
const init = path.node.init;
|
|
111
|
+
if (init.type === "StringLiteral") {
|
|
112
|
+
resolvedValue = init.value;
|
|
113
|
+
path.stop();
|
|
114
|
+
}
|
|
115
|
+
else if (init.type === "NumericLiteral") {
|
|
116
|
+
resolvedValue = String(init.value);
|
|
117
|
+
path.stop();
|
|
118
|
+
}
|
|
119
|
+
else if (init.type === "TemplateLiteral") {
|
|
120
|
+
// Handle template literals
|
|
121
|
+
let result = "";
|
|
122
|
+
for (let i = 0; i < init.quasis.length; i++) {
|
|
123
|
+
result += init.quasis[i].value.raw;
|
|
124
|
+
if (i < init.expressions.length) {
|
|
125
|
+
const expr = init.expressions[i];
|
|
126
|
+
if (expr.type === "Identifier") {
|
|
127
|
+
// Recursively resolve nested variables
|
|
128
|
+
const nestedValue = resolveVariableInChunk(expr.name, chunkCode, depth + 1);
|
|
129
|
+
result += nestedValue;
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
result += `[${expr.type}]`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
resolvedValue = result;
|
|
137
|
+
path.stop();
|
|
138
|
+
}
|
|
139
|
+
else if (init.type === "Identifier") {
|
|
140
|
+
// Recursively resolve if it references another variable
|
|
141
|
+
resolvedValue = resolveVariableInChunk(init.name, chunkCode, depth + 1);
|
|
142
|
+
path.stop();
|
|
143
|
+
}
|
|
144
|
+
else if (init.type === "CallExpression" &&
|
|
145
|
+
init.callee.type === "MemberExpression" &&
|
|
146
|
+
init.callee.property.type === "Identifier" &&
|
|
147
|
+
init.callee.property.name === "concat") {
|
|
148
|
+
// Handle concat chains
|
|
149
|
+
const parts = [];
|
|
150
|
+
let currentCall = init;
|
|
151
|
+
while (currentCall.type === "CallExpression" &&
|
|
152
|
+
currentCall.callee.type === "MemberExpression" &&
|
|
153
|
+
currentCall.callee.property.type === "Identifier" &&
|
|
154
|
+
currentCall.callee.property.name === "concat") {
|
|
155
|
+
for (const arg of currentCall.arguments) {
|
|
156
|
+
if (arg.type === "StringLiteral") {
|
|
157
|
+
parts.unshift(arg.value);
|
|
158
|
+
}
|
|
159
|
+
else if (arg.type === "Identifier") {
|
|
160
|
+
const argValue = resolveVariableInChunk(arg.name, chunkCode, depth + 1);
|
|
161
|
+
parts.unshift(argValue);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
parts.unshift(`[${arg.type}]`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
currentCall = currentCall.callee.object;
|
|
168
|
+
}
|
|
169
|
+
if (currentCall.type === "StringLiteral") {
|
|
170
|
+
parts.unshift(currentCall.value);
|
|
171
|
+
}
|
|
172
|
+
else if (currentCall.type === "Identifier") {
|
|
173
|
+
const baseValue = resolveVariableInChunk(currentCall.name, chunkCode, depth + 1);
|
|
174
|
+
parts.unshift(baseValue);
|
|
175
|
+
}
|
|
176
|
+
resolvedValue = parts.join("");
|
|
177
|
+
path.stop();
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
// Find assignments: varName = ...
|
|
182
|
+
AssignmentExpression(path) {
|
|
183
|
+
// Skip assignments inside loops for the same reason as above
|
|
184
|
+
if (isInsideLoop(path))
|
|
185
|
+
return;
|
|
186
|
+
if (path.node.left.type === "Identifier" && path.node.left.name === varName) {
|
|
187
|
+
const right = path.node.right;
|
|
188
|
+
if (right.type === "StringLiteral") {
|
|
189
|
+
resolvedValue = right.value;
|
|
190
|
+
path.stop();
|
|
191
|
+
}
|
|
192
|
+
else if (right.type === "NumericLiteral") {
|
|
193
|
+
resolvedValue = String(right.value);
|
|
194
|
+
path.stop();
|
|
195
|
+
}
|
|
196
|
+
else if (right.type === "Identifier") {
|
|
197
|
+
resolvedValue = resolveVariableInChunk(right.name, chunkCode, depth + 1);
|
|
198
|
+
path.stop();
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
return resolvedValue || `[unresolved: ${varName}]`;
|
|
204
|
+
}
|
|
205
|
+
catch (e) {
|
|
206
|
+
return `[error resolving ${varName}: ${e.message}]`;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
/**
|
|
210
|
+
* Wraps resolveVariableInChunk and only returns the result when it looks like a
|
|
211
|
+
* URL component (contains "/" or "://"). Identifiers inside function bodies may
|
|
212
|
+
* coincidentally match module-scope declarations with the same name — gating on
|
|
213
|
+
* URL shape prevents substituting non-URL values into URL templates.
|
|
214
|
+
*/
|
|
215
|
+
export const resolveChunkVarAsUrlPart = (name, code) => {
|
|
216
|
+
const val = resolveVariableInChunk(name, code);
|
|
217
|
+
if (!val || String(val).startsWith("["))
|
|
218
|
+
return null;
|
|
219
|
+
const s = String(val);
|
|
220
|
+
return s.includes("/") || s.includes("://") ? s : null;
|
|
221
|
+
};
|
|
222
|
+
/**
|
|
223
|
+
* Resolves a member expression like "obj.property" in a chunk.
|
|
224
|
+
*
|
|
225
|
+
* @param objectName - The name of the object variable
|
|
226
|
+
* @param propertyName - The name of the property to access
|
|
227
|
+
* @param chunkCode - The source code of the chunk
|
|
228
|
+
* @param chunks - All available chunks for cross-chunk resolution
|
|
229
|
+
* @param thirdArgName - The name of the third parameter (webpack require function)
|
|
230
|
+
* @param depth - Current recursion depth to prevent infinite loops
|
|
231
|
+
* @returns The resolved value or a placeholder if unresolved
|
|
232
|
+
*/
|
|
233
|
+
export const resolveMemberExpressionInChunk = (objectName, propertyName, chunkCode, chunks, thirdArgName, depth = 0) => {
|
|
234
|
+
if (depth > 10) {
|
|
235
|
+
return `[max recursion depth for ${objectName}.${propertyName}]`;
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
const ast = parser.parse(chunkCode, {
|
|
239
|
+
sourceType: "module",
|
|
240
|
+
plugins: ["jsx", "typescript"],
|
|
241
|
+
errorRecovery: true,
|
|
242
|
+
});
|
|
243
|
+
let resolvedValue = null;
|
|
244
|
+
traverse(ast, {
|
|
245
|
+
VariableDeclarator(path) {
|
|
246
|
+
if (path.node.id.type === "Identifier" && path.node.id.name === objectName && path.node.init) {
|
|
247
|
+
const init = path.node.init;
|
|
248
|
+
// Check if this is a webpack chunk import: u = r(3269)
|
|
249
|
+
if (init.type === "CallExpression" &&
|
|
250
|
+
init.callee.type === "Identifier" &&
|
|
251
|
+
thirdArgName &&
|
|
252
|
+
init.callee.name === thirdArgName &&
|
|
253
|
+
init.arguments.length > 0 &&
|
|
254
|
+
init.arguments[0].type === "NumericLiteral" &&
|
|
255
|
+
chunks) {
|
|
256
|
+
// This is a webpack chunk import, use resolveWebpackChunkImport with the property name
|
|
257
|
+
const chunkImportValue = resolveWebpackChunkImport(objectName, chunkCode, chunks, thirdArgName, [propertyName]);
|
|
258
|
+
if (chunkImportValue &&
|
|
259
|
+
typeof chunkImportValue === "string" &&
|
|
260
|
+
!chunkImportValue.startsWith("[unresolved") &&
|
|
261
|
+
!chunkImportValue.startsWith("[error")) {
|
|
262
|
+
resolvedValue = chunkImportValue;
|
|
263
|
+
path.stop();
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Handle object expressions: let obj = { prop: "value" }
|
|
268
|
+
if (init.type === "ObjectExpression") {
|
|
269
|
+
for (const prop of init.properties) {
|
|
270
|
+
if (prop.type === "ObjectProperty" &&
|
|
271
|
+
prop.key.type === "Identifier" &&
|
|
272
|
+
prop.key.name === propertyName) {
|
|
273
|
+
const value = prop.value;
|
|
274
|
+
if (value.type === "StringLiteral") {
|
|
275
|
+
resolvedValue = value.value;
|
|
276
|
+
path.stop();
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
else if (value.type === "NumericLiteral") {
|
|
280
|
+
resolvedValue = String(value.value);
|
|
281
|
+
path.stop();
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
else if (value.type === "Identifier") {
|
|
285
|
+
resolvedValue = resolveVariableInChunk(value.name, chunkCode, depth + 1);
|
|
286
|
+
path.stop();
|
|
287
|
+
return;
|
|
288
|
+
}
|
|
289
|
+
else if (value.type === "LogicalExpression") {
|
|
290
|
+
// Handle: baseUrl: c.env.UMAMI_API_ENDPOINT || "https://..."
|
|
291
|
+
const right = value.right;
|
|
292
|
+
if (right.type === "StringLiteral") {
|
|
293
|
+
resolvedValue = right.value;
|
|
294
|
+
path.stop();
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
else if (value.type === "TemplateLiteral") {
|
|
299
|
+
let result = "";
|
|
300
|
+
for (let i = 0; i < value.quasis.length; i++) {
|
|
301
|
+
result += value.quasis[i].value.raw;
|
|
302
|
+
if (i < value.expressions.length) {
|
|
303
|
+
const expr = value.expressions[i];
|
|
304
|
+
if (expr.type === "Identifier") {
|
|
305
|
+
const nestedValue = resolveVariableInChunk(expr.name, chunkCode, depth + 1);
|
|
306
|
+
result += nestedValue;
|
|
307
|
+
}
|
|
308
|
+
else {
|
|
309
|
+
result += `[${expr.type}]`;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
resolvedValue = result;
|
|
314
|
+
path.stop();
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
else if (value.type === "CallExpression" &&
|
|
318
|
+
value.callee.type === "MemberExpression" &&
|
|
319
|
+
value.callee.property.type === "Identifier" &&
|
|
320
|
+
value.callee.property.name === "concat") {
|
|
321
|
+
// Handle concat chains in property values
|
|
322
|
+
const parts = [];
|
|
323
|
+
let currentCall = value;
|
|
324
|
+
while (currentCall.type === "CallExpression" &&
|
|
325
|
+
currentCall.callee.type === "MemberExpression" &&
|
|
326
|
+
currentCall.callee.property.type === "Identifier" &&
|
|
327
|
+
currentCall.callee.property.name === "concat") {
|
|
328
|
+
for (const arg of currentCall.arguments) {
|
|
329
|
+
if (arg.type === "StringLiteral") {
|
|
330
|
+
parts.unshift(arg.value);
|
|
331
|
+
}
|
|
332
|
+
else if (arg.type === "Identifier") {
|
|
333
|
+
const argValue = resolveVariableInChunk(arg.name, chunkCode, depth + 1);
|
|
334
|
+
parts.unshift(argValue);
|
|
335
|
+
}
|
|
336
|
+
else {
|
|
337
|
+
parts.unshift(`[${arg.type}]`);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
currentCall = currentCall.callee.object;
|
|
341
|
+
}
|
|
342
|
+
if (currentCall.type === "StringLiteral") {
|
|
343
|
+
parts.unshift(currentCall.value);
|
|
344
|
+
}
|
|
345
|
+
else if (currentCall.type === "Identifier") {
|
|
346
|
+
const baseValue = resolveVariableInChunk(currentCall.name, chunkCode, depth + 1);
|
|
347
|
+
parts.unshift(baseValue);
|
|
348
|
+
}
|
|
349
|
+
resolvedValue = parts.join("");
|
|
350
|
+
path.stop();
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
// Handle if object is assigned to another variable
|
|
357
|
+
else if (init.type === "Identifier") {
|
|
358
|
+
resolvedValue = resolveMemberExpressionInChunk(init.name, propertyName, chunkCode, chunks, thirdArgName, depth + 1);
|
|
359
|
+
path.stop();
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
},
|
|
363
|
+
});
|
|
364
|
+
return resolvedValue || `[unresolved: ${objectName}.${propertyName}]`;
|
|
365
|
+
}
|
|
366
|
+
catch (e) {
|
|
367
|
+
return `[error resolving ${objectName}.${propertyName}: ${e.message}]`;
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
/**
|
|
371
|
+
* Substitutes [var X] placeholders in a string with their resolved values.
|
|
372
|
+
*
|
|
373
|
+
* @param str - The string containing [var X] placeholders
|
|
374
|
+
* @param chunkCode - The source code of the chunk to resolve variables from
|
|
375
|
+
* @param chunks - All available chunks for cross-chunk resolution
|
|
376
|
+
* @param thirdArgName - The name of the third parameter (webpack require function)
|
|
377
|
+
* @returns The string with variables substituted
|
|
378
|
+
*/
|
|
379
|
+
export const substituteVariablesInString = (str, chunkCode, chunks, thirdArgName) => {
|
|
380
|
+
if (typeof str !== "string")
|
|
381
|
+
return str;
|
|
382
|
+
let result = str;
|
|
383
|
+
// Match [MemberExpression -> propertyName] patterns
|
|
384
|
+
const memberPattern = /\[MemberExpression -> ([^\]]+)\]/g;
|
|
385
|
+
let memberMatch;
|
|
386
|
+
while ((memberMatch = memberPattern.exec(str)) !== null) {
|
|
387
|
+
const propertyName = memberMatch[1];
|
|
388
|
+
// Try to find the object that contains this property
|
|
389
|
+
// We need to look at the context where this placeholder came from
|
|
390
|
+
// For now, we'll search for common patterns in the chunk
|
|
391
|
+
try {
|
|
392
|
+
const ast = parser.parse(chunkCode, {
|
|
393
|
+
sourceType: "module",
|
|
394
|
+
plugins: ["jsx", "typescript"],
|
|
395
|
+
errorRecovery: true,
|
|
396
|
+
});
|
|
397
|
+
let foundValue = null;
|
|
398
|
+
traverse(ast, {
|
|
399
|
+
MemberExpression(path) {
|
|
400
|
+
if (path.node.property.type === "Identifier" &&
|
|
401
|
+
path.node.property.name === propertyName &&
|
|
402
|
+
path.node.object.type === "Identifier") {
|
|
403
|
+
const objectName = path.node.object.name;
|
|
404
|
+
const resolvedValue = resolveMemberExpressionInChunk(objectName, propertyName, chunkCode, chunks, thirdArgName);
|
|
405
|
+
if (typeof resolvedValue === "string" &&
|
|
406
|
+
!resolvedValue.startsWith("[unresolved:") &&
|
|
407
|
+
!resolvedValue.startsWith("[error") &&
|
|
408
|
+
!resolvedValue.startsWith("[max recursion")) {
|
|
409
|
+
foundValue = resolvedValue;
|
|
410
|
+
path.stop();
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
},
|
|
414
|
+
});
|
|
415
|
+
if (foundValue) {
|
|
416
|
+
result = result.replace(`[MemberExpression -> ${propertyName}]`, foundValue);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
catch (e) {
|
|
420
|
+
// Skip if parsing fails
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
// Match [var varName] patterns
|
|
424
|
+
const varPattern = /\[var ([^\]]+)\]/g;
|
|
425
|
+
let match;
|
|
426
|
+
while ((match = varPattern.exec(str)) !== null) {
|
|
427
|
+
const varName = match[1];
|
|
428
|
+
const resolvedValue = resolveVariableInChunk(varName, chunkCode);
|
|
429
|
+
// Only substitute if we got a clean value (not an error/unresolved placeholder).
|
|
430
|
+
// Also reject values that contain placeholder-style brackets (they are not fully
|
|
431
|
+
// resolved), pure numbers (likely loop counters, not URL segments), very long
|
|
432
|
+
// strings (likely resolved to code, not a URL component), or strings containing
|
|
433
|
+
// ANSI escape sequences (leaked from logging utilities in the bundle).
|
|
434
|
+
if (typeof resolvedValue === "string" &&
|
|
435
|
+
!resolvedValue.startsWith("[unresolved:") &&
|
|
436
|
+
!resolvedValue.startsWith("[error") &&
|
|
437
|
+
!resolvedValue.startsWith("[max recursion") &&
|
|
438
|
+
!resolvedValue.includes("[") &&
|
|
439
|
+
!/^\d+$/.test(resolvedValue) &&
|
|
440
|
+
!/^\d+:\d+$/.test(resolvedValue) &&
|
|
441
|
+
!resolvedValue.includes("\x1b") &&
|
|
442
|
+
resolvedValue.length <= 500) {
|
|
443
|
+
result = result.replace(`[var ${varName}]`, resolvedValue);
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return result;
|
|
447
|
+
};
|
|
448
|
+
/**
|
|
449
|
+
* Resolves webpack chunk imports by tracing through chunk definitions.
|
|
450
|
+
*
|
|
451
|
+
* This function handles patterns like:
|
|
452
|
+
* - `i = l(17917)` where `l` is the third arg and `17917` is a chunk ID
|
|
453
|
+
* - Finds exports in the target chunk (e.g., `l: function() { return n; }`)
|
|
454
|
+
* - Recursively follows references to resolve the final object
|
|
455
|
+
* - Supports nested member expressions like `i.l.FLOW.postFlowCompleteStatus`
|
|
456
|
+
*
|
|
457
|
+
* @param identifierName - The name of the identifier to resolve (e.g., 'i')
|
|
458
|
+
* @param chunkCode - The source code of the current chunk
|
|
459
|
+
* @param chunks - All available chunks for cross-chunk resolution
|
|
460
|
+
* @param thirdArgName - The name of the third parameter (webpack require function)
|
|
461
|
+
* @param memberPath - Array of property names to traverse (e.g., ['l', 'FLOW', 'getTaxonomies'])
|
|
462
|
+
* @returns The resolved value or a descriptive placeholder
|
|
463
|
+
*/
|
|
464
|
+
export const resolveWebpackChunkImport = (identifierName, chunkCode, chunks, thirdArgName, memberPath = []) => {
|
|
465
|
+
try {
|
|
466
|
+
// Parse the current chunk to find the identifier definition
|
|
467
|
+
const ast = parser.parse(chunkCode, {
|
|
468
|
+
sourceType: "unambiguous",
|
|
469
|
+
plugins: ["jsx", "typescript"],
|
|
470
|
+
errorRecovery: true,
|
|
471
|
+
});
|
|
472
|
+
let targetChunkId = null;
|
|
473
|
+
// Find pattern: identifierName = thirdArgName(chunkNumber)
|
|
474
|
+
traverse(ast, {
|
|
475
|
+
AssignmentExpression(path) {
|
|
476
|
+
const left = path.node.left;
|
|
477
|
+
const right = path.node.right;
|
|
478
|
+
// Check if left side matches our identifier
|
|
479
|
+
if (left.type === "Identifier" && left.name === identifierName) {
|
|
480
|
+
// console.log(`[DEBUG] Found assignment to ${identifierName}, right side type: ${right.type}`);
|
|
481
|
+
if (right.type === "CallExpression") {
|
|
482
|
+
// console.log(`[DEBUG] CallExpression callee type: ${right.callee.type}, callee name: ${right.callee.type === "Identifier" ? right.callee.name : "N/A"}`);
|
|
483
|
+
}
|
|
484
|
+
// Check if right side is thirdArgName(number)
|
|
485
|
+
if (right.type === "CallExpression" &&
|
|
486
|
+
right.callee.type === "Identifier" &&
|
|
487
|
+
right.callee.name === thirdArgName &&
|
|
488
|
+
right.arguments.length > 0) {
|
|
489
|
+
const arg = right.arguments[0];
|
|
490
|
+
if (arg.type === "NumericLiteral") {
|
|
491
|
+
targetChunkId = String(arg.value);
|
|
492
|
+
}
|
|
493
|
+
else if (arg.type === "StringLiteral") {
|
|
494
|
+
targetChunkId = arg.value;
|
|
495
|
+
}
|
|
496
|
+
path.stop();
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
},
|
|
500
|
+
VariableDeclarator(path) {
|
|
501
|
+
const id = path.node.id;
|
|
502
|
+
const init = path.node.init;
|
|
503
|
+
if (id.type === "Identifier" && id.name === identifierName && init) {
|
|
504
|
+
// console.log(`[DEBUG] Found variable declarator for ${identifierName}, init type: ${init.type}`);
|
|
505
|
+
if (init.type === "CallExpression") {
|
|
506
|
+
// console.log(`[DEBUG] CallExpression callee type: ${init.callee.type}, callee name: ${init.callee.type === "Identifier" ? init.callee.name : "N/A"}`);
|
|
507
|
+
}
|
|
508
|
+
if (init.type === "CallExpression" &&
|
|
509
|
+
init.callee.type === "Identifier" &&
|
|
510
|
+
init.callee.name === thirdArgName &&
|
|
511
|
+
init.arguments.length > 0) {
|
|
512
|
+
const arg = init.arguments[0];
|
|
513
|
+
if (arg.type === "NumericLiteral") {
|
|
514
|
+
targetChunkId = String(arg.value);
|
|
515
|
+
}
|
|
516
|
+
else if (arg.type === "StringLiteral") {
|
|
517
|
+
targetChunkId = arg.value;
|
|
518
|
+
}
|
|
519
|
+
path.stop();
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
},
|
|
523
|
+
});
|
|
524
|
+
if (!targetChunkId) {
|
|
525
|
+
// console.log(`[DEBUG] Could not find chunk import for ${identifierName} using third arg ${thirdArgName}`);
|
|
526
|
+
return `[unresolved: could not find chunk import for ${identifierName}]`;
|
|
527
|
+
}
|
|
528
|
+
// console.log(`[DEBUG] Resolved ${identifierName} to chunk ${targetChunkId}, looking for path: ${memberPath.join('.')}`);
|
|
529
|
+
// Find the target chunk
|
|
530
|
+
const targetChunk = chunks[targetChunkId];
|
|
531
|
+
if (!targetChunk) {
|
|
532
|
+
return `[unresolved: chunk ${targetChunkId} not found]`;
|
|
533
|
+
}
|
|
534
|
+
// If no member path, return a placeholder
|
|
535
|
+
if (memberPath.length === 0) {
|
|
536
|
+
return `[webpack_import: chunk_${targetChunkId}]`;
|
|
537
|
+
}
|
|
538
|
+
// Parse the target chunk
|
|
539
|
+
let targetAst;
|
|
540
|
+
try {
|
|
541
|
+
targetAst = parser.parse(targetChunk.code, {
|
|
542
|
+
sourceType: "unambiguous",
|
|
543
|
+
plugins: ["jsx", "typescript"],
|
|
544
|
+
errorRecovery: true,
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
catch (_a) {
|
|
548
|
+
return `[webpack_import: chunk_${targetChunkId}]`;
|
|
549
|
+
}
|
|
550
|
+
// Find the export for the first property in memberPath
|
|
551
|
+
const firstProperty = memberPath[0];
|
|
552
|
+
let resolvedValue = null;
|
|
553
|
+
// Helper to resolve a value recursively in the target chunk
|
|
554
|
+
const resolveInChunk = (varName, currentAst, depth = 0) => {
|
|
555
|
+
if (depth > 10) {
|
|
556
|
+
return `[max_depth_exceeded]`;
|
|
557
|
+
}
|
|
558
|
+
let result = null;
|
|
559
|
+
traverse(currentAst, {
|
|
560
|
+
// Look for: propertyName: function() { return someVar; }
|
|
561
|
+
ObjectProperty(path) {
|
|
562
|
+
if (result)
|
|
563
|
+
return; // Already found
|
|
564
|
+
const key = path.node.key;
|
|
565
|
+
const value = path.node.value;
|
|
566
|
+
// Check if key matches what we're looking for
|
|
567
|
+
const keyName = key.type === "Identifier" ? key.name : key.type === "StringLiteral" ? key.value : null;
|
|
568
|
+
if (keyName === varName) {
|
|
569
|
+
// Check if it's a function that returns something
|
|
570
|
+
if (value.type === "FunctionExpression" || value.type === "ArrowFunctionExpression") {
|
|
571
|
+
const body = value.body;
|
|
572
|
+
if (body.type === "BlockStatement" && body.body.length > 0) {
|
|
573
|
+
const lastStatement = body.body[body.body.length - 1];
|
|
574
|
+
if (lastStatement.type === "ReturnStatement" && lastStatement.argument) {
|
|
575
|
+
if (lastStatement.argument.type === "Identifier") {
|
|
576
|
+
// Recursively resolve the returned identifier
|
|
577
|
+
result = resolveInChunk(lastStatement.argument.name, currentAst, depth + 1);
|
|
578
|
+
}
|
|
579
|
+
else if (lastStatement.argument.type === "ObjectExpression") {
|
|
580
|
+
// Directly an object
|
|
581
|
+
result = lastStatement.argument;
|
|
582
|
+
}
|
|
583
|
+
else if (lastStatement.argument.type === "CallExpression") {
|
|
584
|
+
result = lastStatement.argument;
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
else if (body.type === "ObjectExpression") {
|
|
589
|
+
// Arrow function directly returning an object
|
|
590
|
+
result = body;
|
|
591
|
+
}
|
|
592
|
+
else if (body.type === "Identifier") {
|
|
593
|
+
// Arrow function returning an identifier
|
|
594
|
+
result = resolveInChunk(body.name, currentAst, depth + 1);
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
else if (value.type === "ObjectExpression") {
|
|
598
|
+
result = value;
|
|
599
|
+
}
|
|
600
|
+
else if (value.type === "Identifier") {
|
|
601
|
+
result = resolveInChunk(value.name, currentAst, depth + 1);
|
|
602
|
+
}
|
|
603
|
+
path.stop();
|
|
604
|
+
}
|
|
605
|
+
},
|
|
606
|
+
// Look for: let varName = { ... } or const varName = { ... }
|
|
607
|
+
VariableDeclarator(path) {
|
|
608
|
+
if (result)
|
|
609
|
+
return;
|
|
610
|
+
const id = path.node.id;
|
|
611
|
+
const init = path.node.init;
|
|
612
|
+
if (id.type === "Identifier" && id.name === varName && init) {
|
|
613
|
+
if (init.type === "ObjectExpression") {
|
|
614
|
+
result = init;
|
|
615
|
+
}
|
|
616
|
+
else if (init.type === "Identifier") {
|
|
617
|
+
result = resolveInChunk(init.name, currentAst, depth + 1);
|
|
618
|
+
}
|
|
619
|
+
else if (init.type === "CallExpression") {
|
|
620
|
+
result = init;
|
|
621
|
+
}
|
|
622
|
+
path.stop();
|
|
623
|
+
}
|
|
624
|
+
},
|
|
625
|
+
});
|
|
626
|
+
return result;
|
|
627
|
+
};
|
|
628
|
+
// Start resolving from the first property
|
|
629
|
+
const initialResolved = resolveInChunk(firstProperty, targetAst);
|
|
630
|
+
if (!initialResolved) {
|
|
631
|
+
// console.log(`[DEBUG] Property ${firstProperty} not found in chunk ${targetChunkId}`);
|
|
632
|
+
return `[unresolved: property ${firstProperty} not found in chunk ${targetChunkId}]`;
|
|
633
|
+
}
|
|
634
|
+
// console.log(`[DEBUG] Found property ${firstProperty} in chunk ${targetChunkId}`);
|
|
635
|
+
// Convert AST node to JavaScript object
|
|
636
|
+
const convertAstToValue = (node, remainingPath = []) => {
|
|
637
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
|
638
|
+
if (!node)
|
|
639
|
+
return null;
|
|
640
|
+
// Unwrap Object.freeze({...}) — single-arg wrapper that returns its first arg.
|
|
641
|
+
if (node.type === "CallExpression" &&
|
|
642
|
+
((_a = node.callee) === null || _a === void 0 ? void 0 : _a.type) === "MemberExpression" &&
|
|
643
|
+
((_b = node.callee.property) === null || _b === void 0 ? void 0 : _b.type) === "Identifier" &&
|
|
644
|
+
node.callee.property.name === "freeze" &&
|
|
645
|
+
((_c = node.arguments) === null || _c === void 0 ? void 0 : _c.length) > 0) {
|
|
646
|
+
return convertAstToValue(node.arguments[0], remainingPath);
|
|
647
|
+
}
|
|
648
|
+
// Unwrap Object.assign(target, ...sources) by merging each arg's properties
|
|
649
|
+
// so downstream remainingPath lookups can resolve keys contributed by sources.
|
|
650
|
+
if (node.type === "CallExpression" &&
|
|
651
|
+
((_d = node.callee) === null || _d === void 0 ? void 0 : _d.type) === "MemberExpression" &&
|
|
652
|
+
((_e = node.callee.property) === null || _e === void 0 ? void 0 : _e.type) === "Identifier" &&
|
|
653
|
+
node.callee.property.name === "assign" &&
|
|
654
|
+
((_f = node.arguments) === null || _f === void 0 ? void 0 : _f.length) > 0) {
|
|
655
|
+
const merged = {};
|
|
656
|
+
for (const arg of node.arguments) {
|
|
657
|
+
const value = convertAstToValue(arg, []);
|
|
658
|
+
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
659
|
+
Object.assign(merged, value);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (remainingPath.length === 0)
|
|
663
|
+
return merged;
|
|
664
|
+
const [next, ...rest] = remainingPath;
|
|
665
|
+
if (next in merged) {
|
|
666
|
+
const v = merged[next];
|
|
667
|
+
if (rest.length === 0)
|
|
668
|
+
return v;
|
|
669
|
+
if (v && typeof v === "object") {
|
|
670
|
+
let cur = v;
|
|
671
|
+
for (const k of rest) {
|
|
672
|
+
if (cur && typeof cur === "object" && k in cur)
|
|
673
|
+
cur = cur[k];
|
|
674
|
+
else
|
|
675
|
+
return null;
|
|
676
|
+
}
|
|
677
|
+
return cur;
|
|
678
|
+
}
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
return null;
|
|
682
|
+
}
|
|
683
|
+
if (node.type === "ObjectExpression") {
|
|
684
|
+
const obj = {};
|
|
685
|
+
for (const prop of node.properties) {
|
|
686
|
+
if (prop.type === "ObjectProperty") {
|
|
687
|
+
let key = null;
|
|
688
|
+
if (prop.key.type === "Identifier") {
|
|
689
|
+
key = prop.key.name;
|
|
690
|
+
}
|
|
691
|
+
else if (prop.key.type === "StringLiteral") {
|
|
692
|
+
key = prop.key.value;
|
|
693
|
+
}
|
|
694
|
+
if (key) {
|
|
695
|
+
const value = prop.value;
|
|
696
|
+
if (value.type === "ArrowFunctionExpression" || value.type === "FunctionExpression") {
|
|
697
|
+
// Try to extract the return value from arrow/regular functions
|
|
698
|
+
let returnValue = null;
|
|
699
|
+
if (value.type === "ArrowFunctionExpression") {
|
|
700
|
+
// Arrow function: could be expression body or block body
|
|
701
|
+
if (value.body.type !== "BlockStatement") {
|
|
702
|
+
// Expression body - directly use it
|
|
703
|
+
returnValue = value.body;
|
|
704
|
+
}
|
|
705
|
+
else if (value.body.body.length > 0) {
|
|
706
|
+
// Block body - look for return statement
|
|
707
|
+
const returnStmt = value.body.body.find((stmt) => stmt.type === "ReturnStatement");
|
|
708
|
+
if (returnStmt &&
|
|
709
|
+
returnStmt.type === "ReturnStatement" &&
|
|
710
|
+
returnStmt.argument) {
|
|
711
|
+
returnValue = returnStmt.argument;
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
}
|
|
715
|
+
else if (value.type === "FunctionExpression" && value.body.body.length > 0) {
|
|
716
|
+
// Regular function - look for return statement
|
|
717
|
+
const returnStmt = value.body.body.find((stmt) => stmt.type === "ReturnStatement");
|
|
718
|
+
if (returnStmt && returnStmt.type === "ReturnStatement" && returnStmt.argument) {
|
|
719
|
+
returnValue = returnStmt.argument;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
// Process the return value
|
|
723
|
+
if (returnValue) {
|
|
724
|
+
if (returnValue.type === "StringLiteral") {
|
|
725
|
+
obj[key] = returnValue.value;
|
|
726
|
+
}
|
|
727
|
+
else if (returnValue.type === "TemplateLiteral") {
|
|
728
|
+
// Handle template literals in function returns
|
|
729
|
+
const parts = [];
|
|
730
|
+
for (let i = 0; i < returnValue.quasis.length; i++) {
|
|
731
|
+
parts.push(returnValue.quasis[i].value.raw);
|
|
732
|
+
if (i < returnValue.expressions.length) {
|
|
733
|
+
const expr = returnValue.expressions[i];
|
|
734
|
+
if (expr.type === "Identifier") {
|
|
735
|
+
parts.push((_g = resolveChunkVarAsUrlPart(expr.name, targetChunk.code)) !== null && _g !== void 0 ? _g : `[var ${expr.name}]`);
|
|
736
|
+
}
|
|
737
|
+
else {
|
|
738
|
+
parts.push(`[${expr.type}]`);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
// Reorganize if base URL found
|
|
743
|
+
let baseUrlIndex = -1;
|
|
744
|
+
for (let i = 0; i < parts.length; i++) {
|
|
745
|
+
if (typeof parts[i] === "string" &&
|
|
746
|
+
(parts[i].startsWith("http://") || parts[i].startsWith("https://"))) {
|
|
747
|
+
baseUrlIndex = i;
|
|
748
|
+
break;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (baseUrlIndex > 0) {
|
|
752
|
+
const beforeUrl = parts.slice(0, baseUrlIndex);
|
|
753
|
+
const baseUrl = parts[baseUrlIndex];
|
|
754
|
+
const afterUrl = parts.slice(baseUrlIndex + 1);
|
|
755
|
+
// Normalize slashes to avoid double slashes
|
|
756
|
+
const result = (baseUrl + beforeUrl.join("") + afterUrl.join("")).replace(/([^:]\/)\/+/g, "$1");
|
|
757
|
+
obj[key] = result;
|
|
758
|
+
}
|
|
759
|
+
else {
|
|
760
|
+
obj[key] = parts.join("");
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
else if (returnValue.type === "CallExpression" &&
|
|
764
|
+
returnValue.callee.type === "MemberExpression" &&
|
|
765
|
+
returnValue.callee.property.type === "Identifier" &&
|
|
766
|
+
returnValue.callee.property.name === "concat") {
|
|
767
|
+
// Handle concat chains in function returns
|
|
768
|
+
let currentCall = returnValue;
|
|
769
|
+
const parts = [];
|
|
770
|
+
while (currentCall.type === "CallExpression" &&
|
|
771
|
+
currentCall.callee.type === "MemberExpression" &&
|
|
772
|
+
currentCall.callee.property.type === "Identifier" &&
|
|
773
|
+
currentCall.callee.property.name === "concat") {
|
|
774
|
+
for (const arg of currentCall.arguments) {
|
|
775
|
+
if (arg.type === "StringLiteral") {
|
|
776
|
+
parts.unshift(arg.value);
|
|
777
|
+
}
|
|
778
|
+
else if (arg.type === "Identifier") {
|
|
779
|
+
parts.unshift((_h = resolveChunkVarAsUrlPart(arg.name, targetChunk.code)) !== null && _h !== void 0 ? _h : `[var ${arg.name}]`);
|
|
780
|
+
}
|
|
781
|
+
else {
|
|
782
|
+
parts.unshift(`[${arg.type}]`);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
currentCall = currentCall.callee.object;
|
|
786
|
+
}
|
|
787
|
+
if (currentCall && currentCall.type === "StringLiteral") {
|
|
788
|
+
parts.unshift(currentCall.value);
|
|
789
|
+
}
|
|
790
|
+
else if (currentCall && currentCall.type === "Identifier") {
|
|
791
|
+
parts.unshift((_j = resolveChunkVarAsUrlPart(currentCall.name, targetChunk.code)) !== null && _j !== void 0 ? _j : `[var ${currentCall.name}]`);
|
|
792
|
+
}
|
|
793
|
+
// Reorganize parts if a base URL is found in the middle
|
|
794
|
+
let baseUrlIndex = -1;
|
|
795
|
+
for (let i = 0; i < parts.length; i++) {
|
|
796
|
+
if (typeof parts[i] === "string" &&
|
|
797
|
+
(parts[i].startsWith("http://") || parts[i].startsWith("https://"))) {
|
|
798
|
+
baseUrlIndex = i;
|
|
799
|
+
break;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
if (baseUrlIndex > 0) {
|
|
803
|
+
// Move base URL to the front and append path parts
|
|
804
|
+
const beforeUrl = parts.slice(0, baseUrlIndex);
|
|
805
|
+
const baseUrl = parts[baseUrlIndex];
|
|
806
|
+
const afterUrl = parts.slice(baseUrlIndex + 1);
|
|
807
|
+
// Reconstruct: baseUrl + beforeUrl + afterUrl and normalize slashes
|
|
808
|
+
const result = (baseUrl + beforeUrl.join("") + afterUrl.join("")).replace(/([^:]\/)\/+/g, "$1");
|
|
809
|
+
obj[key] = result;
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
obj[key] = parts.join("");
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
obj[key] = `[function -> ${returnValue.type}]`;
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
obj[key] = `[function]`;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
else if (value.type === "StringLiteral") {
|
|
824
|
+
obj[key] = value.value;
|
|
825
|
+
}
|
|
826
|
+
else if (value.type === "NumericLiteral") {
|
|
827
|
+
obj[key] = value.value;
|
|
828
|
+
}
|
|
829
|
+
else if (value.type === "ObjectExpression") {
|
|
830
|
+
obj[key] = convertAstToValue(value, []);
|
|
831
|
+
}
|
|
832
|
+
else if (value.type === "TemplateLiteral") {
|
|
833
|
+
// Handle template literals
|
|
834
|
+
const parts = [];
|
|
835
|
+
for (let i = 0; i < value.quasis.length; i++) {
|
|
836
|
+
parts.push(value.quasis[i].value.raw);
|
|
837
|
+
if (i < value.expressions.length) {
|
|
838
|
+
const expr = value.expressions[i];
|
|
839
|
+
if (expr.type === "Identifier") {
|
|
840
|
+
parts.push((_k = resolveChunkVarAsUrlPart(expr.name, targetChunk.code)) !== null && _k !== void 0 ? _k : `[var ${expr.name}]`);
|
|
841
|
+
}
|
|
842
|
+
else {
|
|
843
|
+
parts.push(`[${expr.type}]`);
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
// Reorganize if base URL found
|
|
848
|
+
let baseUrlIndex = -1;
|
|
849
|
+
for (let i = 0; i < parts.length; i++) {
|
|
850
|
+
if (typeof parts[i] === "string" &&
|
|
851
|
+
(parts[i].startsWith("http://") || parts[i].startsWith("https://"))) {
|
|
852
|
+
baseUrlIndex = i;
|
|
853
|
+
break;
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
if (baseUrlIndex > 0) {
|
|
857
|
+
const beforeUrl = parts.slice(0, baseUrlIndex);
|
|
858
|
+
const baseUrl = parts[baseUrlIndex];
|
|
859
|
+
const afterUrl = parts.slice(baseUrlIndex + 1);
|
|
860
|
+
const result = (baseUrl + beforeUrl.join("") + afterUrl.join("")).replace(/([^:]\/)\/+/g, "$1");
|
|
861
|
+
obj[key] = result;
|
|
862
|
+
}
|
|
863
|
+
else {
|
|
864
|
+
obj[key] = parts.join("");
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
else if (value.type === "CallExpression") {
|
|
868
|
+
// Handle concat patterns
|
|
869
|
+
if (value.callee.type === "MemberExpression" &&
|
|
870
|
+
value.callee.property.type === "Identifier" &&
|
|
871
|
+
value.callee.property.name === "concat") {
|
|
872
|
+
// Try to resolve concat chain
|
|
873
|
+
let currentCall = value;
|
|
874
|
+
const parts = [];
|
|
875
|
+
// Walk back through the concat chain
|
|
876
|
+
while (currentCall.type === "CallExpression" &&
|
|
877
|
+
currentCall.callee.type === "MemberExpression" &&
|
|
878
|
+
currentCall.callee.property.type === "Identifier" &&
|
|
879
|
+
currentCall.callee.property.name === "concat") {
|
|
880
|
+
// Get arguments
|
|
881
|
+
for (const arg of currentCall.arguments) {
|
|
882
|
+
if (arg.type === "StringLiteral") {
|
|
883
|
+
parts.unshift(arg.value);
|
|
884
|
+
}
|
|
885
|
+
else if (arg.type === "Identifier") {
|
|
886
|
+
parts.unshift((_l = resolveChunkVarAsUrlPart(arg.name, targetChunk.code)) !== null && _l !== void 0 ? _l : `[var ${arg.name}]`);
|
|
887
|
+
}
|
|
888
|
+
else {
|
|
889
|
+
parts.unshift(`[${arg.type}]`);
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
currentCall = currentCall.callee.object;
|
|
893
|
+
}
|
|
894
|
+
// Get the base string
|
|
895
|
+
if (currentCall && currentCall.type === "StringLiteral") {
|
|
896
|
+
parts.unshift(currentCall.value);
|
|
897
|
+
}
|
|
898
|
+
else if (currentCall && currentCall.type === "Identifier") {
|
|
899
|
+
parts.unshift((_m = resolveChunkVarAsUrlPart(currentCall.name, targetChunk.code)) !== null && _m !== void 0 ? _m : `[var ${currentCall.name}]`);
|
|
900
|
+
}
|
|
901
|
+
// Reorganize parts if a base URL is found in the middle
|
|
902
|
+
let baseUrlIndex = -1;
|
|
903
|
+
for (let i = 0; i < parts.length; i++) {
|
|
904
|
+
if (typeof parts[i] === "string" &&
|
|
905
|
+
(parts[i].startsWith("http://") || parts[i].startsWith("https://"))) {
|
|
906
|
+
baseUrlIndex = i;
|
|
907
|
+
break;
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
if (baseUrlIndex > 0) {
|
|
911
|
+
const beforeUrl = parts.slice(0, baseUrlIndex);
|
|
912
|
+
const baseUrl = parts[baseUrlIndex];
|
|
913
|
+
const afterUrl = parts.slice(baseUrlIndex + 1);
|
|
914
|
+
const result = (baseUrl + beforeUrl.join("") + afterUrl.join("")).replace(/([^:]\/)\/+/g, "$1");
|
|
915
|
+
obj[key] = result;
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
obj[key] = parts.join("");
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
else {
|
|
922
|
+
obj[key] = `[CallExpression]`;
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
else {
|
|
926
|
+
obj[key] = `[${value.type}]`;
|
|
927
|
+
}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
// If we have remaining path, traverse it
|
|
932
|
+
if (remainingPath.length > 0) {
|
|
933
|
+
let current = obj;
|
|
934
|
+
for (const prop of remainingPath) {
|
|
935
|
+
if (current && typeof current === "object" && prop in current) {
|
|
936
|
+
current = current[prop];
|
|
937
|
+
}
|
|
938
|
+
else {
|
|
939
|
+
return `[unresolved: property ${prop} not found]`;
|
|
940
|
+
}
|
|
941
|
+
}
|
|
942
|
+
return current;
|
|
943
|
+
}
|
|
944
|
+
return obj;
|
|
945
|
+
}
|
|
946
|
+
return `[unsupported AST node: ${node.type}]`;
|
|
947
|
+
};
|
|
948
|
+
// Convert and resolve the remaining member path
|
|
949
|
+
const remainingPath = memberPath.slice(1);
|
|
950
|
+
resolvedValue = convertAstToValue(initialResolved, remainingPath);
|
|
951
|
+
// console.log(`[DEBUG] Final resolved value for ${identifierName}.${memberPath.join('.')}: ${typeof resolvedValue === 'object' ? JSON.stringify(resolvedValue) : resolvedValue}`);
|
|
952
|
+
return resolvedValue;
|
|
953
|
+
}
|
|
954
|
+
catch (e) {
|
|
955
|
+
return `[error resolving webpack import: ${e.message}]`;
|
|
956
|
+
}
|
|
957
|
+
};
|
|
958
|
+
/**
|
|
959
|
+
* Resolves AST node values to their actual runtime values for fetch and axios calls.
|
|
960
|
+
*
|
|
961
|
+
* This function performs deep resolution of JavaScript AST nodes, handling:
|
|
962
|
+
* - String literals, template literals, and concatenation
|
|
963
|
+
* - Object expressions and member access
|
|
964
|
+
* - Variable bindings and identifier resolution
|
|
965
|
+
* - Call expressions including JSON.stringify
|
|
966
|
+
* - Logical and conditional expressions
|
|
967
|
+
* - Binary expressions and arithmetic operations
|
|
968
|
+
* - Webpack chunk imports (for axios with chunks context)
|
|
969
|
+
*
|
|
970
|
+
* @param initialNode - The AST node to resolve
|
|
971
|
+
* @param scope - The Babel scope for variable resolution
|
|
972
|
+
* @param nodeCode - The source code string for the node
|
|
973
|
+
* @param callType - Whether this is for 'fetch' or 'axios' call analysis
|
|
974
|
+
* @param chunkCode - Optional: The source code of the current chunk (for webpack resolution)
|
|
975
|
+
* @param chunks - Optional: All available chunks (for webpack resolution)
|
|
976
|
+
* @param thirdArgName - Optional: The webpack require function name (for webpack resolution)
|
|
977
|
+
* @returns The resolved value or a descriptive placeholder string
|
|
978
|
+
*/
|
|
979
|
+
export const resolveNodeValue = (initialNode, scope, nodeCode, callType, chunkCode, chunks, thirdArgName) => {
|
|
980
|
+
var _a, _b;
|
|
981
|
+
let currentNode = initialNode;
|
|
982
|
+
const visited = new Set();
|
|
983
|
+
try {
|
|
984
|
+
while (currentNode) {
|
|
985
|
+
if (visited.has(currentNode)) {
|
|
986
|
+
return "[cyclic reference]";
|
|
987
|
+
}
|
|
988
|
+
visited.add(currentNode);
|
|
989
|
+
if (!currentNode)
|
|
990
|
+
return null;
|
|
991
|
+
// fetch specific ops
|
|
992
|
+
if (callType === "fetch") {
|
|
993
|
+
// check if it is a JSON.stringify call
|
|
994
|
+
if (currentNode.type === "CallExpression" && currentNode.callee.type === "MemberExpression") {
|
|
995
|
+
if (currentNode.callee.property.type === "Identifier" &&
|
|
996
|
+
currentNode.callee.property.name === "stringify") {
|
|
997
|
+
// if so, then first get the args for it
|
|
998
|
+
const args = currentNode.arguments;
|
|
999
|
+
// see if the first arg is an object
|
|
1000
|
+
if (args.length > 0 && args[0].type === "ObjectExpression") {
|
|
1001
|
+
// if it is an object, then convert stringify it
|
|
1002
|
+
const obj = {};
|
|
1003
|
+
for (const prop of args[0].properties) {
|
|
1004
|
+
if (prop.type === "ObjectProperty" && prop.key.type === "Identifier") {
|
|
1005
|
+
const key = prop.key.name;
|
|
1006
|
+
if (prop.value.type === "Identifier") {
|
|
1007
|
+
// Try to resolve via scope; fall back to [param:name] for params
|
|
1008
|
+
const valBinding = scope.getBinding(prop.value.name);
|
|
1009
|
+
if (valBinding && valBinding.path.node.init) {
|
|
1010
|
+
const resolved = resolveNodeValue(prop.value, scope, "", callType, chunkCode, chunks, thirdArgName);
|
|
1011
|
+
obj[key] = resolved;
|
|
1012
|
+
}
|
|
1013
|
+
else if (valBinding && valBinding.kind === "param") {
|
|
1014
|
+
obj[key] = `[param:${prop.value.name}]`;
|
|
1015
|
+
}
|
|
1016
|
+
else {
|
|
1017
|
+
obj[key] = prop.value.name;
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
else if (prop.value.type === "CallExpression" &&
|
|
1021
|
+
prop.value.callee.type === "MemberExpression" &&
|
|
1022
|
+
prop.value.callee.property.type === "Identifier" &&
|
|
1023
|
+
prop.value.callee.property.name === "stringify") {
|
|
1024
|
+
// Nested JSON.stringify(expr) — resolve expr so we show what's being serialized.
|
|
1025
|
+
const innerArgs = prop.value.arguments;
|
|
1026
|
+
if (innerArgs.length > 0) {
|
|
1027
|
+
obj[key] =
|
|
1028
|
+
(_a = resolveNodeValue(innerArgs[0], scope, "", callType, chunkCode, chunks, thirdArgName)) !== null && _a !== void 0 ? _a : "[call to object...]";
|
|
1029
|
+
}
|
|
1030
|
+
else {
|
|
1031
|
+
obj[key] = "[call to object...]";
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
else {
|
|
1035
|
+
obj[key] =
|
|
1036
|
+
(_b = resolveNodeValue(prop.value, scope, "", callType, chunkCode, chunks, thirdArgName)) !== null && _b !== void 0 ? _b : `[${prop.value.type}]`;
|
|
1037
|
+
}
|
|
1038
|
+
}
|
|
1039
|
+
else if (prop.type === "SpreadElement") {
|
|
1040
|
+
// Resolve the spread argument; if it's a known object, merge its
|
|
1041
|
+
// keys. Otherwise surface the spread as a sentinel key so the
|
|
1042
|
+
// downstream body shape advertises that there are unresolvable
|
|
1043
|
+
// additional fields, rather than silently shrinking the body.
|
|
1044
|
+
const spreadResolved = resolveNodeValue(prop.argument, scope, "", callType, chunkCode, chunks, thirdArgName);
|
|
1045
|
+
if (spreadResolved &&
|
|
1046
|
+
typeof spreadResolved === "object" &&
|
|
1047
|
+
!Array.isArray(spreadResolved)) {
|
|
1048
|
+
for (const [sk, sv] of Object.entries(spreadResolved)) {
|
|
1049
|
+
if (!(sk in obj))
|
|
1050
|
+
obj[sk] = sv;
|
|
1051
|
+
}
|
|
1052
|
+
}
|
|
1053
|
+
else {
|
|
1054
|
+
const argName = describeSpreadArg(prop.argument);
|
|
1055
|
+
obj[`...${argName}`] = "<spread>";
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
return obj;
|
|
1060
|
+
}
|
|
1061
|
+
else if (args.length > 0) {
|
|
1062
|
+
// Argument isn't a literal object — try resolving it (handles Identifier,
|
|
1063
|
+
// ConditionalExpression, etc.) so we can surface the actual body shape.
|
|
1064
|
+
const resolved = resolveNodeValue(args[0], scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1065
|
+
if (resolved !== null &&
|
|
1066
|
+
resolved !== undefined &&
|
|
1067
|
+
resolved !== "[call_stack_exceeded_use_better_machine]") {
|
|
1068
|
+
return resolved;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
}
|
|
1074
|
+
switch (currentNode.type) {
|
|
1075
|
+
case "StringLiteral":
|
|
1076
|
+
case "NumericLiteral":
|
|
1077
|
+
case "BooleanLiteral":
|
|
1078
|
+
return currentNode.value;
|
|
1079
|
+
case "NullLiteral":
|
|
1080
|
+
return null;
|
|
1081
|
+
case "TemplateLiteral": {
|
|
1082
|
+
let result = "";
|
|
1083
|
+
for (let i = 0; i < currentNode.quasis.length; i++) {
|
|
1084
|
+
result += currentNode.quasis[i].value.raw;
|
|
1085
|
+
if (i < currentNode.expressions.length) {
|
|
1086
|
+
const resolved = resolveNodeValue(currentNode.expressions[i], scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1087
|
+
if (resolved === "[call_stack_exceeded_use_better_machine]") {
|
|
1088
|
+
return resolved;
|
|
1089
|
+
}
|
|
1090
|
+
result += resolved;
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
return result;
|
|
1094
|
+
}
|
|
1095
|
+
case "Identifier": {
|
|
1096
|
+
const binding = scope.getBinding(currentNode.name);
|
|
1097
|
+
if (binding && binding.path.node.init) {
|
|
1098
|
+
const initNode = binding.path.node.init;
|
|
1099
|
+
// Update nodeCode to the actual source of the init so that concat
|
|
1100
|
+
// patterns (e.g. "".concat(x, "/path")) are re-parsed correctly
|
|
1101
|
+
if (chunkCode &&
|
|
1102
|
+
typeof initNode.start === "number" &&
|
|
1103
|
+
typeof initNode.end === "number") {
|
|
1104
|
+
nodeCode = chunkCode
|
|
1105
|
+
.slice(initNode.start, initNode.end)
|
|
1106
|
+
.replace(/\n\s*/g, "");
|
|
1107
|
+
}
|
|
1108
|
+
currentNode = initNode;
|
|
1109
|
+
continue;
|
|
1110
|
+
}
|
|
1111
|
+
if (binding && binding.kind === "param") {
|
|
1112
|
+
return `[param:${currentNode.name}]`;
|
|
1113
|
+
}
|
|
1114
|
+
return `[unresolved: ${currentNode.name}]`;
|
|
1115
|
+
}
|
|
1116
|
+
case "ObjectExpression": {
|
|
1117
|
+
const obj = {};
|
|
1118
|
+
for (const prop of currentNode.properties) {
|
|
1119
|
+
if (prop.type === "ObjectProperty") {
|
|
1120
|
+
let key;
|
|
1121
|
+
if (prop.computed) {
|
|
1122
|
+
const resolved = resolveNodeValue(prop.key, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1123
|
+
if (resolved === "[call_stack_exceeded_use_better_machine]") {
|
|
1124
|
+
return resolved;
|
|
1125
|
+
}
|
|
1126
|
+
key = resolved;
|
|
1127
|
+
}
|
|
1128
|
+
else if (prop.key.type === "Identifier") {
|
|
1129
|
+
key = prop.key.name;
|
|
1130
|
+
}
|
|
1131
|
+
else if (prop.key.type === "StringLiteral") {
|
|
1132
|
+
key = prop.key.value;
|
|
1133
|
+
}
|
|
1134
|
+
const value = resolveNodeValue(prop.value, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1135
|
+
if (value === "[call_stack_exceeded_use_better_machine]") {
|
|
1136
|
+
return value;
|
|
1137
|
+
}
|
|
1138
|
+
obj[key] = value;
|
|
1139
|
+
}
|
|
1140
|
+
else if (prop.type === "SpreadElement") {
|
|
1141
|
+
const resolved = resolveNodeValue(prop.argument, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1142
|
+
if (resolved === "[call_stack_exceeded_use_better_machine]") {
|
|
1143
|
+
return resolved;
|
|
1144
|
+
}
|
|
1145
|
+
const spreadObj = resolved;
|
|
1146
|
+
if (typeof spreadObj === "object" && spreadObj !== null) {
|
|
1147
|
+
Object.assign(obj, spreadObj);
|
|
1148
|
+
}
|
|
1149
|
+
else {
|
|
1150
|
+
// Couldn't resolve to a concrete object — keep the spread visible
|
|
1151
|
+
// in the output so callers know fields are missing.
|
|
1152
|
+
const argName = describeSpreadArg(prop.argument);
|
|
1153
|
+
obj[`...${argName}`] = "<spread>";
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
}
|
|
1157
|
+
return obj;
|
|
1158
|
+
}
|
|
1159
|
+
case "OptionalMemberExpression":
|
|
1160
|
+
case "MemberExpression": {
|
|
1161
|
+
// Handle deeply-nested webpack chunk imports by flattening the chain:
|
|
1162
|
+
// s.h.NEXT_OKTA_VALIDATE_USER -> resolveWebpackChunkImport("s", ..., ["h", "NEXT_OKTA_VALIDATE_USER"])
|
|
1163
|
+
if (chunkCode && chunks && thirdArgName && !currentNode.computed) {
|
|
1164
|
+
const chain = [];
|
|
1165
|
+
let walker = currentNode;
|
|
1166
|
+
let rootIdent = null;
|
|
1167
|
+
while (walker) {
|
|
1168
|
+
if (walker.type === "MemberExpression" &&
|
|
1169
|
+
!walker.computed &&
|
|
1170
|
+
walker.property.type === "Identifier") {
|
|
1171
|
+
chain.unshift(walker.property.name);
|
|
1172
|
+
walker = walker.object;
|
|
1173
|
+
}
|
|
1174
|
+
else if (walker.type === "Identifier") {
|
|
1175
|
+
rootIdent = walker.name;
|
|
1176
|
+
break;
|
|
1177
|
+
}
|
|
1178
|
+
else {
|
|
1179
|
+
break;
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (rootIdent && chain.length > 0) {
|
|
1183
|
+
try {
|
|
1184
|
+
const webpackResult = resolveWebpackChunkImport(rootIdent, chunkCode, chunks, thirdArgName, chain);
|
|
1185
|
+
if (webpackResult !== null &&
|
|
1186
|
+
webpackResult !== undefined &&
|
|
1187
|
+
typeof webpackResult === "string" &&
|
|
1188
|
+
!webpackResult.startsWith("[unresolved") &&
|
|
1189
|
+
!webpackResult.startsWith("[error") &&
|
|
1190
|
+
!webpackResult.startsWith("[unsupported") &&
|
|
1191
|
+
!webpackResult.startsWith("[max_depth")) {
|
|
1192
|
+
return webpackResult;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
catch (e) {
|
|
1196
|
+
// fall through
|
|
1197
|
+
}
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
const object = resolveNodeValue(currentNode.object, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1201
|
+
if (object === "[call_stack_exceeded_use_better_machine]") {
|
|
1202
|
+
return object;
|
|
1203
|
+
}
|
|
1204
|
+
if (typeof object === "object" && object !== null) {
|
|
1205
|
+
let propertyName;
|
|
1206
|
+
if (currentNode.computed) {
|
|
1207
|
+
const resolved = resolveNodeValue(currentNode.property, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1208
|
+
if (resolved === "[call_stack_exceeded_use_better_machine]") {
|
|
1209
|
+
return resolved;
|
|
1210
|
+
}
|
|
1211
|
+
propertyName = resolved;
|
|
1212
|
+
}
|
|
1213
|
+
else if (currentNode.property.type === "Identifier") {
|
|
1214
|
+
propertyName = currentNode.property.name;
|
|
1215
|
+
}
|
|
1216
|
+
return object[propertyName];
|
|
1217
|
+
}
|
|
1218
|
+
// Build a readable path like [member:e.Rut.toString] for unresolved member expressions
|
|
1219
|
+
const memberParts = [];
|
|
1220
|
+
let memberWalker = currentNode;
|
|
1221
|
+
while (memberWalker &&
|
|
1222
|
+
memberWalker.type === "MemberExpression" &&
|
|
1223
|
+
!memberWalker.computed &&
|
|
1224
|
+
memberWalker.property.type === "Identifier") {
|
|
1225
|
+
memberParts.unshift(memberWalker.property.name);
|
|
1226
|
+
memberWalker = memberWalker.object;
|
|
1227
|
+
}
|
|
1228
|
+
if (memberWalker && memberWalker.type === "Identifier" && memberParts.length > 0) {
|
|
1229
|
+
memberParts.unshift(memberWalker.name);
|
|
1230
|
+
return `[member:${memberParts.join(".")}]`;
|
|
1231
|
+
}
|
|
1232
|
+
return `[unresolved member expression]`;
|
|
1233
|
+
}
|
|
1234
|
+
case "CallExpression": {
|
|
1235
|
+
if (currentNode.callee.type === "MemberExpression" &&
|
|
1236
|
+
currentNode.callee.property.type === "Identifier" &&
|
|
1237
|
+
currentNode.callee.property.name === "toString") {
|
|
1238
|
+
currentNode = currentNode.callee.object;
|
|
1239
|
+
continue;
|
|
1240
|
+
}
|
|
1241
|
+
// For axios, try to resolve the callee if it's a webpack chunk import MemberExpression
|
|
1242
|
+
if (callType === "axios" &&
|
|
1243
|
+
currentNode.callee.type === "MemberExpression" &&
|
|
1244
|
+
chunkCode &&
|
|
1245
|
+
chunks &&
|
|
1246
|
+
thirdArgName) {
|
|
1247
|
+
// Try to resolve the callee as a webpack chunk import
|
|
1248
|
+
const memberExpr = currentNode.callee;
|
|
1249
|
+
// Collect the full member expression path
|
|
1250
|
+
const memberPath = [];
|
|
1251
|
+
let tempNode = memberExpr;
|
|
1252
|
+
// Traverse backwards to collect the path
|
|
1253
|
+
while (tempNode.type === "MemberExpression") {
|
|
1254
|
+
if (tempNode.property.type === "Identifier") {
|
|
1255
|
+
memberPath.unshift(tempNode.property.name);
|
|
1256
|
+
}
|
|
1257
|
+
tempNode = tempNode.object;
|
|
1258
|
+
}
|
|
1259
|
+
// Get the root identifier
|
|
1260
|
+
if (tempNode.type === "Identifier") {
|
|
1261
|
+
const rootIdentifier = tempNode.name;
|
|
1262
|
+
// Try to resolve using webpack chunk import
|
|
1263
|
+
const resolved = resolveWebpackChunkImport(rootIdentifier, chunkCode, chunks, thirdArgName, memberPath);
|
|
1264
|
+
// If resolved successfully (not an error message), return it
|
|
1265
|
+
// console.log(`[DEBUG] Webpack resolved value: ${typeof resolved === 'object' ? JSON.stringify(resolved) : resolved}, starts with unresolved: ${String(resolved).startsWith("[unresolved:")}, starts with error: ${String(resolved).startsWith("[error")}`);
|
|
1266
|
+
if (resolved &&
|
|
1267
|
+
!String(resolved).startsWith("[unresolved:") &&
|
|
1268
|
+
!String(resolved).startsWith("[error")) {
|
|
1269
|
+
// console.log(`[DEBUG] RETURNING webpack resolved value: ${resolved}`);
|
|
1270
|
+
return resolved;
|
|
1271
|
+
}
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
let calleeName = "[unknown]";
|
|
1275
|
+
if (currentNode.callee.type === "Identifier") {
|
|
1276
|
+
calleeName = currentNode.callee.name;
|
|
1277
|
+
}
|
|
1278
|
+
// a lot of times, things like `"".concat(var1).concat(var2)` - which is basically multiple
|
|
1279
|
+
// .concat() with varying arguments end up here. They needs to be resolved as a string
|
|
1280
|
+
// first, match as regex
|
|
1281
|
+
if (nodeCode.replace(/\n\s*/g, "").match(/^"[^"]*"(\.concat\(.+\))+$/)) {
|
|
1282
|
+
// parse it separately with ast
|
|
1283
|
+
let ast;
|
|
1284
|
+
try {
|
|
1285
|
+
ast = parser.parse(nodeCode, {
|
|
1286
|
+
sourceType: "unambiguous",
|
|
1287
|
+
plugins: ["jsx", "typescript"],
|
|
1288
|
+
errorRecovery: true,
|
|
1289
|
+
});
|
|
1290
|
+
}
|
|
1291
|
+
catch (_c) {
|
|
1292
|
+
break;
|
|
1293
|
+
}
|
|
1294
|
+
// get all the concat calls first. Like .concat(...)
|
|
1295
|
+
// I want to only get concat() and nothing else. Also, it doesn't matter how many times they are called
|
|
1296
|
+
const concatCalls = [];
|
|
1297
|
+
const getArgValue = (arg) => {
|
|
1298
|
+
var _a;
|
|
1299
|
+
switch (arg.type) {
|
|
1300
|
+
case "StringLiteral":
|
|
1301
|
+
case "NumericLiteral":
|
|
1302
|
+
case "BooleanLiteral":
|
|
1303
|
+
return arg.value;
|
|
1304
|
+
case "NullLiteral":
|
|
1305
|
+
return null;
|
|
1306
|
+
case "Identifier":
|
|
1307
|
+
return `[var ${arg.name}]`; // Format identifiers as [var name]
|
|
1308
|
+
default:
|
|
1309
|
+
// @ts-ignore
|
|
1310
|
+
return `[${arg.type} -> ${arg.type === "MemberExpression" ? (_a = arg.property) === null || _a === void 0 ? void 0 : _a.name : ""}]`;
|
|
1311
|
+
}
|
|
1312
|
+
};
|
|
1313
|
+
traverse(ast, {
|
|
1314
|
+
CallExpression(path) {
|
|
1315
|
+
var _a;
|
|
1316
|
+
// We only want to start from the outermost `concat` call.
|
|
1317
|
+
if (path.node.callee.type !== "MemberExpression" ||
|
|
1318
|
+
path.node.callee.property.type !== "Identifier" ||
|
|
1319
|
+
path.node.callee.property.name !== "concat" ||
|
|
1320
|
+
path.parent.type === "MemberExpression") {
|
|
1321
|
+
return;
|
|
1322
|
+
}
|
|
1323
|
+
let current = path.node;
|
|
1324
|
+
while (current &&
|
|
1325
|
+
current.type === "CallExpression" &&
|
|
1326
|
+
current.callee.type === "MemberExpression") {
|
|
1327
|
+
const args = current.arguments.map(getArgValue);
|
|
1328
|
+
concatCalls.unshift(args);
|
|
1329
|
+
current = current.callee.object;
|
|
1330
|
+
}
|
|
1331
|
+
if (current) {
|
|
1332
|
+
if (current.type === "StringLiteral") {
|
|
1333
|
+
concatCalls.unshift([current.value]);
|
|
1334
|
+
}
|
|
1335
|
+
else if (current.type === "Identifier") {
|
|
1336
|
+
concatCalls.unshift([`[var ${current.name}]`]);
|
|
1337
|
+
}
|
|
1338
|
+
else {
|
|
1339
|
+
concatCalls.unshift([
|
|
1340
|
+
`[${current.type} -> ${current.type === "MemberExpression" ? (_a = current.property) === null || _a === void 0 ? void 0 : _a.name : ""}]`,
|
|
1341
|
+
]);
|
|
1342
|
+
}
|
|
1343
|
+
}
|
|
1344
|
+
// Stop traversal once we've processed the chain.
|
|
1345
|
+
path.stop();
|
|
1346
|
+
},
|
|
1347
|
+
});
|
|
1348
|
+
// process the concatCalls to return a single string
|
|
1349
|
+
if (concatCalls.length > 0) {
|
|
1350
|
+
const toReturn = concatCalls.flat().join("");
|
|
1351
|
+
return toReturn;
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
// Build a readable callee label for the placeholder
|
|
1355
|
+
let calleeLabel = calleeName !== "[unknown]" ? calleeName : "";
|
|
1356
|
+
if (!calleeLabel && currentNode.callee.type === "MemberExpression") {
|
|
1357
|
+
const parts = [];
|
|
1358
|
+
let c = currentNode.callee;
|
|
1359
|
+
while (c.type === "MemberExpression" && !c.computed && c.property.type === "Identifier") {
|
|
1360
|
+
parts.unshift(c.property.name);
|
|
1361
|
+
c = c.object;
|
|
1362
|
+
}
|
|
1363
|
+
if (c.type === "Identifier")
|
|
1364
|
+
parts.unshift(c.name);
|
|
1365
|
+
calleeLabel = parts.join(".");
|
|
1366
|
+
}
|
|
1367
|
+
return `[call:${calleeLabel || "?"}()]`;
|
|
1368
|
+
}
|
|
1369
|
+
case "AwaitExpression": {
|
|
1370
|
+
currentNode = currentNode.argument;
|
|
1371
|
+
continue;
|
|
1372
|
+
}
|
|
1373
|
+
case "NewExpression": {
|
|
1374
|
+
if (currentNode.callee.type === "Identifier" &&
|
|
1375
|
+
currentNode.callee.name === "URL" &&
|
|
1376
|
+
currentNode.arguments.length > 0) {
|
|
1377
|
+
currentNode = currentNode.arguments[0];
|
|
1378
|
+
continue;
|
|
1379
|
+
}
|
|
1380
|
+
if (currentNode.callee.type === "Identifier" &&
|
|
1381
|
+
currentNode.callee.name === "URLSearchParams" &&
|
|
1382
|
+
currentNode.arguments.length > 0) {
|
|
1383
|
+
const spArg = currentNode.arguments[0];
|
|
1384
|
+
// If the argument is a plain MemberExpression like `a.b`,
|
|
1385
|
+
// emit a typed marker so the downstream caller-substitution
|
|
1386
|
+
// pass knows this part of the URL is a query expansion of
|
|
1387
|
+
// an object reference, not just an inert placeholder.
|
|
1388
|
+
const memberChain = memberChainToString(spArg);
|
|
1389
|
+
if (memberChain && spArg.type === "MemberExpression" && !spArg.computed) {
|
|
1390
|
+
return `[urlsearchparams:${memberChain}]`;
|
|
1391
|
+
}
|
|
1392
|
+
if (spArg.type === "ObjectExpression") {
|
|
1393
|
+
const params = [];
|
|
1394
|
+
for (const prop of spArg.properties) {
|
|
1395
|
+
if (prop.type !== "ObjectProperty")
|
|
1396
|
+
continue;
|
|
1397
|
+
const key = prop.key.type === "Identifier"
|
|
1398
|
+
? prop.key.name
|
|
1399
|
+
: prop.key.type === "StringLiteral"
|
|
1400
|
+
? prop.key.value
|
|
1401
|
+
: null;
|
|
1402
|
+
if (!key)
|
|
1403
|
+
continue;
|
|
1404
|
+
const val = resolveNodeValue(prop.value, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1405
|
+
if (val === "[call_stack_exceeded_use_better_machine]")
|
|
1406
|
+
return val;
|
|
1407
|
+
// Use the literal value when fully resolved; otherwise use {key} as placeholder.
|
|
1408
|
+
const valStr = val !== null && val !== undefined && !String(val).startsWith("[")
|
|
1409
|
+
? encodeURIComponent(String(val))
|
|
1410
|
+
: `{${key}}`;
|
|
1411
|
+
params.push(`${key}=${valStr}`);
|
|
1412
|
+
}
|
|
1413
|
+
if (params.length > 0)
|
|
1414
|
+
return params.join("&");
|
|
1415
|
+
}
|
|
1416
|
+
// Non-object arg — try to resolve it directly
|
|
1417
|
+
const spResolved = resolveNodeValue(spArg, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1418
|
+
if (spResolved !== null &&
|
|
1419
|
+
spResolved !== undefined &&
|
|
1420
|
+
spResolved !== "[call_stack_exceeded_use_better_machine]") {
|
|
1421
|
+
return String(spResolved);
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
return `[unresolved new expression]`;
|
|
1425
|
+
}
|
|
1426
|
+
case "LogicalExpression": {
|
|
1427
|
+
const left = resolveNodeValue(currentNode.left, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1428
|
+
if (left === "[call_stack_exceeded_use_better_machine]") {
|
|
1429
|
+
return left;
|
|
1430
|
+
}
|
|
1431
|
+
else if (left && !String(left).startsWith("[")) {
|
|
1432
|
+
return left;
|
|
1433
|
+
}
|
|
1434
|
+
currentNode = currentNode.right;
|
|
1435
|
+
continue;
|
|
1436
|
+
}
|
|
1437
|
+
case "ConditionalExpression": {
|
|
1438
|
+
const consequent = resolveNodeValue(currentNode.consequent, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1439
|
+
if (consequent === "[call_stack_exceeded_use_better_machine]") {
|
|
1440
|
+
return consequent;
|
|
1441
|
+
}
|
|
1442
|
+
else if (consequent && !String(consequent).startsWith("[")) {
|
|
1443
|
+
return consequent;
|
|
1444
|
+
}
|
|
1445
|
+
currentNode = currentNode.alternate;
|
|
1446
|
+
continue;
|
|
1447
|
+
}
|
|
1448
|
+
case "BinaryExpression": {
|
|
1449
|
+
const left = resolveNodeValue(currentNode.left, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1450
|
+
if (left === "[call_stack_exceeded_use_better_machine]") {
|
|
1451
|
+
return left;
|
|
1452
|
+
}
|
|
1453
|
+
const right = resolveNodeValue(currentNode.right, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1454
|
+
if (right === "[call_stack_exceeded_use_better_machine]") {
|
|
1455
|
+
return right;
|
|
1456
|
+
}
|
|
1457
|
+
if (currentNode.operator === "+") {
|
|
1458
|
+
const leftOk = left !== null && left !== undefined;
|
|
1459
|
+
const rightOk = right !== null && right !== undefined;
|
|
1460
|
+
// Fully resolved — concatenate directly.
|
|
1461
|
+
if (leftOk && rightOk && !String(left).startsWith("[") && !String(right).startsWith("[")) {
|
|
1462
|
+
return left + right;
|
|
1463
|
+
}
|
|
1464
|
+
// Partially resolved — concatenate what we have so the caller
|
|
1465
|
+
// at least sees the resolvable fragments alongside the placeholders.
|
|
1466
|
+
if (leftOk && rightOk) {
|
|
1467
|
+
return `${left}${right}`;
|
|
1468
|
+
}
|
|
1469
|
+
if (leftOk)
|
|
1470
|
+
return String(left);
|
|
1471
|
+
if (rightOk)
|
|
1472
|
+
return String(right);
|
|
1473
|
+
}
|
|
1474
|
+
return `[unresolved binary expression: ${currentNode.operator}]`;
|
|
1475
|
+
}
|
|
1476
|
+
case "ArrayExpression": {
|
|
1477
|
+
const elements = [];
|
|
1478
|
+
for (const element of currentNode.elements) {
|
|
1479
|
+
if (element === null) {
|
|
1480
|
+
elements.push(null);
|
|
1481
|
+
continue;
|
|
1482
|
+
}
|
|
1483
|
+
const resolved = resolveNodeValue(element, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1484
|
+
if (resolved === "[call_stack_exceeded_use_better_machine]")
|
|
1485
|
+
return resolved;
|
|
1486
|
+
elements.push(resolved);
|
|
1487
|
+
}
|
|
1488
|
+
return elements;
|
|
1489
|
+
}
|
|
1490
|
+
case "UnaryExpression": {
|
|
1491
|
+
if (currentNode.operator === "void")
|
|
1492
|
+
return null;
|
|
1493
|
+
const operand = resolveNodeValue(currentNode.argument, scope, nodeCode, callType, chunkCode, chunks, thirdArgName);
|
|
1494
|
+
if (operand === "[call_stack_exceeded_use_better_machine]")
|
|
1495
|
+
return operand;
|
|
1496
|
+
if (currentNode.operator === "!") {
|
|
1497
|
+
if (typeof operand === "boolean")
|
|
1498
|
+
return !operand;
|
|
1499
|
+
if (typeof operand === "number")
|
|
1500
|
+
return operand === 0;
|
|
1501
|
+
return "<boolean>";
|
|
1502
|
+
}
|
|
1503
|
+
if (currentNode.operator === "-") {
|
|
1504
|
+
if (typeof operand === "number")
|
|
1505
|
+
return -operand;
|
|
1506
|
+
return "<number>";
|
|
1507
|
+
}
|
|
1508
|
+
if (currentNode.operator === "typeof")
|
|
1509
|
+
return "<string>";
|
|
1510
|
+
return "<unknown>";
|
|
1511
|
+
}
|
|
1512
|
+
default:
|
|
1513
|
+
return `[unsupported node type: ${currentNode.type}]`;
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
return null;
|
|
1517
|
+
}
|
|
1518
|
+
catch (e) {
|
|
1519
|
+
// check if it's a "Maximum call stack size exceeded" error
|
|
1520
|
+
if (e instanceof RangeError && e.message.includes("Maximum call stack size exceeded")) {
|
|
1521
|
+
return "[call_stack_exceeded_use_better_machine]";
|
|
1522
|
+
// console.error("[error] Maximum call stack size exceeded. Please use a better machine.");
|
|
1523
|
+
// process.exit(21);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
};
|
|
1527
|
+
/**
|
|
1528
|
+
* Resolves string concatenation operations to flatten concat chains.
|
|
1529
|
+
*
|
|
1530
|
+
* Handles patterns like '"/api/teams/".concat(i, "/members")' by:
|
|
1531
|
+
* - Parsing the string literal and concat arguments
|
|
1532
|
+
* - Replacing variables with placeholder strings like '[var name]'
|
|
1533
|
+
* - Flattening the entire concatenation chain into a single string
|
|
1534
|
+
* - Respecting quoted strings and handling nested expressions
|
|
1535
|
+
*
|
|
1536
|
+
* @param rawExpr - The raw expression string containing concat operations
|
|
1537
|
+
* @returns Flattened string with variable placeholders
|
|
1538
|
+
*/
|
|
1539
|
+
export const resolveStringOps = (rawExpr) => {
|
|
1540
|
+
if (!rawExpr || typeof rawExpr !== "string")
|
|
1541
|
+
return rawExpr;
|
|
1542
|
+
// Quick check for pattern "<string literal>.concat(... )"
|
|
1543
|
+
const concatMatch = rawExpr.match(/^(\s*["'`])(.*?)(\1)\.concat\(([\s\S]*)\)$/);
|
|
1544
|
+
if (!concatMatch) {
|
|
1545
|
+
// Not in expected pattern – return as-is for now.
|
|
1546
|
+
return rawExpr;
|
|
1547
|
+
}
|
|
1548
|
+
const leadingLiteral = concatMatch[2];
|
|
1549
|
+
const argsPart = concatMatch[4]; // everything inside the concat(...)
|
|
1550
|
+
// Split arguments respecting quotes. We'll do a naive split on commas that are not inside quotes.
|
|
1551
|
+
const args = [];
|
|
1552
|
+
let current = "";
|
|
1553
|
+
let inSingle = false;
|
|
1554
|
+
let inDouble = false;
|
|
1555
|
+
let inBacktick = false;
|
|
1556
|
+
for (let i = 0; i < argsPart.length; i++) {
|
|
1557
|
+
const ch = argsPart[i];
|
|
1558
|
+
if (ch === "'" && !inDouble && !inBacktick) {
|
|
1559
|
+
inSingle = !inSingle;
|
|
1560
|
+
current += ch;
|
|
1561
|
+
continue;
|
|
1562
|
+
}
|
|
1563
|
+
if (ch === '"' && !inSingle && !inBacktick) {
|
|
1564
|
+
inDouble = !inDouble;
|
|
1565
|
+
current += ch;
|
|
1566
|
+
continue;
|
|
1567
|
+
}
|
|
1568
|
+
if (ch === "`" && !inSingle && !inDouble) {
|
|
1569
|
+
inBacktick = !inBacktick;
|
|
1570
|
+
current += ch;
|
|
1571
|
+
continue;
|
|
1572
|
+
}
|
|
1573
|
+
if (ch === "," && !inSingle && !inDouble && !inBacktick) {
|
|
1574
|
+
args.push(current.trim());
|
|
1575
|
+
current = "";
|
|
1576
|
+
continue;
|
|
1577
|
+
}
|
|
1578
|
+
current += ch;
|
|
1579
|
+
}
|
|
1580
|
+
if (current.trim() !== "")
|
|
1581
|
+
args.push(current.trim());
|
|
1582
|
+
// Build resolved string
|
|
1583
|
+
let result = leadingLiteral;
|
|
1584
|
+
for (const arg of args) {
|
|
1585
|
+
const trimmed = arg.trim();
|
|
1586
|
+
if (/^['"`].*['"`]$/.test(trimmed)) {
|
|
1587
|
+
// string literal – strip quotes
|
|
1588
|
+
result += trimmed.slice(1, -1);
|
|
1589
|
+
}
|
|
1590
|
+
else if (trimmed.length) {
|
|
1591
|
+
// treat as identifier / expression – replace with placeholder
|
|
1592
|
+
// attempt to extract simple identifier name if possible
|
|
1593
|
+
const idMatch = trimmed.match(/^[a-zA-Z_$][a-zA-Z0-9_$]*/);
|
|
1594
|
+
const idName = idMatch ? idMatch[0] : trimmed;
|
|
1595
|
+
result += `[var ${idName}]`;
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
return result;
|
|
1599
|
+
};
|
|
1600
|
+
//# sourceMappingURL=utils.js.map
|