@wyw-in-js/transform 1.0.8 → 2.0.0-alpha.0
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/esm/cache.js +426 -289
- package/esm/cache.js.map +1 -1
- package/esm/debug/fileReporter.js +137 -134
- package/esm/debug/fileReporter.js.map +1 -1
- package/esm/eval/broker.js +2134 -0
- package/esm/eval/broker.js.map +1 -0
- package/esm/eval/lru.js +36 -0
- package/esm/eval/lru.js.map +1 -0
- package/esm/eval/prepareModuleOnDemand.js +21 -0
- package/esm/eval/prepareModuleOnDemand.js.map +1 -0
- package/esm/eval/protocol.js +2 -0
- package/esm/eval/protocol.js.map +1 -0
- package/esm/eval/resolverStrategy.js +51 -0
- package/esm/eval/resolverStrategy.js.map +1 -0
- package/esm/eval/runner.js +1759 -0
- package/esm/eval/runner.js.map +1 -0
- package/esm/eval/serialize.js +333 -0
- package/esm/eval/serialize.js.map +1 -0
- package/esm/eval/writeQueue.js +81 -0
- package/esm/eval/writeQueue.js.map +1 -0
- package/esm/evaluators/index.js +11 -12
- package/esm/evaluators/index.js.map +1 -1
- package/esm/index.js +25 -28
- package/esm/index.js.map +1 -1
- package/esm/module.js +896 -520
- package/esm/module.js.map +1 -1
- package/esm/shaker.js +14 -80
- package/esm/shaker.js.map +1 -1
- package/esm/transform/BaseEntrypoint.js +162 -164
- package/esm/transform/BaseEntrypoint.js.map +1 -1
- package/esm/transform/Entrypoint.helpers.js +96 -253
- package/esm/transform/Entrypoint.helpers.js.map +1 -1
- package/esm/transform/Entrypoint.js +336 -270
- package/esm/transform/Entrypoint.js.map +1 -1
- package/esm/transform/Entrypoint.types.js +1 -1
- package/esm/transform/Entrypoint.types.js.map +1 -1
- package/esm/transform/EvaluatedEntrypoint.js +10 -4
- package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
- package/esm/transform/actions/AbortError.js +6 -6
- package/esm/transform/actions/AbortError.js.map +1 -1
- package/esm/transform/actions/BaseAction.js +140 -136
- package/esm/transform/actions/BaseAction.js.map +1 -1
- package/esm/transform/actions/UnprocessedEntrypointError.js +6 -6
- package/esm/transform/actions/UnprocessedEntrypointError.js.map +1 -1
- package/esm/transform/actions/actionRunner.js +63 -66
- package/esm/transform/actions/actionRunner.js.map +1 -1
- package/esm/transform/actions/types.js +1 -1
- package/esm/transform/actions/types.js.map +1 -1
- package/esm/transform/barrelManifest.types.js +2 -0
- package/esm/transform/barrelManifest.types.js.map +1 -0
- package/esm/transform/generators/baseProcessingHandlers.js +15 -17
- package/esm/transform/generators/baseProcessingHandlers.js.map +1 -1
- package/esm/transform/generators/collect.js +27 -55
- package/esm/transform/generators/collect.js.map +1 -1
- package/esm/transform/generators/createStylisPreprocessor.js +353 -321
- package/esm/transform/generators/createStylisPreprocessor.js.map +1 -1
- package/esm/transform/generators/evalFile.js +48 -47
- package/esm/transform/generators/evalFile.js.map +1 -1
- package/esm/transform/generators/extract.js +78 -90
- package/esm/transform/generators/extract.js.map +1 -1
- package/esm/transform/generators/getExports.js +57 -74
- package/esm/transform/generators/getExports.js.map +1 -1
- package/esm/transform/generators/index.js +11 -11
- package/esm/transform/generators/index.js.map +1 -1
- package/esm/transform/generators/processEntrypoint.js +78 -67
- package/esm/transform/generators/processEntrypoint.js.map +1 -1
- package/esm/transform/generators/processImports.js +102 -67
- package/esm/transform/generators/processImports.js.map +1 -1
- package/esm/transform/generators/resolveImports.js +165 -196
- package/esm/transform/generators/resolveImports.js.map +1 -1
- package/esm/transform/generators/resolveStaticOxcValues.js +2911 -0
- package/esm/transform/generators/resolveStaticOxcValues.js.map +1 -0
- package/esm/transform/generators/rewriteOxcBarrelImports.js +822 -0
- package/esm/transform/generators/rewriteOxcBarrelImports.js.map +1 -0
- package/esm/transform/generators/transform.js +239 -248
- package/esm/transform/generators/transform.js.map +1 -1
- package/esm/transform/generators/workflow.js +87 -79
- package/esm/transform/generators/workflow.js.map +1 -1
- package/esm/transform/helpers/loadWywOptions.js +154 -73
- package/esm/transform/helpers/loadWywOptions.js.map +1 -1
- package/esm/transform/helpers/withDefaultServices.js +13 -22
- package/esm/transform/helpers/withDefaultServices.js.map +1 -1
- package/esm/transform/isStaticallyEvaluatableModule.js +140 -152
- package/esm/transform/isStaticallyEvaluatableModule.js.map +1 -1
- package/esm/transform/oxcBarrelManifest.js +349 -0
- package/esm/transform/oxcBarrelManifest.js.map +1 -0
- package/esm/transform/rootLog.js +3 -3
- package/esm/transform/rootLog.js.map +1 -1
- package/esm/transform/syntax.js +2 -0
- package/esm/transform/syntax.js.map +1 -0
- package/esm/transform/types.js +2 -2
- package/esm/transform/types.js.map +1 -1
- package/esm/transform.js +123 -147
- package/esm/transform.js.map +1 -1
- package/esm/types.js +4 -1
- package/esm/types.js.map +1 -1
- package/esm/utils/EventEmitter.js +46 -48
- package/esm/utils/EventEmitter.js.map +1 -1
- package/esm/utils/ShakerMetadata.js +2 -2
- package/esm/utils/ShakerMetadata.js.map +1 -1
- package/esm/utils/TransformDiagnostics.js +10 -0
- package/esm/utils/TransformDiagnostics.js.map +1 -0
- package/esm/utils/TransformMetadata.js +28 -10
- package/esm/utils/TransformMetadata.js.map +1 -1
- package/esm/utils/applyOxcProcessors.js +1217 -0
- package/esm/utils/applyOxcProcessors.js.map +1 -0
- package/esm/utils/collectOxcExportsAndImports.js +934 -0
- package/esm/utils/collectOxcExportsAndImports.js.map +1 -0
- package/esm/utils/collectOxcRuntime.js +220 -0
- package/esm/utils/collectOxcRuntime.js.map +1 -0
- package/esm/utils/collectOxcTemplateDependencies.js +1398 -0
- package/esm/utils/collectOxcTemplateDependencies.js.map +1 -0
- package/esm/utils/dispose-polyfill.js +3 -4
- package/esm/utils/dispose-polyfill.js.map +1 -1
- package/esm/utils/getFileIdx.js +6 -6
- package/esm/utils/getFileIdx.js.map +1 -1
- package/esm/utils/getPluginKey.js +12 -12
- package/esm/utils/getPluginKey.js.map +1 -1
- package/esm/utils/getVisitorKeys.js +9 -3
- package/esm/utils/getVisitorKeys.js.map +1 -1
- package/esm/utils/hasCachedWywPrevalExport.js +23 -0
- package/esm/utils/hasCachedWywPrevalExport.js.map +1 -0
- package/esm/utils/hasWywPreval.js +5 -5
- package/esm/utils/hasWywPreval.js.map +1 -1
- package/esm/utils/importOverrides.js +75 -90
- package/esm/utils/importOverrides.js.map +1 -1
- package/esm/utils/isNode.js +2 -2
- package/esm/utils/isNode.js.map +1 -1
- package/esm/utils/isNotNull.js +2 -2
- package/esm/utils/isNotNull.js.map +1 -1
- package/esm/utils/isSerializable.js +11 -11
- package/esm/utils/isSerializable.js.map +1 -1
- package/esm/utils/oxcAstService.js +121 -0
- package/esm/utils/oxcAstService.js.map +1 -0
- package/esm/utils/oxcEmit.js +447 -0
- package/esm/utils/oxcEmit.js.map +1 -0
- package/esm/utils/oxcPreevalStage.js +97 -0
- package/esm/utils/oxcPreevalStage.js.map +1 -0
- package/esm/utils/oxcPreevalTransforms.js +1054 -0
- package/esm/utils/oxcPreevalTransforms.js.map +1 -0
- package/esm/utils/oxcShaker.js +662 -0
- package/esm/utils/oxcShaker.js.map +1 -0
- package/esm/utils/parseOxc.js +37 -0
- package/esm/utils/parseOxc.js.map +1 -0
- package/esm/utils/parseRequest.js +27 -27
- package/esm/utils/parseRequest.js.map +1 -1
- package/esm/utils/peek.js +1 -1
- package/esm/utils/peek.js.map +1 -1
- package/esm/utils/processorLookup.js +125 -0
- package/esm/utils/processorLookup.js.map +1 -0
- package/esm/utils/resolveWithConditions.js +99 -0
- package/esm/utils/resolveWithConditions.js.map +1 -0
- package/esm/vm/createVmContext.js +140 -141
- package/esm/vm/createVmContext.js.map +1 -1
- package/esm/vm/process.js +11 -13
- package/esm/vm/process.js.map +1 -1
- package/package.json +18 -26
- package/types/cache.d.ts +17 -8
- package/types/cache.js +237 -95
- package/types/debug/fileReporter.js +22 -22
- package/types/eval/broker.d.ts +88 -0
- package/types/eval/broker.js +2262 -0
- package/types/eval/lru.d.ts +10 -0
- package/types/eval/lru.js +36 -0
- package/types/eval/prepareModuleOnDemand.d.ts +7 -0
- package/types/eval/prepareModuleOnDemand.js +24 -0
- package/types/eval/protocol.d.ts +97 -0
- package/types/eval/protocol.js +1 -0
- package/types/eval/resolverStrategy.d.ts +13 -0
- package/types/eval/resolverStrategy.js +46 -0
- package/types/eval/serialize.d.ts +78 -0
- package/types/eval/serialize.js +357 -0
- package/types/eval/writeQueue.d.ts +13 -0
- package/types/eval/writeQueue.js +80 -0
- package/types/evaluators/index.d.ts +2 -2
- package/types/evaluators/index.js +6 -9
- package/types/index.d.ts +7 -8
- package/types/index.js +24 -77
- package/types/module.d.ts +35 -7
- package/types/module.js +535 -163
- package/types/shaker.d.ts +2 -10
- package/types/shaker.js +10 -100
- package/types/transform/BaseEntrypoint.js +6 -11
- package/types/transform/Entrypoint.d.ts +15 -15
- package/types/transform/Entrypoint.helpers.d.ts +2 -5
- package/types/transform/Entrypoint.helpers.js +43 -203
- package/types/transform/Entrypoint.js +130 -53
- package/types/transform/Entrypoint.types.d.ts +28 -6
- package/types/transform/Entrypoint.types.js +1 -2
- package/types/transform/EvaluatedEntrypoint.d.ts +13 -2
- package/types/transform/EvaluatedEntrypoint.js +7 -6
- package/types/transform/actions/AbortError.js +2 -7
- package/types/transform/actions/BaseAction.js +4 -8
- package/types/transform/actions/UnprocessedEntrypointError.js +2 -7
- package/types/transform/actions/actionRunner.js +8 -12
- package/types/transform/actions/types.d.ts +6 -2
- package/types/transform/actions/types.js +1 -2
- package/types/transform/{barrelManifest.d.ts → barrelManifest.types.d.ts} +0 -2
- package/types/transform/barrelManifest.types.js +1 -0
- package/types/transform/generators/baseProcessingHandlers.d.ts +4 -5
- package/types/transform/generators/baseProcessingHandlers.js +10 -14
- package/types/transform/generators/collect.js +13 -39
- package/types/transform/generators/createStylisPreprocessor.js +19 -60
- package/types/transform/generators/evalFile.d.ts +2 -2
- package/types/transform/generators/evalFile.js +26 -28
- package/types/transform/generators/extract.js +5 -8
- package/types/transform/generators/getExports.js +23 -30
- package/types/transform/generators/index.d.ts +2 -2
- package/types/transform/generators/index.js +11 -14
- package/types/transform/generators/processEntrypoint.d.ts +2 -2
- package/types/transform/generators/processEntrypoint.js +60 -26
- package/types/transform/generators/processImports.d.ts +0 -3
- package/types/transform/generators/processImports.js +60 -20
- package/types/transform/generators/resolveImports.js +18 -22
- package/types/transform/generators/resolveStaticOxcValues.d.ts +2 -0
- package/types/transform/generators/resolveStaticOxcValues.js +3235 -0
- package/types/transform/generators/{rewriteBarrelImports.d.ts → rewriteOxcBarrelImports.d.ts} +2 -3
- package/types/transform/generators/{rewriteBarrelImports.js → rewriteOxcBarrelImports.js} +282 -225
- package/types/transform/generators/transform.d.ts +3 -7
- package/types/transform/generators/transform.js +203 -199
- package/types/transform/generators/workflow.js +62 -37
- package/types/transform/helpers/loadWywOptions.js +95 -20
- package/types/transform/helpers/withDefaultServices.d.ts +1 -1
- package/types/transform/helpers/withDefaultServices.js +6 -44
- package/types/transform/isStaticallyEvaluatableModule.d.ts +1 -2
- package/types/transform/isStaticallyEvaluatableModule.js +125 -126
- package/types/transform/oxcBarrelManifest.d.ts +2 -0
- package/types/transform/{barrelManifest.js → oxcBarrelManifest.js} +156 -97
- package/types/transform/rootLog.js +2 -5
- package/types/transform/syntax.d.ts +38 -0
- package/types/transform/syntax.js +1 -0
- package/types/transform/types.d.ts +9 -6
- package/types/transform/types.js +1 -4
- package/types/transform.d.ts +2 -2
- package/types/transform.js +88 -101
- package/types/types.d.ts +4 -24
- package/types/types.js +1 -2
- package/types/utils/EventEmitter.js +3 -9
- package/types/utils/ShakerMetadata.js +1 -5
- package/types/utils/TransformDiagnostics.d.ts +9 -0
- package/types/utils/TransformDiagnostics.js +11 -0
- package/types/utils/TransformMetadata.d.ts +22 -4
- package/types/utils/TransformMetadata.js +23 -8
- package/types/utils/applyOxcProcessors.d.ts +16 -0
- package/types/utils/applyOxcProcessors.js +1391 -0
- package/types/utils/collectOxcExportsAndImports.d.ts +35 -0
- package/types/utils/collectOxcExportsAndImports.js +957 -0
- package/types/utils/collectOxcRuntime.d.ts +14 -0
- package/types/utils/collectOxcRuntime.js +250 -0
- package/types/utils/collectOxcTemplateDependencies.d.ts +38 -0
- package/types/utils/collectOxcTemplateDependencies.js +1580 -0
- package/types/utils/getFileIdx.js +1 -4
- package/types/utils/getPluginKey.d.ts +5 -2
- package/types/utils/getPluginKey.js +2 -6
- package/types/utils/getVisitorKeys.d.ts +4 -4
- package/types/utils/getVisitorKeys.js +9 -6
- package/types/utils/hasCachedWywPrevalExport.d.ts +14 -0
- package/types/utils/hasCachedWywPrevalExport.js +30 -0
- package/types/utils/hasWywPreval.js +1 -4
- package/types/utils/importOverrides.js +17 -27
- package/types/utils/isNode.d.ts +2 -2
- package/types/utils/isNode.js +2 -6
- package/types/utils/isNotNull.js +1 -4
- package/types/utils/isSerializable.js +3 -6
- package/types/utils/oxcAstService.d.ts +11 -0
- package/types/utils/oxcAstService.js +79 -0
- package/types/utils/oxcEmit.d.ts +19 -0
- package/types/utils/oxcEmit.js +506 -0
- package/types/utils/oxcPreevalStage.d.ts +20 -0
- package/types/utils/oxcPreevalStage.js +102 -0
- package/types/utils/oxcPreevalTransforms.d.ts +13 -0
- package/types/utils/oxcPreevalTransforms.js +1179 -0
- package/types/utils/oxcShaker.d.ts +13 -0
- package/types/utils/oxcShaker.js +751 -0
- package/types/utils/parseOxc.d.ts +11 -0
- package/types/utils/parseOxc.js +38 -0
- package/types/utils/parseRequest.js +2 -7
- package/types/utils/peek.js +1 -5
- package/types/utils/processorLookup.d.ts +8 -0
- package/types/utils/processorLookup.js +135 -0
- package/types/utils/resolveWithConditions.d.ts +12 -0
- package/types/utils/resolveWithConditions.js +103 -0
- package/types/vm/createVmContext.d.ts +2 -2
- package/types/vm/createVmContext.js +25 -62
- package/types/vm/process.js +20 -26
- package/esm/babel.js +0 -2
- package/esm/babel.js.map +0 -1
- package/esm/options/buildOptions.js +0 -168
- package/esm/options/buildOptions.js.map +0 -1
- package/esm/options/buildOptions.test.js +0 -138
- package/esm/options/buildOptions.test.js.map +0 -1
- package/esm/options/loadBabelOptions.js +0 -24
- package/esm/options/loadBabelOptions.js.map +0 -1
- package/esm/plugins/babel-transform.js +0 -53
- package/esm/plugins/babel-transform.js.map +0 -1
- package/esm/plugins/collector.js +0 -60
- package/esm/plugins/collector.js.map +0 -1
- package/esm/plugins/dynamic-import.js +0 -56
- package/esm/plugins/dynamic-import.js.map +0 -1
- package/esm/plugins/preeval.js +0 -73
- package/esm/plugins/preeval.js.map +0 -1
- package/esm/plugins/shaker.js +0 -680
- package/esm/plugins/shaker.js.map +0 -1
- package/esm/transform/barrelManifest.js +0 -291
- package/esm/transform/barrelManifest.js.map +0 -1
- package/esm/transform/generators/explodeReexports.js +0 -64
- package/esm/transform/generators/explodeReexports.js.map +0 -1
- package/esm/transform/generators/rewriteBarrelImports.js +0 -733
- package/esm/transform/generators/rewriteBarrelImports.js.map +0 -1
- package/esm/utils/addIdentifierToWywPreval.js +0 -68
- package/esm/utils/addIdentifierToWywPreval.js.map +0 -1
- package/esm/utils/collectExportsAndImports.js +0 -1157
- package/esm/utils/collectExportsAndImports.js.map +0 -1
- package/esm/utils/collectTemplateDependencies.js +0 -228
- package/esm/utils/collectTemplateDependencies.js.map +0 -1
- package/esm/utils/createId.js +0 -6
- package/esm/utils/createId.js.map +0 -1
- package/esm/utils/findIdentifiers.js +0 -62
- package/esm/utils/findIdentifiers.js.map +0 -1
- package/esm/utils/getConstantStringValue.js +0 -58
- package/esm/utils/getConstantStringValue.js.map +0 -1
- package/esm/utils/getMemberExpressionPropertyName.js +0 -11
- package/esm/utils/getMemberExpressionPropertyName.js.map +0 -1
- package/esm/utils/getScope.js +0 -6
- package/esm/utils/getScope.js.map +0 -1
- package/esm/utils/getSource.js +0 -15
- package/esm/utils/getSource.js.map +0 -1
- package/esm/utils/getTagProcessor.js +0 -404
- package/esm/utils/getTagProcessor.js.map +0 -1
- package/esm/utils/isExports.js +0 -22
- package/esm/utils/isExports.js.map +0 -1
- package/esm/utils/isGlobal.js +0 -6
- package/esm/utils/isGlobal.js.map +0 -1
- package/esm/utils/isNodePath.js +0 -4
- package/esm/utils/isNodePath.js.map +0 -1
- package/esm/utils/isRemoved.js +0 -46
- package/esm/utils/isRemoved.js.map +0 -1
- package/esm/utils/isRequire.js +0 -13
- package/esm/utils/isRequire.js.map +0 -1
- package/esm/utils/isTypedNode.js +0 -6
- package/esm/utils/isTypedNode.js.map +0 -1
- package/esm/utils/isUnnecessaryReactCall.js +0 -72
- package/esm/utils/isUnnecessaryReactCall.js.map +0 -1
- package/esm/utils/removeDangerousCode.js +0 -276
- package/esm/utils/removeDangerousCode.js.map +0 -1
- package/esm/utils/replaceImportMetaEnv.js +0 -44
- package/esm/utils/replaceImportMetaEnv.js.map +0 -1
- package/esm/utils/scopeHelpers.js +0 -527
- package/esm/utils/scopeHelpers.js.map +0 -1
- package/esm/utils/traversalCache.js +0 -23
- package/esm/utils/traversalCache.js.map +0 -1
- package/esm/utils/unwrapExpression.js +0 -18
- package/esm/utils/unwrapExpression.js.map +0 -1
- package/esm/utils/unwrapSequence.js +0 -14
- package/esm/utils/unwrapSequence.js.map +0 -1
- package/esm/utils/valueToLiteral.js +0 -59
- package/esm/utils/valueToLiteral.js.map +0 -1
- package/esm/utils/visitors/JSXElementsRemover.js +0 -51
- package/esm/utils/visitors/JSXElementsRemover.js.map +0 -1
- package/lib/babel.js +0 -2
- package/lib/babel.js.map +0 -1
- package/lib/cache.js +0 -308
- package/lib/cache.js.map +0 -1
- package/lib/debug/fileReporter.js +0 -153
- package/lib/debug/fileReporter.js.map +0 -1
- package/lib/evaluators/index.js +0 -20
- package/lib/evaluators/index.js.map +0 -1
- package/lib/index.js +0 -257
- package/lib/index.js.map +0 -1
- package/lib/module.js +0 -552
- package/lib/module.js.map +0 -1
- package/lib/options/buildOptions.js +0 -176
- package/lib/options/buildOptions.js.map +0 -1
- package/lib/options/buildOptions.test.js +0 -141
- package/lib/options/buildOptions.test.js.map +0 -1
- package/lib/options/loadBabelOptions.js +0 -31
- package/lib/options/loadBabelOptions.js.map +0 -1
- package/lib/plugins/babel-transform.js +0 -60
- package/lib/plugins/babel-transform.js.map +0 -1
- package/lib/plugins/collector.js +0 -70
- package/lib/plugins/collector.js.map +0 -1
- package/lib/plugins/dynamic-import.js +0 -61
- package/lib/plugins/dynamic-import.js.map +0 -1
- package/lib/plugins/preeval.js +0 -81
- package/lib/plugins/preeval.js.map +0 -1
- package/lib/plugins/shaker.js +0 -691
- package/lib/plugins/shaker.js.map +0 -1
- package/lib/shaker.js +0 -95
- package/lib/shaker.js.map +0 -1
- package/lib/transform/BaseEntrypoint.js +0 -179
- package/lib/transform/BaseEntrypoint.js.map +0 -1
- package/lib/transform/Entrypoint.helpers.js +0 -279
- package/lib/transform/Entrypoint.helpers.js.map +0 -1
- package/lib/transform/Entrypoint.js +0 -289
- package/lib/transform/Entrypoint.js.map +0 -1
- package/lib/transform/Entrypoint.types.js +0 -2
- package/lib/transform/Entrypoint.types.js.map +0 -1
- package/lib/transform/EvaluatedEntrypoint.js +0 -13
- package/lib/transform/EvaluatedEntrypoint.js.map +0 -1
- package/lib/transform/actions/AbortError.js +0 -16
- package/lib/transform/actions/AbortError.js.map +0 -1
- package/lib/transform/actions/BaseAction.js +0 -150
- package/lib/transform/actions/BaseAction.js.map +0 -1
- package/lib/transform/actions/UnprocessedEntrypointError.js +0 -16
- package/lib/transform/actions/UnprocessedEntrypointError.js.map +0 -1
- package/lib/transform/actions/actionRunner.js +0 -82
- package/lib/transform/actions/actionRunner.js.map +0 -1
- package/lib/transform/actions/types.js +0 -2
- package/lib/transform/actions/types.js.map +0 -1
- package/lib/transform/barrelManifest.js +0 -300
- package/lib/transform/barrelManifest.js.map +0 -1
- package/lib/transform/generators/baseProcessingHandlers.js +0 -27
- package/lib/transform/generators/baseProcessingHandlers.js.map +0 -1
- package/lib/transform/generators/collect.js +0 -66
- package/lib/transform/generators/collect.js.map +0 -1
- package/lib/transform/generators/createStylisPreprocessor.js +0 -372
- package/lib/transform/generators/createStylisPreprocessor.js.map +0 -1
- package/lib/transform/generators/evalFile.js +0 -57
- package/lib/transform/generators/evalFile.js.map +0 -1
- package/lib/transform/generators/explodeReexports.js +0 -71
- package/lib/transform/generators/explodeReexports.js.map +0 -1
- package/lib/transform/generators/extract.js +0 -102
- package/lib/transform/generators/extract.js.map +0 -1
- package/lib/transform/generators/getExports.js +0 -85
- package/lib/transform/generators/getExports.js.map +0 -1
- package/lib/transform/generators/index.js +0 -19
- package/lib/transform/generators/index.js.map +0 -1
- package/lib/transform/generators/processEntrypoint.js +0 -76
- package/lib/transform/generators/processEntrypoint.js.map +0 -1
- package/lib/transform/generators/processImports.js +0 -82
- package/lib/transform/generators/processImports.js.map +0 -1
- package/lib/transform/generators/resolveImports.js +0 -221
- package/lib/transform/generators/resolveImports.js.map +0 -1
- package/lib/transform/generators/rewriteBarrelImports.js +0 -743
- package/lib/transform/generators/rewriteBarrelImports.js.map +0 -1
- package/lib/transform/generators/transform.js +0 -272
- package/lib/transform/generators/transform.js.map +0 -1
- package/lib/transform/generators/workflow.js +0 -90
- package/lib/transform/generators/workflow.js.map +0 -1
- package/lib/transform/helpers/loadWywOptions.js +0 -87
- package/lib/transform/helpers/loadWywOptions.js.map +0 -1
- package/lib/transform/helpers/withDefaultServices.js +0 -31
- package/lib/transform/helpers/withDefaultServices.js.map +0 -1
- package/lib/transform/isStaticallyEvaluatableModule.js +0 -159
- package/lib/transform/isStaticallyEvaluatableModule.js.map +0 -1
- package/lib/transform/rootLog.js +0 -9
- package/lib/transform/rootLog.js.map +0 -1
- package/lib/transform/types.js +0 -8
- package/lib/transform/types.js.map +0 -1
- package/lib/transform.js +0 -160
- package/lib/transform.js.map +0 -1
- package/lib/types.js +0 -2
- package/lib/types.js.map +0 -1
- package/lib/utils/EventEmitter.js +0 -61
- package/lib/utils/EventEmitter.js.map +0 -1
- package/lib/utils/ShakerMetadata.js +0 -9
- package/lib/utils/ShakerMetadata.js.map +0 -1
- package/lib/utils/TransformMetadata.js +0 -19
- package/lib/utils/TransformMetadata.js.map +0 -1
- package/lib/utils/addIdentifierToWywPreval.js +0 -75
- package/lib/utils/addIdentifierToWywPreval.js.map +0 -1
- package/lib/utils/collectExportsAndImports.js +0 -1173
- package/lib/utils/collectExportsAndImports.js.map +0 -1
- package/lib/utils/collectTemplateDependencies.js +0 -242
- package/lib/utils/collectTemplateDependencies.js.map +0 -1
- package/lib/utils/createId.js +0 -13
- package/lib/utils/createId.js.map +0 -1
- package/lib/utils/dispose-polyfill.js +0 -9
- package/lib/utils/dispose-polyfill.js.map +0 -1
- package/lib/utils/findIdentifiers.js +0 -73
- package/lib/utils/findIdentifiers.js.map +0 -1
- package/lib/utils/getConstantStringValue.js +0 -66
- package/lib/utils/getConstantStringValue.js.map +0 -1
- package/lib/utils/getFileIdx.js +0 -16
- package/lib/utils/getFileIdx.js.map +0 -1
- package/lib/utils/getMemberExpressionPropertyName.js +0 -18
- package/lib/utils/getMemberExpressionPropertyName.js.map +0 -1
- package/lib/utils/getPluginKey.js +0 -21
- package/lib/utils/getPluginKey.js.map +0 -1
- package/lib/utils/getScope.js +0 -12
- package/lib/utils/getScope.js.map +0 -1
- package/lib/utils/getSource.js +0 -24
- package/lib/utils/getSource.js.map +0 -1
- package/lib/utils/getTagProcessor.js +0 -424
- package/lib/utils/getTagProcessor.js.map +0 -1
- package/lib/utils/getVisitorKeys.js +0 -11
- package/lib/utils/getVisitorKeys.js.map +0 -1
- package/lib/utils/hasWywPreval.js +0 -13
- package/lib/utils/hasWywPreval.js.map +0 -1
- package/lib/utils/importOverrides.js +0 -119
- package/lib/utils/importOverrides.js.map +0 -1
- package/lib/utils/isExports.js +0 -27
- package/lib/utils/isExports.js.map +0 -1
- package/lib/utils/isGlobal.js +0 -13
- package/lib/utils/isGlobal.js.map +0 -1
- package/lib/utils/isNode.js +0 -9
- package/lib/utils/isNode.js.map +0 -1
- package/lib/utils/isNodePath.js +0 -10
- package/lib/utils/isNodePath.js.map +0 -1
- package/lib/utils/isNotNull.js +0 -10
- package/lib/utils/isNotNull.js.map +0 -1
- package/lib/utils/isRemoved.js +0 -52
- package/lib/utils/isRemoved.js.map +0 -1
- package/lib/utils/isRequire.js +0 -18
- package/lib/utils/isRequire.js.map +0 -1
- package/lib/utils/isSerializable.js +0 -19
- package/lib/utils/isSerializable.js.map +0 -1
- package/lib/utils/isTypedNode.js +0 -13
- package/lib/utils/isTypedNode.js.map +0 -1
- package/lib/utils/isUnnecessaryReactCall.js +0 -81
- package/lib/utils/isUnnecessaryReactCall.js.map +0 -1
- package/lib/utils/parseRequest.js +0 -37
- package/lib/utils/parseRequest.js.map +0 -1
- package/lib/utils/peek.js +0 -9
- package/lib/utils/peek.js.map +0 -1
- package/lib/utils/removeDangerousCode.js +0 -284
- package/lib/utils/removeDangerousCode.js.map +0 -1
- package/lib/utils/replaceImportMetaEnv.js +0 -50
- package/lib/utils/replaceImportMetaEnv.js.map +0 -1
- package/lib/utils/scopeHelpers.js +0 -557
- package/lib/utils/scopeHelpers.js.map +0 -1
- package/lib/utils/traversalCache.js +0 -31
- package/lib/utils/traversalCache.js.map +0 -1
- package/lib/utils/unwrapExpression.js +0 -25
- package/lib/utils/unwrapExpression.js.map +0 -1
- package/lib/utils/unwrapSequence.js +0 -20
- package/lib/utils/unwrapSequence.js.map +0 -1
- package/lib/utils/valueToLiteral.js +0 -65
- package/lib/utils/valueToLiteral.js.map +0 -1
- package/lib/utils/visitors/JSXElementsRemover.js +0 -57
- package/lib/utils/visitors/JSXElementsRemover.js.map +0 -1
- package/lib/vm/createVmContext.js +0 -166
- package/lib/vm/createVmContext.js.map +0 -1
- package/lib/vm/process.js +0 -38
- package/lib/vm/process.js.map +0 -1
- package/types/babel.d.ts +0 -2
- package/types/babel.js +0 -2
- package/types/options/buildOptions.d.ts +0 -6
- package/types/options/buildOptions.js +0 -178
- package/types/options/loadBabelOptions.d.ts +0 -3
- package/types/options/loadBabelOptions.js +0 -26
- package/types/plugins/babel-transform.d.ts +0 -4
- package/types/plugins/babel-transform.js +0 -49
- package/types/plugins/collector.d.ts +0 -20
- package/types/plugins/collector.js +0 -62
- package/types/plugins/dynamic-import.d.ts +0 -6
- package/types/plugins/dynamic-import.js +0 -60
- package/types/plugins/preeval.d.ts +0 -16
- package/types/plugins/preeval.js +0 -69
- package/types/plugins/shaker.d.ts +0 -14
- package/types/plugins/shaker.js +0 -724
- package/types/transform/generators/explodeReexports.d.ts +0 -7
- package/types/transform/generators/explodeReexports.js +0 -65
- package/types/utils/addIdentifierToWywPreval.d.ts +0 -4
- package/types/utils/addIdentifierToWywPreval.js +0 -74
- package/types/utils/collectExportsAndImports.d.ts +0 -31
- package/types/utils/collectExportsAndImports.js +0 -1147
- package/types/utils/collectTemplateDependencies.d.ts +0 -17
- package/types/utils/collectTemplateDependencies.js +0 -220
- package/types/utils/createId.d.ts +0 -2
- package/types/utils/createId.js +0 -9
- package/types/utils/findIdentifiers.d.ts +0 -6
- package/types/utils/findIdentifiers.js +0 -67
- package/types/utils/getConstantStringValue.d.ts +0 -2
- package/types/utils/getConstantStringValue.js +0 -94
- package/types/utils/getMemberExpressionPropertyName.d.ts +0 -2
- package/types/utils/getMemberExpressionPropertyName.js +0 -46
- package/types/utils/getScope.d.ts +0 -2
- package/types/utils/getScope.js +0 -10
- package/types/utils/getSource.d.ts +0 -2
- package/types/utils/getSource.js +0 -22
- package/types/utils/getTagProcessor.d.ts +0 -13
- package/types/utils/getTagProcessor.js +0 -411
- package/types/utils/isExports.d.ts +0 -6
- package/types/utils/isExports.js +0 -19
- package/types/utils/isGlobal.d.ts +0 -2
- package/types/utils/isGlobal.js +0 -9
- package/types/utils/isNodePath.d.ts +0 -3
- package/types/utils/isNodePath.js +0 -6
- package/types/utils/isRemoved.d.ts +0 -5
- package/types/utils/isRemoved.js +0 -41
- package/types/utils/isRequire.d.ts +0 -6
- package/types/utils/isRequire.js +0 -14
- package/types/utils/isTypedNode.d.ts +0 -5
- package/types/utils/isTypedNode.js +0 -9
- package/types/utils/isUnnecessaryReactCall.d.ts +0 -3
- package/types/utils/isUnnecessaryReactCall.js +0 -75
- package/types/utils/removeDangerousCode.d.ts +0 -4
- package/types/utils/removeDangerousCode.js +0 -326
- package/types/utils/replaceImportMetaEnv.d.ts +0 -3
- package/types/utils/replaceImportMetaEnv.js +0 -39
- package/types/utils/scopeHelpers.d.ts +0 -12
- package/types/utils/scopeHelpers.js +0 -580
- package/types/utils/traversalCache.d.ts +0 -4
- package/types/utils/traversalCache.js +0 -27
- package/types/utils/unwrapExpression.d.ts +0 -2
- package/types/utils/unwrapExpression.js +0 -57
- package/types/utils/unwrapSequence.d.ts +0 -8
- package/types/utils/unwrapSequence.js +0 -16
- package/types/utils/valueToLiteral.d.ts +0 -3
- package/types/utils/valueToLiteral.js +0 -63
- package/types/utils/visitors/JSXElementsRemover.d.ts +0 -3
- package/types/utils/visitors/JSXElementsRemover.js +0 -51
|
@@ -0,0 +1,3235 @@
|
|
|
1
|
+
/* eslint-disable no-restricted-syntax,no-continue,@typescript-eslint/no-use-before-define */
|
|
2
|
+
import { createHash } from 'crypto';
|
|
3
|
+
import { readFileSync, statSync } from 'fs';
|
|
4
|
+
import { dirname, isAbsolute, relative, resolve as resolvePath } from 'path';
|
|
5
|
+
import { isFeatureEnabled } from '@wyw-in-js/shared';
|
|
6
|
+
import { oxcShaker } from '../../shaker';
|
|
7
|
+
import { collectOxcProcessorImportsFromProgram } from '../../utils/collectOxcExportsAndImports';
|
|
8
|
+
import { createOxcStaticCallableValue, evaluateOxcStaticExpression, evaluateOxcStaticExpressionAt, isOxcStaticSerializableValue, } from '../../utils/collectOxcTemplateDependencies';
|
|
9
|
+
import { appendOxcWywPreval, runOxcPreevalStage, } from '../../utils/oxcPreevalStage';
|
|
10
|
+
import { parseOxcProgramCached } from '../../utils/parseOxc';
|
|
11
|
+
import { stripQueryAndHash } from '../../utils/parseRequest';
|
|
12
|
+
import { getProcessorForImport } from '../../utils/processorLookup';
|
|
13
|
+
import { Entrypoint } from '../Entrypoint';
|
|
14
|
+
const STATIC_EXPORT_MAX_NULL_ATTEMPTS = 2;
|
|
15
|
+
const isInsideRoot = (filename, root) => {
|
|
16
|
+
const relativePath = relative(root, filename);
|
|
17
|
+
return (relativePath === '' ||
|
|
18
|
+
(!!relativePath &&
|
|
19
|
+
!relativePath.startsWith('..') &&
|
|
20
|
+
!isAbsolute(relativePath)));
|
|
21
|
+
};
|
|
22
|
+
const nodeModulesPattern = /[\\/]node_modules[\\/]/;
|
|
23
|
+
const isLocalStaticMetadataFile = (filename, root) => {
|
|
24
|
+
const strippedFilename = stripQueryAndHash(filename);
|
|
25
|
+
if (isInsideRoot(strippedFilename, root)) {
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return (isAbsolute(strippedFilename) && !nodeModulesPattern.test(strippedFilename));
|
|
29
|
+
};
|
|
30
|
+
const isEnvDisabled = (value) => value === '0' || value === 'false' || value === 'no' || value === 'off';
|
|
31
|
+
const isStaticImportValuesEnabled = (action, filename) => {
|
|
32
|
+
const envValue = process.env.WYW_STATIC_IMPORT_VALUES?.trim().toLowerCase();
|
|
33
|
+
if (envValue) {
|
|
34
|
+
return !isEnvDisabled(envValue);
|
|
35
|
+
}
|
|
36
|
+
return isFeatureEnabled(action.services.options.pluginOptions.features, 'staticImportValues', filename);
|
|
37
|
+
};
|
|
38
|
+
const debugStaticResolve = (action, event) => {
|
|
39
|
+
const labels = Object.fromEntries(Object.entries({
|
|
40
|
+
...event,
|
|
41
|
+
type: 'staticResolve',
|
|
42
|
+
}).filter(([, value]) => value !== undefined));
|
|
43
|
+
action.services.eventEmitter.single(labels);
|
|
44
|
+
};
|
|
45
|
+
const parseProgram = (code, filename) => parseOxcProgramCached(filename, code, 'unambiguous');
|
|
46
|
+
const staticFileAnalysisCaches = new WeakMap();
|
|
47
|
+
const staticFileHashCaches = new WeakMap();
|
|
48
|
+
const staticExportResultCaches = new WeakMap();
|
|
49
|
+
const staticMetadataPreevalCaches = new WeakMap();
|
|
50
|
+
const hashStaticContent = (content) => createHash('sha256').update(content).digest('hex');
|
|
51
|
+
const getWeakCacheMap = (caches, key) => {
|
|
52
|
+
let cache = caches.get(key);
|
|
53
|
+
if (!cache) {
|
|
54
|
+
cache = new Map();
|
|
55
|
+
caches.set(key, cache);
|
|
56
|
+
}
|
|
57
|
+
return cache;
|
|
58
|
+
};
|
|
59
|
+
const isStaticResolveCacheEnabled = () => {
|
|
60
|
+
const envValue = process.env.WYW_STATIC_RESOLVE_CACHE?.trim().toLowerCase();
|
|
61
|
+
if (envValue) {
|
|
62
|
+
return !isEnvDisabled(envValue);
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
const staticCachePrefix = (action) => `${action.services.cache.getKeySalt() ?? ''}\0${action.services.options.root ?? ''}`;
|
|
67
|
+
const staticFileAnalysisCache = (action) => getWeakCacheMap(staticFileAnalysisCaches, action.services.cache);
|
|
68
|
+
const staticFileHashCache = (action) => getWeakCacheMap(staticFileHashCaches, action.services.cache);
|
|
69
|
+
const staticExportResultCache = (action) => getWeakCacheMap(staticExportResultCaches, action.services.cache);
|
|
70
|
+
const staticMetadataPreevalCache = (action) => getWeakCacheMap(staticMetadataPreevalCaches, action.services.cache);
|
|
71
|
+
const staticFileAnalysisCacheKey = (action, filename, codeHash) => `${staticCachePrefix(action)}\0${filename}\0${codeHash}`;
|
|
72
|
+
const staticExportCacheKey = (action, filename, exportedName, codeHash) => `${staticCachePrefix(action)}\0${filename}\0${exportedName}\0${codeHash}`;
|
|
73
|
+
const staticMetadataPreevalCacheKey = (action, filename, codeHash) => `${staticCachePrefix(action)}\0${filename}\0${codeHash}`;
|
|
74
|
+
const getStaticFileContentHash = (action, dependency) => {
|
|
75
|
+
const filename = stripQueryAndHash(dependency);
|
|
76
|
+
if (!isAbsolute(filename)) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
let stat;
|
|
80
|
+
try {
|
|
81
|
+
stat = statSync(filename);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
if (!stat.isFile()) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
const cache = staticFileHashCache(action);
|
|
90
|
+
const cached = cache.get(filename);
|
|
91
|
+
if (cached && cached.mtimeMs === stat.mtimeMs && cached.size === stat.size) {
|
|
92
|
+
return cached.hash;
|
|
93
|
+
}
|
|
94
|
+
let hash;
|
|
95
|
+
try {
|
|
96
|
+
hash = hashStaticContent(readFileSync(filename));
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
cache.set(filename, {
|
|
102
|
+
hash,
|
|
103
|
+
mtimeMs: stat.mtimeMs,
|
|
104
|
+
size: stat.size,
|
|
105
|
+
});
|
|
106
|
+
return hash;
|
|
107
|
+
};
|
|
108
|
+
const collectStaticDependencyHashes = (action, dependencies) => {
|
|
109
|
+
const hashes = new Map();
|
|
110
|
+
for (const dependency of dependencies) {
|
|
111
|
+
const hash = getStaticFileContentHash(action, dependency);
|
|
112
|
+
if (!hash) {
|
|
113
|
+
return null;
|
|
114
|
+
}
|
|
115
|
+
hashes.set(stripQueryAndHash(dependency), hash);
|
|
116
|
+
}
|
|
117
|
+
return hashes;
|
|
118
|
+
};
|
|
119
|
+
const areStaticDependencyHashesCurrent = (action, dependencyHashes) => {
|
|
120
|
+
for (const [dependency, expectedHash] of dependencyHashes) {
|
|
121
|
+
if (getStaticFileContentHash(action, dependency) !== expectedHash) {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return true;
|
|
126
|
+
};
|
|
127
|
+
const getStaticExportCachedResult = (action, filename, exportedName, codeHash) => {
|
|
128
|
+
if (!isStaticResolveCacheEnabled()) {
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
131
|
+
const cache = staticExportResultCache(action);
|
|
132
|
+
const cacheKey = staticExportCacheKey(action, filename, exportedName, codeHash);
|
|
133
|
+
const cached = cache.get(cacheKey);
|
|
134
|
+
if (!cached) {
|
|
135
|
+
return undefined;
|
|
136
|
+
}
|
|
137
|
+
if (cached.result === null) {
|
|
138
|
+
// Bounded retry: until the attempt counter has been bumped enough times
|
|
139
|
+
// that we accept the null as stable, treat it as a cache miss so the
|
|
140
|
+
// caller re-walks. The counter is updated in setStaticExportCachedResult.
|
|
141
|
+
if (cached.attempts < STATIC_EXPORT_MAX_NULL_ATTEMPTS) {
|
|
142
|
+
return undefined;
|
|
143
|
+
}
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
if (areStaticDependencyHashesCurrent(action, cached.dependencyHashes)) {
|
|
147
|
+
return cached.result;
|
|
148
|
+
}
|
|
149
|
+
cache.delete(cacheKey);
|
|
150
|
+
return undefined;
|
|
151
|
+
};
|
|
152
|
+
const setStaticExportCachedResult = (action, filename, exportedName, codeHash, result) => {
|
|
153
|
+
if (!isStaticResolveCacheEnabled()) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const cache = staticExportResultCache(action);
|
|
157
|
+
const cacheKey = staticExportCacheKey(action, filename, exportedName, codeHash);
|
|
158
|
+
if (!result) {
|
|
159
|
+
const existing = cache.get(cacheKey);
|
|
160
|
+
const attempts = existing && existing.result === null ? existing.attempts + 1 : 1;
|
|
161
|
+
cache.set(cacheKey, { attempts, result: null });
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
const dependencyHashes = collectStaticDependencyHashes(action, result.dependencies);
|
|
165
|
+
if (!dependencyHashes) {
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
cache.set(cacheKey, {
|
|
169
|
+
dependencyHashes,
|
|
170
|
+
result,
|
|
171
|
+
});
|
|
172
|
+
};
|
|
173
|
+
const getStaticFileAnalysis = (action, filename) => {
|
|
174
|
+
const loadedAndParsed = action.services.loadAndParseFn(action.services, filename, undefined, action.services.log);
|
|
175
|
+
if (loadedAndParsed.evaluator === 'ignored' ||
|
|
176
|
+
loadedAndParsed.evaluator !== oxcShaker) {
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
const { code } = loadedAndParsed;
|
|
180
|
+
const codeHash = hashStaticContent(code);
|
|
181
|
+
const cache = staticFileAnalysisCache(action);
|
|
182
|
+
const cacheKey = staticFileAnalysisCacheKey(action, filename, codeHash);
|
|
183
|
+
const cached = cache.get(cacheKey);
|
|
184
|
+
if (cached) {
|
|
185
|
+
return cached;
|
|
186
|
+
}
|
|
187
|
+
const analysis = {
|
|
188
|
+
code,
|
|
189
|
+
codeHash,
|
|
190
|
+
program: parseProgram(code, filename),
|
|
191
|
+
};
|
|
192
|
+
cache.set(cacheKey, analysis);
|
|
193
|
+
return analysis;
|
|
194
|
+
};
|
|
195
|
+
const getStaticMetadataPreevalResult = (action, filename, code, codeHash) => {
|
|
196
|
+
const cache = staticMetadataPreevalCache(action);
|
|
197
|
+
const cacheKey = staticMetadataPreevalCacheKey(action, filename, codeHash);
|
|
198
|
+
const cached = cache.get(cacheKey);
|
|
199
|
+
if (cached) {
|
|
200
|
+
return cached.result;
|
|
201
|
+
}
|
|
202
|
+
const root = action.services.options.root ?? process.cwd();
|
|
203
|
+
try {
|
|
204
|
+
const result = action.services.eventEmitter.perf('transform:preeval:staticMetadata', () => runOxcPreevalStage(code, {
|
|
205
|
+
filename,
|
|
206
|
+
root,
|
|
207
|
+
}, {
|
|
208
|
+
...action.services.options.pluginOptions,
|
|
209
|
+
eventEmitter: action.services.eventEmitter,
|
|
210
|
+
}));
|
|
211
|
+
cache.set(cacheKey, { result });
|
|
212
|
+
return result;
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
cache.set(cacheKey, { result: null });
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
};
|
|
219
|
+
const getChildren = (node) => {
|
|
220
|
+
const children = [];
|
|
221
|
+
Object.entries(node).forEach(([key, value]) => {
|
|
222
|
+
if (key === 'comments' ||
|
|
223
|
+
key === 'errors' ||
|
|
224
|
+
key === 'parent' ||
|
|
225
|
+
key === 'span') {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (Array.isArray(value)) {
|
|
229
|
+
value.forEach((item) => {
|
|
230
|
+
if (item && typeof item === 'object' && 'type' in item) {
|
|
231
|
+
children.push(item);
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
if (value && typeof value === 'object' && 'type' in value) {
|
|
237
|
+
children.push(value);
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
return children;
|
|
241
|
+
};
|
|
242
|
+
const moduleExportName = (node) => node.type === 'Literal' ? String(node.value) : node.name;
|
|
243
|
+
const unwrapExpression = (expr) => {
|
|
244
|
+
let current = expr;
|
|
245
|
+
for (;;) {
|
|
246
|
+
if (current.type === 'TSAsExpression' ||
|
|
247
|
+
current.type === 'TSSatisfiesExpression' ||
|
|
248
|
+
current.type === 'TSNonNullExpression' ||
|
|
249
|
+
current.type === 'TSInstantiationExpression' ||
|
|
250
|
+
current.type === 'TSTypeAssertion' ||
|
|
251
|
+
current.type === 'ParenthesizedExpression') {
|
|
252
|
+
current = current.expression;
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
return current;
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
const isProcessEnvMember = (node) => {
|
|
259
|
+
if (node.type !== 'MemberExpression' || node.computed) {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
if (node.property.type !== 'Identifier' || node.property.name !== 'env') {
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
return node.object.type === 'Identifier' && node.object.name === 'process';
|
|
266
|
+
};
|
|
267
|
+
const isSafeLiteral = (node) => {
|
|
268
|
+
if (node.type !== 'Literal') {
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
const { value } = node;
|
|
272
|
+
return (value === null ||
|
|
273
|
+
typeof value === 'string' ||
|
|
274
|
+
typeof value === 'number' ||
|
|
275
|
+
typeof value === 'boolean');
|
|
276
|
+
};
|
|
277
|
+
const isSafeStaticExpression = (expr, options = {}) => {
|
|
278
|
+
const unwrapped = unwrapExpression(expr);
|
|
279
|
+
if (isSafeLiteral(unwrapped)) {
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
if (unwrapped.type === 'Identifier') {
|
|
283
|
+
return true;
|
|
284
|
+
}
|
|
285
|
+
if (unwrapped.type === 'TemplateLiteral') {
|
|
286
|
+
return unwrapped.expressions.every((item) => isSafeStaticExpression(item, options));
|
|
287
|
+
}
|
|
288
|
+
if (unwrapped.type === 'UnaryExpression') {
|
|
289
|
+
return isSafeStaticExpression(unwrapped.argument, options);
|
|
290
|
+
}
|
|
291
|
+
if (unwrapped.type === 'BinaryExpression' ||
|
|
292
|
+
unwrapped.type === 'LogicalExpression') {
|
|
293
|
+
return (isSafeStaticExpression(unwrapped.left, options) &&
|
|
294
|
+
isSafeStaticExpression(unwrapped.right, options));
|
|
295
|
+
}
|
|
296
|
+
if (unwrapped.type === 'ConditionalExpression') {
|
|
297
|
+
return (isSafeStaticExpression(unwrapped.test, options) &&
|
|
298
|
+
isSafeStaticExpression(unwrapped.consequent, options) &&
|
|
299
|
+
isSafeStaticExpression(unwrapped.alternate, options));
|
|
300
|
+
}
|
|
301
|
+
if (unwrapped.type === 'MemberExpression') {
|
|
302
|
+
return (isSafeStaticExpression(unwrapped.object, options) &&
|
|
303
|
+
(unwrapped.computed
|
|
304
|
+
? isSafeStaticExpression(unwrapped.property, options)
|
|
305
|
+
: unwrapped.property.type === 'Identifier'));
|
|
306
|
+
}
|
|
307
|
+
if (options.allowMetadataCalls && unwrapped.type === 'CallExpression') {
|
|
308
|
+
return (unwrapped.callee.type === 'Identifier' && unwrapped.arguments.length === 0);
|
|
309
|
+
}
|
|
310
|
+
if (options.allowMetadataCalls &&
|
|
311
|
+
(unwrapped.type === 'ArrowFunctionExpression' ||
|
|
312
|
+
unwrapped.type === 'FunctionExpression')) {
|
|
313
|
+
return (!unwrapped.async &&
|
|
314
|
+
unwrapped.params.length === 0 &&
|
|
315
|
+
!!unwrapped.body &&
|
|
316
|
+
isSafeFunctionBodyExpression(unwrapped.body, options));
|
|
317
|
+
}
|
|
318
|
+
if (unwrapped.type === 'ArrayExpression') {
|
|
319
|
+
return unwrapped.elements.every((item) => {
|
|
320
|
+
if (!item) {
|
|
321
|
+
return false;
|
|
322
|
+
}
|
|
323
|
+
return item.type === 'SpreadElement'
|
|
324
|
+
? isSafeStaticExpression(item.argument, options)
|
|
325
|
+
: isSafeStaticExpression(item, options);
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
if (unwrapped.type === 'ObjectExpression') {
|
|
329
|
+
return unwrapped.properties.every((property) => {
|
|
330
|
+
if (property.type === 'SpreadElement') {
|
|
331
|
+
return isSafeStaticExpression(property.argument);
|
|
332
|
+
}
|
|
333
|
+
const propertyNode = property;
|
|
334
|
+
if (propertyNode.computed || propertyNode.method) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
return (propertyNode.value &&
|
|
338
|
+
typeof propertyNode.value === 'object' &&
|
|
339
|
+
isSafeStaticExpression(propertyNode.value, options));
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
return false;
|
|
343
|
+
};
|
|
344
|
+
const isTypeOnlyImport = (statement) => {
|
|
345
|
+
if (statement.importKind === 'type') {
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
return statement.specifiers.every((specifier) => specifier.type === 'ImportSpecifier' &&
|
|
349
|
+
specifier.importKind === 'type');
|
|
350
|
+
};
|
|
351
|
+
const getImportBinding = (statement, specifier, options = {}) => {
|
|
352
|
+
const local = specifier.local?.name;
|
|
353
|
+
if (!local) {
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
if (specifier.type === 'ImportNamespaceSpecifier') {
|
|
357
|
+
return options.includeNamespace
|
|
358
|
+
? {
|
|
359
|
+
imported: '*',
|
|
360
|
+
local,
|
|
361
|
+
source: statement.source.value,
|
|
362
|
+
}
|
|
363
|
+
: null;
|
|
364
|
+
}
|
|
365
|
+
if (specifier.type === 'ImportDefaultSpecifier') {
|
|
366
|
+
return {
|
|
367
|
+
imported: 'default',
|
|
368
|
+
local,
|
|
369
|
+
source: statement.source.value,
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
if (specifier.type !== 'ImportSpecifier') {
|
|
373
|
+
return null;
|
|
374
|
+
}
|
|
375
|
+
if (statement.importKind === 'type' ||
|
|
376
|
+
specifier.importKind === 'type') {
|
|
377
|
+
return null;
|
|
378
|
+
}
|
|
379
|
+
return {
|
|
380
|
+
imported: moduleExportName(specifier.imported),
|
|
381
|
+
local,
|
|
382
|
+
source: statement.source.value,
|
|
383
|
+
};
|
|
384
|
+
};
|
|
385
|
+
const collectImportBindings = (program, options = {}) => {
|
|
386
|
+
const result = new Map();
|
|
387
|
+
program.body.forEach((statement) => {
|
|
388
|
+
if (statement.type !== 'ImportDeclaration' || isTypeOnlyImport(statement)) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
statement.specifiers.forEach((specifier) => {
|
|
392
|
+
const binding = getImportBinding(statement, specifier, options);
|
|
393
|
+
if (binding) {
|
|
394
|
+
result.set(binding.local, binding);
|
|
395
|
+
}
|
|
396
|
+
});
|
|
397
|
+
});
|
|
398
|
+
return result;
|
|
399
|
+
};
|
|
400
|
+
const applyReplacements = (code, replacements) => {
|
|
401
|
+
let result = code;
|
|
402
|
+
replacements
|
|
403
|
+
.sort((a, b) => b.start - a.start)
|
|
404
|
+
.forEach((replacement) => {
|
|
405
|
+
result =
|
|
406
|
+
result.slice(0, replacement.start) +
|
|
407
|
+
replacement.text +
|
|
408
|
+
result.slice(replacement.end);
|
|
409
|
+
});
|
|
410
|
+
return result;
|
|
411
|
+
};
|
|
412
|
+
const isIdentifierBindingPosition = (node, parent) => {
|
|
413
|
+
if (node.type !== 'Identifier' || !parent) {
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
if ((parent.type === 'VariableDeclarator' && parent.id === node) ||
|
|
417
|
+
(parent.type === 'FunctionDeclaration' && parent.id === node) ||
|
|
418
|
+
(parent.type === 'FunctionExpression' && parent.id === node) ||
|
|
419
|
+
(parent.type === 'ClassDeclaration' && parent.id === node) ||
|
|
420
|
+
(parent.type === 'ClassExpression' && parent.id === node)) {
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
if ((parent.type === 'ArrowFunctionExpression' ||
|
|
424
|
+
parent.type === 'FunctionDeclaration' ||
|
|
425
|
+
parent.type === 'FunctionExpression') &&
|
|
426
|
+
parent.params.some((param) => param === node)) {
|
|
427
|
+
return true;
|
|
428
|
+
}
|
|
429
|
+
return ((parent.type === 'ImportSpecifier' && parent.local === node) ||
|
|
430
|
+
(parent.type === 'ImportDefaultSpecifier' && parent.local === node) ||
|
|
431
|
+
(parent.type === 'ImportNamespaceSpecifier' && parent.local === node));
|
|
432
|
+
};
|
|
433
|
+
const isPropertyKeyOnlyIdentifier = (node, parent) => node.type === 'Identifier' &&
|
|
434
|
+
!!parent &&
|
|
435
|
+
((parent.type === 'MemberExpression' &&
|
|
436
|
+
parent.property === node &&
|
|
437
|
+
!parent.computed) ||
|
|
438
|
+
(parent.type === 'Property' &&
|
|
439
|
+
parent.key === node &&
|
|
440
|
+
!parent.computed &&
|
|
441
|
+
!parent.shorthand));
|
|
442
|
+
const collectUsedIdentifierNames = (program) => {
|
|
443
|
+
const used = new Set();
|
|
444
|
+
const walk = (node, parent) => {
|
|
445
|
+
if (node.type === 'ImportDeclaration') {
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
if (node.type === 'Identifier' &&
|
|
449
|
+
!isIdentifierBindingPosition(node, parent) &&
|
|
450
|
+
!isPropertyKeyOnlyIdentifier(node, parent)) {
|
|
451
|
+
used.add(node.name);
|
|
452
|
+
}
|
|
453
|
+
getChildren(node).forEach((child) => walk(child, node));
|
|
454
|
+
};
|
|
455
|
+
walk(program, null);
|
|
456
|
+
return used;
|
|
457
|
+
};
|
|
458
|
+
const removableStaticHelperNames = (program, staticValueNames) => {
|
|
459
|
+
const used = collectUsedIdentifierNames(program);
|
|
460
|
+
const result = new Set();
|
|
461
|
+
program.body.forEach((statement) => {
|
|
462
|
+
if (statement.type !== 'VariableDeclaration') {
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
statement.declarations.forEach((declarator) => {
|
|
466
|
+
if (declarator.id.type === 'Identifier' &&
|
|
467
|
+
staticValueNames.has(declarator.id.name) &&
|
|
468
|
+
!used.has(declarator.id.name)) {
|
|
469
|
+
result.add(declarator.id.name);
|
|
470
|
+
}
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
return result;
|
|
474
|
+
};
|
|
475
|
+
const collectImportLocalReferences = (node, importLocals, result) => {
|
|
476
|
+
const walk = (item, parent) => {
|
|
477
|
+
if (item.type === 'Identifier' &&
|
|
478
|
+
importLocals.has(item.name) &&
|
|
479
|
+
!isIdentifierBindingPosition(item, parent) &&
|
|
480
|
+
!isPropertyKeyOnlyIdentifier(item, parent)) {
|
|
481
|
+
result.add(item.name);
|
|
482
|
+
}
|
|
483
|
+
getChildren(item).forEach((child) => walk(child, item));
|
|
484
|
+
};
|
|
485
|
+
walk(node, null);
|
|
486
|
+
};
|
|
487
|
+
const parseStaticExpressionSource = (source, filename) => {
|
|
488
|
+
try {
|
|
489
|
+
const program = parseProgram(`const __wyw_static_value = ${source};`, filename);
|
|
490
|
+
const declaration = program.body[0];
|
|
491
|
+
if (declaration?.type !== 'VariableDeclaration') {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
const [declarator] = declaration.declarations;
|
|
495
|
+
return declarator?.init ?? null;
|
|
496
|
+
}
|
|
497
|
+
catch {
|
|
498
|
+
return null;
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
const expressionUsesNameOnlyAsZeroArgCalls = (expression, name) => {
|
|
502
|
+
let seen = false;
|
|
503
|
+
let valid = true;
|
|
504
|
+
const walk = (node, parent) => {
|
|
505
|
+
if (!valid) {
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (node.type === 'Identifier' &&
|
|
509
|
+
node.name === name &&
|
|
510
|
+
!isIdentifierBindingPosition(node, parent) &&
|
|
511
|
+
!isPropertyKeyOnlyIdentifier(node, parent)) {
|
|
512
|
+
if (parent?.type === 'CallExpression' &&
|
|
513
|
+
parent.callee === node &&
|
|
514
|
+
parent.arguments.length === 0) {
|
|
515
|
+
seen = true;
|
|
516
|
+
}
|
|
517
|
+
else {
|
|
518
|
+
valid = false;
|
|
519
|
+
return;
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
getChildren(node).forEach((child) => walk(child, node));
|
|
523
|
+
};
|
|
524
|
+
walk(expression, null);
|
|
525
|
+
return seen && valid;
|
|
526
|
+
};
|
|
527
|
+
const bindStaticResolvedValue = (env, expression, local, resolved, options = {}) => {
|
|
528
|
+
if (resolved.callable === 'zero-arg') {
|
|
529
|
+
if (!expressionUsesNameOnlyAsZeroArgCalls(expression, local)) {
|
|
530
|
+
return false;
|
|
531
|
+
}
|
|
532
|
+
env.set(local, createOxcStaticCallableValue(resolved.value));
|
|
533
|
+
return true;
|
|
534
|
+
}
|
|
535
|
+
env.set(local, options.wrapNonCallable
|
|
536
|
+
? createOxcStaticCallableValue(resolved.value)
|
|
537
|
+
: resolved.value);
|
|
538
|
+
return true;
|
|
539
|
+
};
|
|
540
|
+
const removeStaticHelperDeclarations = (code, filename, staticValueNames) => {
|
|
541
|
+
if (staticValueNames.size === 0) {
|
|
542
|
+
return { code, removed: new Set(), removedImportLocals: new Set() };
|
|
543
|
+
}
|
|
544
|
+
const program = parseProgram(code, filename);
|
|
545
|
+
const removableNames = removableStaticHelperNames(program, staticValueNames);
|
|
546
|
+
const importLocals = new Set();
|
|
547
|
+
collectImportBindings(program).forEach((_, local) => importLocals.add(local));
|
|
548
|
+
const removedImportLocals = new Set();
|
|
549
|
+
const ranges = [];
|
|
550
|
+
const replacements = [];
|
|
551
|
+
program.body.forEach((statement) => {
|
|
552
|
+
if (statement.type !== 'VariableDeclaration' ||
|
|
553
|
+
statement.declarations.length === 0) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const removableIndexes = statement.declarations.flatMap((declarator, index) => declarator.id.type === 'Identifier' &&
|
|
557
|
+
removableNames.has(declarator.id.name)
|
|
558
|
+
? [index]
|
|
559
|
+
: []);
|
|
560
|
+
if (removableIndexes.length === 0) {
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
removableIndexes.forEach((index) => {
|
|
564
|
+
collectImportLocalReferences(statement.declarations[index], importLocals, removedImportLocals);
|
|
565
|
+
});
|
|
566
|
+
if (removableIndexes.length === statement.declarations.length) {
|
|
567
|
+
ranges.push({
|
|
568
|
+
end: statement.end,
|
|
569
|
+
start: statement.start,
|
|
570
|
+
});
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
const keptDeclarations = statement.declarations
|
|
574
|
+
.filter((_, index) => !removableIndexes.includes(index))
|
|
575
|
+
.map((declarator) => code.slice(declarator.start, declarator.end));
|
|
576
|
+
replacements.push({
|
|
577
|
+
end: statement.end,
|
|
578
|
+
start: statement.start,
|
|
579
|
+
text: `${statement.kind} ${keptDeclarations.join(', ')};`,
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
return {
|
|
583
|
+
code: applyReplacements(code, [
|
|
584
|
+
...ranges.map((range) => ({ ...range, text: '' })),
|
|
585
|
+
...replacements,
|
|
586
|
+
]),
|
|
587
|
+
removed: removableNames,
|
|
588
|
+
removedImportLocals,
|
|
589
|
+
};
|
|
590
|
+
};
|
|
591
|
+
const importSpecifierLocalName = (specifier) => specifier.local?.name ?? null;
|
|
592
|
+
const removeUnusedStaticImports = (code, filename, staticImportLocals, sideEffectImportLocals) => {
|
|
593
|
+
if (staticImportLocals.size === 0) {
|
|
594
|
+
return code;
|
|
595
|
+
}
|
|
596
|
+
const program = parseProgram(code, filename);
|
|
597
|
+
const used = collectUsedIdentifierNames(program);
|
|
598
|
+
const ranges = [];
|
|
599
|
+
const replacements = [];
|
|
600
|
+
program.body.forEach((statement) => {
|
|
601
|
+
if (statement.type !== 'ImportDeclaration' ||
|
|
602
|
+
statement.specifiers.length === 0) {
|
|
603
|
+
return;
|
|
604
|
+
}
|
|
605
|
+
const removable = statement.specifiers.flatMap((specifier, index) => {
|
|
606
|
+
const localName = importSpecifierLocalName(specifier);
|
|
607
|
+
return localName &&
|
|
608
|
+
staticImportLocals.has(localName) &&
|
|
609
|
+
!used.has(localName)
|
|
610
|
+
? [{ index, localName }]
|
|
611
|
+
: [];
|
|
612
|
+
});
|
|
613
|
+
if (removable.length === 0) {
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
if (removable.length === statement.specifiers.length) {
|
|
617
|
+
if (removable.some((item) => sideEffectImportLocals.has(item.localName))) {
|
|
618
|
+
replacements.push({
|
|
619
|
+
end: statement.end,
|
|
620
|
+
start: statement.start,
|
|
621
|
+
text: `import ${code.slice(statement.source.start, statement.source.end)};`,
|
|
622
|
+
});
|
|
623
|
+
return;
|
|
624
|
+
}
|
|
625
|
+
ranges.push({
|
|
626
|
+
end: statement.end,
|
|
627
|
+
start: statement.start,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
});
|
|
631
|
+
return applyReplacements(code, [
|
|
632
|
+
...ranges.map((range) => ({ ...range, text: '' })),
|
|
633
|
+
...replacements,
|
|
634
|
+
]);
|
|
635
|
+
};
|
|
636
|
+
const replaceStaticWYWMetaExtendsHelpers = (code, filename, helperValues) => {
|
|
637
|
+
if (helperValues.size === 0) {
|
|
638
|
+
return code;
|
|
639
|
+
}
|
|
640
|
+
const program = parseProgram(code, filename);
|
|
641
|
+
const replacements = [];
|
|
642
|
+
const visit = (node) => {
|
|
643
|
+
if (node.type === 'ObjectExpression') {
|
|
644
|
+
const extendsExpression = findWYWMetaExtendsExpression(node);
|
|
645
|
+
if (extendsExpression) {
|
|
646
|
+
const unwrapped = unwrapExpression(extendsExpression);
|
|
647
|
+
if (unwrapped.type === 'CallExpression' &&
|
|
648
|
+
unwrapped.callee.type === 'Identifier' &&
|
|
649
|
+
unwrapped.arguments.length === 0 &&
|
|
650
|
+
helperValues.has(unwrapped.callee.name)) {
|
|
651
|
+
const replacement = staticWYWMetaExtendsReplacementCode(helperValues.get(unwrapped.callee.name));
|
|
652
|
+
if (replacement) {
|
|
653
|
+
replacements.push({
|
|
654
|
+
end: extendsExpression.end,
|
|
655
|
+
start: extendsExpression.start,
|
|
656
|
+
text: replacement,
|
|
657
|
+
});
|
|
658
|
+
}
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
getChildren(node).forEach(visit);
|
|
663
|
+
};
|
|
664
|
+
visit(program);
|
|
665
|
+
return applyReplacements(code, replacements);
|
|
666
|
+
};
|
|
667
|
+
const pruneStaticPreevalCode = (code, filename, staticValueNames, staticImportLocals, staticExtendsHelperValues, sideEffectImportLocals) => {
|
|
668
|
+
const codeWithMetadataPruned = replaceStaticWYWMetaExtendsHelpers(code, filename, staticExtendsHelperValues);
|
|
669
|
+
const helpersRemoved = removeStaticHelperDeclarations(codeWithMetadataPruned, filename, staticValueNames);
|
|
670
|
+
if (helpersRemoved.removed.size === 0) {
|
|
671
|
+
return codeWithMetadataPruned;
|
|
672
|
+
}
|
|
673
|
+
const importLocalsToPrune = new Set([
|
|
674
|
+
...staticImportLocals,
|
|
675
|
+
...helpersRemoved.removedImportLocals,
|
|
676
|
+
]);
|
|
677
|
+
return removeUnusedStaticImports(helpersRemoved.code, filename, importLocalsToPrune, sideEffectImportLocals);
|
|
678
|
+
};
|
|
679
|
+
const collectProcessorImportLocals = (action, program, code, filename) => {
|
|
680
|
+
const result = new Set();
|
|
681
|
+
collectOxcProcessorImportsFromProgram(program, code).forEach((item) => {
|
|
682
|
+
if (item.type !== 'esm' ||
|
|
683
|
+
item.imported === '*' ||
|
|
684
|
+
item.imported === 'side-effect') {
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
const localName = item.local.name ?? item.local.code;
|
|
688
|
+
if (!localName) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
const [processor] = getProcessorForImport({
|
|
692
|
+
imported: item.imported,
|
|
693
|
+
source: item.source,
|
|
694
|
+
}, filename, action.services.options.pluginOptions);
|
|
695
|
+
if (!processor) {
|
|
696
|
+
return;
|
|
697
|
+
}
|
|
698
|
+
result.add(localName);
|
|
699
|
+
const rootLocalName = localName.split('.')[0];
|
|
700
|
+
if (rootLocalName) {
|
|
701
|
+
result.add(rootLocalName);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
return result;
|
|
705
|
+
};
|
|
706
|
+
const isStaticWYWMetaValue = (value, seen = new Set()) => {
|
|
707
|
+
if (typeof value !== 'object' || value === null) {
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
if (seen.has(value)) {
|
|
711
|
+
return false;
|
|
712
|
+
}
|
|
713
|
+
seen.add(value);
|
|
714
|
+
const meta = value.__wyw_meta;
|
|
715
|
+
if (typeof meta !== 'object' || meta === null) {
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
const { className, extends: extended } = meta;
|
|
719
|
+
return (typeof className === 'string' &&
|
|
720
|
+
(extended === null || isStaticWYWMetaValue(extended, seen)));
|
|
721
|
+
};
|
|
722
|
+
const toStaticWYWSelectorMetaValue = (value, seen = new Set()) => {
|
|
723
|
+
if (typeof value !== 'object' || value === null || seen.has(value)) {
|
|
724
|
+
return null;
|
|
725
|
+
}
|
|
726
|
+
seen.add(value);
|
|
727
|
+
const meta = value.__wyw_meta;
|
|
728
|
+
if (typeof meta !== 'object' || meta === null) {
|
|
729
|
+
return null;
|
|
730
|
+
}
|
|
731
|
+
const { className, extends: extended } = meta;
|
|
732
|
+
if (typeof className !== 'string') {
|
|
733
|
+
return null;
|
|
734
|
+
}
|
|
735
|
+
const staticExtends = extended === null ? null : toStaticWYWSelectorMetaValue(extended, seen);
|
|
736
|
+
if (extended !== null && staticExtends === null) {
|
|
737
|
+
return null;
|
|
738
|
+
}
|
|
739
|
+
return {
|
|
740
|
+
__wyw_meta: {
|
|
741
|
+
className,
|
|
742
|
+
extends: staticExtends,
|
|
743
|
+
},
|
|
744
|
+
};
|
|
745
|
+
};
|
|
746
|
+
const staticWYWMetaExtendsReplacementCode = (value) => {
|
|
747
|
+
if (value === null) {
|
|
748
|
+
return 'null';
|
|
749
|
+
}
|
|
750
|
+
const selectorMeta = toStaticWYWSelectorMetaValue(value);
|
|
751
|
+
return selectorMeta ? `(${JSON.stringify(selectorMeta)})` : null;
|
|
752
|
+
};
|
|
753
|
+
const staticWYWMetaTreeValueStatus = (value, seen = new Set()) => {
|
|
754
|
+
if (value === null ||
|
|
755
|
+
typeof value === 'string' ||
|
|
756
|
+
typeof value === 'number' ||
|
|
757
|
+
typeof value === 'boolean') {
|
|
758
|
+
return {
|
|
759
|
+
hasMetadata: false,
|
|
760
|
+
safe: true,
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
if (typeof value !== 'object') {
|
|
764
|
+
return {
|
|
765
|
+
hasMetadata: false,
|
|
766
|
+
safe: false,
|
|
767
|
+
};
|
|
768
|
+
}
|
|
769
|
+
if (seen.has(value)) {
|
|
770
|
+
return {
|
|
771
|
+
hasMetadata: false,
|
|
772
|
+
safe: false,
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
seen.add(value);
|
|
776
|
+
if (Array.isArray(value)) {
|
|
777
|
+
let hasMetadata = false;
|
|
778
|
+
for (const item of value) {
|
|
779
|
+
const status = staticWYWMetaTreeValueStatus(item, seen);
|
|
780
|
+
if (!status.safe) {
|
|
781
|
+
return {
|
|
782
|
+
hasMetadata: false,
|
|
783
|
+
safe: false,
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
hasMetadata = hasMetadata || status.hasMetadata;
|
|
787
|
+
}
|
|
788
|
+
return {
|
|
789
|
+
hasMetadata,
|
|
790
|
+
safe: true,
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
if ('__wyw_meta' in value) {
|
|
794
|
+
return {
|
|
795
|
+
hasMetadata: isStaticWYWMetaValue(value),
|
|
796
|
+
safe: isStaticWYWMetaValue(value),
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
let hasMetadata = false;
|
|
800
|
+
for (const item of Object.values(value)) {
|
|
801
|
+
const status = staticWYWMetaTreeValueStatus(item, seen);
|
|
802
|
+
if (!status.safe) {
|
|
803
|
+
return {
|
|
804
|
+
hasMetadata: false,
|
|
805
|
+
safe: false,
|
|
806
|
+
};
|
|
807
|
+
}
|
|
808
|
+
hasMetadata = hasMetadata || status.hasMetadata;
|
|
809
|
+
}
|
|
810
|
+
return {
|
|
811
|
+
hasMetadata,
|
|
812
|
+
safe: true,
|
|
813
|
+
};
|
|
814
|
+
};
|
|
815
|
+
const isStaticWYWMetaTreeValue = (value) => {
|
|
816
|
+
const status = staticWYWMetaTreeValueStatus(value);
|
|
817
|
+
return status.safe && status.hasMetadata;
|
|
818
|
+
};
|
|
819
|
+
const isPlainObjectRecord = (value) => typeof value === 'object' &&
|
|
820
|
+
value !== null &&
|
|
821
|
+
!Array.isArray(value) &&
|
|
822
|
+
Object.getPrototypeOf(value) === Object.prototype;
|
|
823
|
+
const isStaticObjectAssignAliasValue = (value) => isStaticWYWMetaValue(value) || isStaticWYWMetaTreeValue(value);
|
|
824
|
+
const artifactCssText = (artifact) => {
|
|
825
|
+
if (!Array.isArray(artifact) || artifact[0] !== 'css') {
|
|
826
|
+
return null;
|
|
827
|
+
}
|
|
828
|
+
const payload = artifact[1];
|
|
829
|
+
if (Array.isArray(payload)) {
|
|
830
|
+
const [rules] = payload;
|
|
831
|
+
if (typeof rules === 'object' && rules !== null) {
|
|
832
|
+
return Object.values(rules)
|
|
833
|
+
.map((rule) => typeof rule === 'object' &&
|
|
834
|
+
rule !== null &&
|
|
835
|
+
'cssText' in rule &&
|
|
836
|
+
typeof rule.cssText === 'string'
|
|
837
|
+
? rule.cssText
|
|
838
|
+
: '')
|
|
839
|
+
.join('');
|
|
840
|
+
}
|
|
841
|
+
}
|
|
842
|
+
if (typeof payload === 'object' &&
|
|
843
|
+
payload !== null &&
|
|
844
|
+
'cssText' in payload &&
|
|
845
|
+
typeof payload.cssText === 'string') {
|
|
846
|
+
return payload.cssText;
|
|
847
|
+
}
|
|
848
|
+
return null;
|
|
849
|
+
};
|
|
850
|
+
const isEmptyProcessorClassName = (value, processors, cache) => {
|
|
851
|
+
if (cache.has(value)) {
|
|
852
|
+
return cache.get(value);
|
|
853
|
+
}
|
|
854
|
+
const processor = processors.find((item) => item.className === value);
|
|
855
|
+
if (!processor) {
|
|
856
|
+
cache.set(value, false);
|
|
857
|
+
return false;
|
|
858
|
+
}
|
|
859
|
+
if (processor.artifacts.length === 0) {
|
|
860
|
+
try {
|
|
861
|
+
processor.build(new Map());
|
|
862
|
+
}
|
|
863
|
+
catch {
|
|
864
|
+
cache.set(value, false);
|
|
865
|
+
return false;
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
const result = processor.artifacts.every((artifact) => {
|
|
869
|
+
const cssText = artifactCssText(artifact);
|
|
870
|
+
return cssText !== null && cssText.trim() === '';
|
|
871
|
+
});
|
|
872
|
+
cache.set(value, result);
|
|
873
|
+
return result;
|
|
874
|
+
};
|
|
875
|
+
const isProcessorClassName = (value, processors, cache) => {
|
|
876
|
+
if (cache.has(value)) {
|
|
877
|
+
return cache.get(value);
|
|
878
|
+
}
|
|
879
|
+
const processor = processors.find((item) => item.className === value);
|
|
880
|
+
if (!processor) {
|
|
881
|
+
cache.set(value, false);
|
|
882
|
+
return false;
|
|
883
|
+
}
|
|
884
|
+
if (processor.artifacts.length === 0) {
|
|
885
|
+
try {
|
|
886
|
+
processor.build(new Map());
|
|
887
|
+
}
|
|
888
|
+
catch {
|
|
889
|
+
cache.set(value, false);
|
|
890
|
+
return false;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
const result = processor.artifacts.every((artifact) => artifactCssText(artifact) !== null);
|
|
894
|
+
cache.set(value, result);
|
|
895
|
+
return result;
|
|
896
|
+
};
|
|
897
|
+
const isSelectorOnlyProcessorValue = (value, processors, cache, seen = new Set()) => {
|
|
898
|
+
if (typeof value === 'string') {
|
|
899
|
+
return isEmptyProcessorClassName(value, processors, cache);
|
|
900
|
+
}
|
|
901
|
+
if (Array.isArray(value)) {
|
|
902
|
+
if (seen.has(value)) {
|
|
903
|
+
return false;
|
|
904
|
+
}
|
|
905
|
+
seen.add(value);
|
|
906
|
+
return value.every((item) => isSelectorOnlyProcessorValue(item, processors, cache, seen));
|
|
907
|
+
}
|
|
908
|
+
if (typeof value === 'object' && value !== null) {
|
|
909
|
+
if (seen.has(value)) {
|
|
910
|
+
return false;
|
|
911
|
+
}
|
|
912
|
+
seen.add(value);
|
|
913
|
+
return Object.values(value).every((item) => isSelectorOnlyProcessorValue(item, processors, cache, seen));
|
|
914
|
+
}
|
|
915
|
+
return false;
|
|
916
|
+
};
|
|
917
|
+
const isProcessorClassValue = (value, processors, cache, seen = new Set()) => {
|
|
918
|
+
if (typeof value === 'string') {
|
|
919
|
+
return isProcessorClassName(value, processors, cache);
|
|
920
|
+
}
|
|
921
|
+
if (Array.isArray(value)) {
|
|
922
|
+
if (seen.has(value)) {
|
|
923
|
+
return false;
|
|
924
|
+
}
|
|
925
|
+
seen.add(value);
|
|
926
|
+
return value.every((item) => isProcessorClassValue(item, processors, cache, seen));
|
|
927
|
+
}
|
|
928
|
+
if (typeof value === 'object' && value !== null) {
|
|
929
|
+
if (seen.has(value)) {
|
|
930
|
+
return false;
|
|
931
|
+
}
|
|
932
|
+
seen.add(value);
|
|
933
|
+
return Object.values(value).every((item) => isProcessorClassValue(item, processors, cache, seen));
|
|
934
|
+
}
|
|
935
|
+
return false;
|
|
936
|
+
};
|
|
937
|
+
const collectLocalConstExpressions = (program) => {
|
|
938
|
+
const result = new Map();
|
|
939
|
+
const collect = (declaration) => {
|
|
940
|
+
if (declaration.kind !== 'const') {
|
|
941
|
+
return;
|
|
942
|
+
}
|
|
943
|
+
declaration.declarations.forEach((declarator) => {
|
|
944
|
+
if (declarator.id.type === 'Identifier' && declarator.init) {
|
|
945
|
+
result.set(declarator.id.name, declarator.init);
|
|
946
|
+
}
|
|
947
|
+
});
|
|
948
|
+
};
|
|
949
|
+
program.body.forEach((statement) => {
|
|
950
|
+
if (statement.type === 'VariableDeclaration') {
|
|
951
|
+
collect(statement);
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
if (statement.type === 'ExportNamedDeclaration' &&
|
|
955
|
+
statement.declaration?.type === 'VariableDeclaration') {
|
|
956
|
+
collect(statement.declaration);
|
|
957
|
+
}
|
|
958
|
+
});
|
|
959
|
+
return result;
|
|
960
|
+
};
|
|
961
|
+
const mutatingMethodNames = new Set([
|
|
962
|
+
'add',
|
|
963
|
+
'clear',
|
|
964
|
+
'copyWithin',
|
|
965
|
+
'delete',
|
|
966
|
+
'fill',
|
|
967
|
+
'pop',
|
|
968
|
+
'push',
|
|
969
|
+
'reverse',
|
|
970
|
+
'set',
|
|
971
|
+
'shift',
|
|
972
|
+
'sort',
|
|
973
|
+
'splice',
|
|
974
|
+
'unshift',
|
|
975
|
+
]);
|
|
976
|
+
const rootIdentifierName = (expr) => {
|
|
977
|
+
const unwrapped = unwrapExpression(expr);
|
|
978
|
+
if (unwrapped.type === 'Identifier') {
|
|
979
|
+
return unwrapped.name;
|
|
980
|
+
}
|
|
981
|
+
if (unwrapped.type === 'MemberExpression') {
|
|
982
|
+
return rootIdentifierName(unwrapped.object);
|
|
983
|
+
}
|
|
984
|
+
if (unwrapped.type === 'ChainExpression') {
|
|
985
|
+
return rootIdentifierName(unwrapped.expression);
|
|
986
|
+
}
|
|
987
|
+
return null;
|
|
988
|
+
};
|
|
989
|
+
const staticMemberName = (expr) => {
|
|
990
|
+
const unwrapped = unwrapExpression(expr);
|
|
991
|
+
if (unwrapped.type === 'Identifier') {
|
|
992
|
+
return unwrapped.name;
|
|
993
|
+
}
|
|
994
|
+
if (isSafeLiteral(unwrapped) && typeof unwrapped.value === 'string') {
|
|
995
|
+
return unwrapped.value;
|
|
996
|
+
}
|
|
997
|
+
return null;
|
|
998
|
+
};
|
|
999
|
+
const expressionMayProduceMutableValue = (expr, locals, visiting) => {
|
|
1000
|
+
const unwrapped = unwrapExpression(expr);
|
|
1001
|
+
if (unwrapped.type === 'ObjectExpression' ||
|
|
1002
|
+
unwrapped.type === 'ArrayExpression') {
|
|
1003
|
+
return true;
|
|
1004
|
+
}
|
|
1005
|
+
if (unwrapped.type === 'Identifier') {
|
|
1006
|
+
const local = locals.get(unwrapped.name);
|
|
1007
|
+
if (!local || visiting.has(unwrapped.name)) {
|
|
1008
|
+
return true;
|
|
1009
|
+
}
|
|
1010
|
+
visiting.add(unwrapped.name);
|
|
1011
|
+
const result = expressionMayProduceMutableValue(local, locals, visiting);
|
|
1012
|
+
visiting.delete(unwrapped.name);
|
|
1013
|
+
return result;
|
|
1014
|
+
}
|
|
1015
|
+
if (unwrapped.type === 'ConditionalExpression') {
|
|
1016
|
+
return (expressionMayProduceMutableValue(unwrapped.consequent, locals, visiting) ||
|
|
1017
|
+
expressionMayProduceMutableValue(unwrapped.alternate, locals, visiting));
|
|
1018
|
+
}
|
|
1019
|
+
if (unwrapped.type === 'LogicalExpression' ||
|
|
1020
|
+
unwrapped.type === 'MemberExpression') {
|
|
1021
|
+
return true;
|
|
1022
|
+
}
|
|
1023
|
+
return false;
|
|
1024
|
+
};
|
|
1025
|
+
const isSafeFunctionBodyExpression = (body, options) => {
|
|
1026
|
+
if (body.type !== 'BlockStatement') {
|
|
1027
|
+
return isSafeStaticExpression(body, options);
|
|
1028
|
+
}
|
|
1029
|
+
return body.body.every((statement) => {
|
|
1030
|
+
if (statement.type === 'VariableDeclaration') {
|
|
1031
|
+
return (statement.kind === 'const' &&
|
|
1032
|
+
statement.declarations.every((declarator) => declarator.init &&
|
|
1033
|
+
declarator.id.type === 'Identifier' &&
|
|
1034
|
+
isSafeStaticExpression(declarator.init, options)));
|
|
1035
|
+
}
|
|
1036
|
+
return (statement.type === 'ReturnStatement' &&
|
|
1037
|
+
!!statement.argument &&
|
|
1038
|
+
isSafeStaticExpression(statement.argument, options));
|
|
1039
|
+
});
|
|
1040
|
+
};
|
|
1041
|
+
const collectStaticFunctionBodyReferences = (body, references, options) => {
|
|
1042
|
+
if (body.type !== 'BlockStatement') {
|
|
1043
|
+
return collectStaticExpressionReferences(body, references, options);
|
|
1044
|
+
}
|
|
1045
|
+
return body.body.every((statement) => {
|
|
1046
|
+
if (statement.type === 'VariableDeclaration') {
|
|
1047
|
+
return (statement.kind === 'const' &&
|
|
1048
|
+
statement.declarations.every((declarator) => declarator.init &&
|
|
1049
|
+
declarator.id.type === 'Identifier' &&
|
|
1050
|
+
collectStaticExpressionReferences(declarator.init, references, options)));
|
|
1051
|
+
}
|
|
1052
|
+
return (statement.type === 'ReturnStatement' &&
|
|
1053
|
+
!!statement.argument &&
|
|
1054
|
+
collectStaticExpressionReferences(statement.argument, references, options));
|
|
1055
|
+
});
|
|
1056
|
+
};
|
|
1057
|
+
const collectStaticExpressionReferences = (expr, references, options = {}) => {
|
|
1058
|
+
const unwrapped = unwrapExpression(expr);
|
|
1059
|
+
if (isSafeLiteral(unwrapped)) {
|
|
1060
|
+
return true;
|
|
1061
|
+
}
|
|
1062
|
+
if (unwrapped.type === 'Identifier') {
|
|
1063
|
+
references.add(unwrapped.name);
|
|
1064
|
+
return true;
|
|
1065
|
+
}
|
|
1066
|
+
if (unwrapped.type === 'TemplateLiteral') {
|
|
1067
|
+
return unwrapped.expressions.every((item) => collectStaticExpressionReferences(item, references, options));
|
|
1068
|
+
}
|
|
1069
|
+
if (unwrapped.type === 'UnaryExpression') {
|
|
1070
|
+
return collectStaticExpressionReferences(unwrapped.argument, references, options);
|
|
1071
|
+
}
|
|
1072
|
+
if (unwrapped.type === 'BinaryExpression' ||
|
|
1073
|
+
unwrapped.type === 'LogicalExpression') {
|
|
1074
|
+
return (collectStaticExpressionReferences(unwrapped.left, references, options) &&
|
|
1075
|
+
collectStaticExpressionReferences(unwrapped.right, references, options));
|
|
1076
|
+
}
|
|
1077
|
+
if (unwrapped.type === 'ConditionalExpression') {
|
|
1078
|
+
return (collectStaticExpressionReferences(unwrapped.test, references, options) &&
|
|
1079
|
+
collectStaticExpressionReferences(unwrapped.consequent, references, options) &&
|
|
1080
|
+
collectStaticExpressionReferences(unwrapped.alternate, references, options));
|
|
1081
|
+
}
|
|
1082
|
+
if (unwrapped.type === 'MemberExpression') {
|
|
1083
|
+
if (isProcessEnvMember(unwrapped) || isProcessEnvMember(unwrapped.object)) {
|
|
1084
|
+
// process.env / process.env.X is an opaque build-time global —
|
|
1085
|
+
// don't treat `process` as an unresolved local reference.
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1088
|
+
return (collectStaticExpressionReferences(unwrapped.object, references, options) &&
|
|
1089
|
+
(!unwrapped.computed ||
|
|
1090
|
+
collectStaticExpressionReferences(unwrapped.property, references, options)));
|
|
1091
|
+
}
|
|
1092
|
+
if (options.allowMetadataCalls && unwrapped.type === 'CallExpression') {
|
|
1093
|
+
if (unwrapped.callee.type !== 'Identifier' ||
|
|
1094
|
+
unwrapped.arguments.length !== 0) {
|
|
1095
|
+
return false;
|
|
1096
|
+
}
|
|
1097
|
+
references.add(unwrapped.callee.name);
|
|
1098
|
+
return true;
|
|
1099
|
+
}
|
|
1100
|
+
if (options.allowMetadataCalls &&
|
|
1101
|
+
(unwrapped.type === 'ArrowFunctionExpression' ||
|
|
1102
|
+
unwrapped.type === 'FunctionExpression')) {
|
|
1103
|
+
if (unwrapped.async || unwrapped.params.length !== 0) {
|
|
1104
|
+
return false;
|
|
1105
|
+
}
|
|
1106
|
+
return (!!unwrapped.body &&
|
|
1107
|
+
collectStaticFunctionBodyReferences(unwrapped.body, references, options));
|
|
1108
|
+
}
|
|
1109
|
+
if (unwrapped.type === 'ArrayExpression') {
|
|
1110
|
+
return unwrapped.elements.every((item) => {
|
|
1111
|
+
if (!item) {
|
|
1112
|
+
return false;
|
|
1113
|
+
}
|
|
1114
|
+
return item.type === 'SpreadElement'
|
|
1115
|
+
? collectStaticExpressionReferences(item.argument, references, options)
|
|
1116
|
+
: collectStaticExpressionReferences(item, references, options);
|
|
1117
|
+
});
|
|
1118
|
+
}
|
|
1119
|
+
if (unwrapped.type === 'ObjectExpression') {
|
|
1120
|
+
return unwrapped.properties.every((property) => {
|
|
1121
|
+
if (property.type === 'SpreadElement') {
|
|
1122
|
+
return collectStaticExpressionReferences(property.argument, references, options);
|
|
1123
|
+
}
|
|
1124
|
+
const propertyNode = property;
|
|
1125
|
+
if (propertyNode.computed ||
|
|
1126
|
+
!propertyNode.value ||
|
|
1127
|
+
typeof propertyNode.value !== 'object') {
|
|
1128
|
+
return false;
|
|
1129
|
+
}
|
|
1130
|
+
return collectStaticExpressionReferences(propertyNode.value, references, options);
|
|
1131
|
+
});
|
|
1132
|
+
}
|
|
1133
|
+
return false;
|
|
1134
|
+
};
|
|
1135
|
+
const collectExpressionMutationHints = (expr, mutatedNames, callArgumentNames) => {
|
|
1136
|
+
const unwrapped = unwrapExpression(expr);
|
|
1137
|
+
if (unwrapped.type === 'AssignmentExpression') {
|
|
1138
|
+
const rootName = rootIdentifierName(unwrapped.left);
|
|
1139
|
+
if (rootName) {
|
|
1140
|
+
mutatedNames.add(rootName);
|
|
1141
|
+
}
|
|
1142
|
+
collectExpressionMutationHints(unwrapped.right, mutatedNames, callArgumentNames);
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
if (unwrapped.type === 'UpdateExpression') {
|
|
1146
|
+
const rootName = rootIdentifierName(unwrapped.argument);
|
|
1147
|
+
if (rootName) {
|
|
1148
|
+
mutatedNames.add(rootName);
|
|
1149
|
+
}
|
|
1150
|
+
return;
|
|
1151
|
+
}
|
|
1152
|
+
if (unwrapped.type === 'UnaryExpression') {
|
|
1153
|
+
if (unwrapped.operator === 'delete') {
|
|
1154
|
+
const rootName = rootIdentifierName(unwrapped.argument);
|
|
1155
|
+
if (rootName) {
|
|
1156
|
+
mutatedNames.add(rootName);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
collectExpressionMutationHints(unwrapped.argument, mutatedNames, callArgumentNames);
|
|
1160
|
+
return;
|
|
1161
|
+
}
|
|
1162
|
+
if (unwrapped.type === 'CallExpression') {
|
|
1163
|
+
const callee = unwrapExpression(unwrapped.callee);
|
|
1164
|
+
if (callee.type === 'MemberExpression') {
|
|
1165
|
+
const methodName = staticMemberName(callee.property);
|
|
1166
|
+
const rootName = rootIdentifierName(callee.object);
|
|
1167
|
+
if (rootName && methodName && mutatingMethodNames.has(methodName)) {
|
|
1168
|
+
mutatedNames.add(rootName);
|
|
1169
|
+
}
|
|
1170
|
+
collectExpressionMutationHints(callee.object, mutatedNames, callArgumentNames);
|
|
1171
|
+
if (callee.computed) {
|
|
1172
|
+
collectExpressionMutationHints(callee.property, mutatedNames, callArgumentNames);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
else {
|
|
1176
|
+
collectExpressionMutationHints(unwrapped.callee, mutatedNames, callArgumentNames);
|
|
1177
|
+
}
|
|
1178
|
+
unwrapped.arguments.forEach((argument) => {
|
|
1179
|
+
const argumentNode = argument.type === 'SpreadElement' ? argument.argument : argument;
|
|
1180
|
+
const rootName = rootIdentifierName(argumentNode);
|
|
1181
|
+
if (rootName) {
|
|
1182
|
+
callArgumentNames.add(rootName);
|
|
1183
|
+
}
|
|
1184
|
+
collectExpressionMutationHints(argumentNode, mutatedNames, callArgumentNames);
|
|
1185
|
+
});
|
|
1186
|
+
return;
|
|
1187
|
+
}
|
|
1188
|
+
if (unwrapped.type === 'TaggedTemplateExpression') {
|
|
1189
|
+
collectExpressionMutationHints(unwrapped.tag, mutatedNames, callArgumentNames);
|
|
1190
|
+
unwrapped.quasi.expressions.forEach((item) => collectExpressionMutationHints(item, mutatedNames, callArgumentNames));
|
|
1191
|
+
return;
|
|
1192
|
+
}
|
|
1193
|
+
if (unwrapped.type === 'ConditionalExpression') {
|
|
1194
|
+
collectExpressionMutationHints(unwrapped.test, mutatedNames, callArgumentNames);
|
|
1195
|
+
collectExpressionMutationHints(unwrapped.consequent, mutatedNames, callArgumentNames);
|
|
1196
|
+
collectExpressionMutationHints(unwrapped.alternate, mutatedNames, callArgumentNames);
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
if (unwrapped.type === 'BinaryExpression' ||
|
|
1200
|
+
unwrapped.type === 'LogicalExpression') {
|
|
1201
|
+
collectExpressionMutationHints(unwrapped.left, mutatedNames, callArgumentNames);
|
|
1202
|
+
collectExpressionMutationHints(unwrapped.right, mutatedNames, callArgumentNames);
|
|
1203
|
+
return;
|
|
1204
|
+
}
|
|
1205
|
+
if (unwrapped.type === 'MemberExpression') {
|
|
1206
|
+
collectExpressionMutationHints(unwrapped.object, mutatedNames, callArgumentNames);
|
|
1207
|
+
if (unwrapped.computed) {
|
|
1208
|
+
collectExpressionMutationHints(unwrapped.property, mutatedNames, callArgumentNames);
|
|
1209
|
+
}
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
if (unwrapped.type === 'ArrayExpression') {
|
|
1213
|
+
unwrapped.elements.forEach((item) => {
|
|
1214
|
+
if (!item) {
|
|
1215
|
+
return;
|
|
1216
|
+
}
|
|
1217
|
+
collectExpressionMutationHints(item.type === 'SpreadElement' ? item.argument : item, mutatedNames, callArgumentNames);
|
|
1218
|
+
});
|
|
1219
|
+
return;
|
|
1220
|
+
}
|
|
1221
|
+
if (unwrapped.type === 'ObjectExpression') {
|
|
1222
|
+
unwrapped.properties.forEach((property) => {
|
|
1223
|
+
if (property.type === 'SpreadElement') {
|
|
1224
|
+
collectExpressionMutationHints(property.argument, mutatedNames, callArgumentNames);
|
|
1225
|
+
return;
|
|
1226
|
+
}
|
|
1227
|
+
const propertyNode = property;
|
|
1228
|
+
if (propertyNode.computed && propertyNode.key) {
|
|
1229
|
+
collectExpressionMutationHints(propertyNode.key, mutatedNames, callArgumentNames);
|
|
1230
|
+
}
|
|
1231
|
+
if (propertyNode.value && typeof propertyNode.value === 'object') {
|
|
1232
|
+
collectExpressionMutationHints(propertyNode.value, mutatedNames, callArgumentNames);
|
|
1233
|
+
}
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
};
|
|
1237
|
+
const collectTopLevelMutationHints = (program) => {
|
|
1238
|
+
const callArgumentNames = new Set();
|
|
1239
|
+
const mutatedNames = new Set();
|
|
1240
|
+
const collectDeclaration = (declaration) => {
|
|
1241
|
+
declaration.declarations.forEach((declarator) => {
|
|
1242
|
+
if (declarator.init) {
|
|
1243
|
+
collectExpressionMutationHints(declarator.init, mutatedNames, callArgumentNames);
|
|
1244
|
+
}
|
|
1245
|
+
});
|
|
1246
|
+
};
|
|
1247
|
+
program.body.forEach((statement) => {
|
|
1248
|
+
if (statement.type === 'VariableDeclaration') {
|
|
1249
|
+
collectDeclaration(statement);
|
|
1250
|
+
return;
|
|
1251
|
+
}
|
|
1252
|
+
if (statement.type === 'ExpressionStatement') {
|
|
1253
|
+
collectExpressionMutationHints(statement.expression, mutatedNames, callArgumentNames);
|
|
1254
|
+
return;
|
|
1255
|
+
}
|
|
1256
|
+
if (statement.type === 'ExportNamedDeclaration') {
|
|
1257
|
+
if (statement.declaration?.type === 'VariableDeclaration') {
|
|
1258
|
+
collectDeclaration(statement.declaration);
|
|
1259
|
+
}
|
|
1260
|
+
return;
|
|
1261
|
+
}
|
|
1262
|
+
if (statement.type === 'ExportDefaultDeclaration') {
|
|
1263
|
+
if (statement.declaration.type !== 'FunctionDeclaration' &&
|
|
1264
|
+
statement.declaration.type !== 'ClassDeclaration') {
|
|
1265
|
+
collectExpressionMutationHints(statement.declaration, mutatedNames, callArgumentNames);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
});
|
|
1269
|
+
return { callArgumentNames, mutatedNames };
|
|
1270
|
+
};
|
|
1271
|
+
const objectPropertyKeyName = (node) => {
|
|
1272
|
+
const unwrapped = unwrapExpression(node);
|
|
1273
|
+
if (unwrapped.type === 'Identifier') {
|
|
1274
|
+
return unwrapped.name;
|
|
1275
|
+
}
|
|
1276
|
+
if (isSafeLiteral(unwrapped) && typeof unwrapped.value === 'string') {
|
|
1277
|
+
return unwrapped.value;
|
|
1278
|
+
}
|
|
1279
|
+
return null;
|
|
1280
|
+
};
|
|
1281
|
+
const findObjectPropertyValue = (expr, name) => {
|
|
1282
|
+
const unwrapped = unwrapExpression(expr);
|
|
1283
|
+
if (unwrapped.type !== 'ObjectExpression') {
|
|
1284
|
+
return null;
|
|
1285
|
+
}
|
|
1286
|
+
for (const property of unwrapped.properties) {
|
|
1287
|
+
if (property.type === 'SpreadElement') {
|
|
1288
|
+
continue;
|
|
1289
|
+
}
|
|
1290
|
+
const propertyNode = property;
|
|
1291
|
+
if (propertyNode.computed) {
|
|
1292
|
+
continue;
|
|
1293
|
+
}
|
|
1294
|
+
const key = propertyNode.key;
|
|
1295
|
+
const value = propertyNode.value;
|
|
1296
|
+
if (key && value && objectPropertyKeyName(key) === name) {
|
|
1297
|
+
return value;
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return null;
|
|
1301
|
+
};
|
|
1302
|
+
const findWYWMetaExtendsExpression = (expr) => {
|
|
1303
|
+
const meta = findObjectPropertyValue(expr, '__wyw_meta');
|
|
1304
|
+
if (!meta) {
|
|
1305
|
+
return null;
|
|
1306
|
+
}
|
|
1307
|
+
return findObjectPropertyValue(meta, 'extends');
|
|
1308
|
+
};
|
|
1309
|
+
const collectWYWMetaExtendsExpressions = (expr) => {
|
|
1310
|
+
const result = [];
|
|
1311
|
+
const visit = (node) => {
|
|
1312
|
+
if (node.type === 'ObjectExpression') {
|
|
1313
|
+
const extendsExpression = findWYWMetaExtendsExpression(node);
|
|
1314
|
+
if (extendsExpression) {
|
|
1315
|
+
result.push(extendsExpression);
|
|
1316
|
+
}
|
|
1317
|
+
}
|
|
1318
|
+
getChildren(node).forEach(visit);
|
|
1319
|
+
};
|
|
1320
|
+
visit(expr);
|
|
1321
|
+
return result;
|
|
1322
|
+
};
|
|
1323
|
+
const topLevelStatements = (program) => {
|
|
1324
|
+
const result = [];
|
|
1325
|
+
program.body.forEach((statement) => {
|
|
1326
|
+
if (statement.type === 'ExportNamedDeclaration' ||
|
|
1327
|
+
statement.type === 'ExportDefaultDeclaration') {
|
|
1328
|
+
result.push(statement.declaration ?? statement);
|
|
1329
|
+
return;
|
|
1330
|
+
}
|
|
1331
|
+
result.push(statement);
|
|
1332
|
+
});
|
|
1333
|
+
return result;
|
|
1334
|
+
};
|
|
1335
|
+
const findTopLevelConstExpression = (program, name) => {
|
|
1336
|
+
for (const statement of topLevelStatements(program)) {
|
|
1337
|
+
if (statement.type !== 'VariableDeclaration' ||
|
|
1338
|
+
statement.kind !== 'const') {
|
|
1339
|
+
continue;
|
|
1340
|
+
}
|
|
1341
|
+
for (const declarator of statement.declarations) {
|
|
1342
|
+
if (declarator.id.type === 'Identifier' &&
|
|
1343
|
+
declarator.id.name === name &&
|
|
1344
|
+
declarator.init) {
|
|
1345
|
+
return declarator.init;
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
return null;
|
|
1350
|
+
};
|
|
1351
|
+
const hasTopLevelBinding = (program, name) => {
|
|
1352
|
+
if (collectImportBindings(program).has(name)) {
|
|
1353
|
+
return true;
|
|
1354
|
+
}
|
|
1355
|
+
return topLevelStatements(program).some((statement) => {
|
|
1356
|
+
if (statement.type === 'VariableDeclaration') {
|
|
1357
|
+
return statement.declarations.some((declarator) => declarator.id.type === 'Identifier' && declarator.id.name === name);
|
|
1358
|
+
}
|
|
1359
|
+
if (statement.type === 'FunctionDeclaration') {
|
|
1360
|
+
return statement.id?.name === name;
|
|
1361
|
+
}
|
|
1362
|
+
if (statement.type === 'ClassDeclaration') {
|
|
1363
|
+
return statement.id?.name === name;
|
|
1364
|
+
}
|
|
1365
|
+
return false;
|
|
1366
|
+
});
|
|
1367
|
+
};
|
|
1368
|
+
const isTopLevelFunctionOrClass = (program, name) => topLevelStatements(program).some((statement) => {
|
|
1369
|
+
if (statement.type === 'FunctionDeclaration') {
|
|
1370
|
+
return statement.id?.name === name;
|
|
1371
|
+
}
|
|
1372
|
+
if (statement.type === 'ClassDeclaration') {
|
|
1373
|
+
return statement.id?.name === name;
|
|
1374
|
+
}
|
|
1375
|
+
return false;
|
|
1376
|
+
});
|
|
1377
|
+
const functionReturnExpression = (expr, options = {}) => {
|
|
1378
|
+
const unwrapped = unwrapExpression(expr);
|
|
1379
|
+
if (unwrapped.type !== 'ArrowFunctionExpression' &&
|
|
1380
|
+
unwrapped.type !== 'FunctionExpression') {
|
|
1381
|
+
return null;
|
|
1382
|
+
}
|
|
1383
|
+
if (unwrapped.async ||
|
|
1384
|
+
(!options.allowParams && unwrapped.params.length > 0) ||
|
|
1385
|
+
!unwrapped.body) {
|
|
1386
|
+
return null;
|
|
1387
|
+
}
|
|
1388
|
+
if (unwrapped.body.type !== 'BlockStatement') {
|
|
1389
|
+
return unwrapped.body;
|
|
1390
|
+
}
|
|
1391
|
+
if (unwrapped.body.body.length !== 1) {
|
|
1392
|
+
return null;
|
|
1393
|
+
}
|
|
1394
|
+
const [statement] = unwrapped.body.body;
|
|
1395
|
+
return statement.type === 'ReturnStatement' && statement.argument
|
|
1396
|
+
? statement.argument
|
|
1397
|
+
: null;
|
|
1398
|
+
};
|
|
1399
|
+
const isReactImport = (imports, localName) => imports.get(localName)?.source === 'react';
|
|
1400
|
+
const isReactFactoryName = (name) => name === 'forwardRef' || name === 'memo';
|
|
1401
|
+
const isKnownReactFactoryCall = (expr, imports) => {
|
|
1402
|
+
const unwrapped = unwrapExpression(expr);
|
|
1403
|
+
if (unwrapped.type !== 'CallExpression') {
|
|
1404
|
+
return false;
|
|
1405
|
+
}
|
|
1406
|
+
const callee = unwrapExpression(unwrapped.callee);
|
|
1407
|
+
if (callee.type === 'Identifier') {
|
|
1408
|
+
return (isReactFactoryName(callee.name) && isReactImport(imports, callee.name));
|
|
1409
|
+
}
|
|
1410
|
+
if (callee.type !== 'MemberExpression' || callee.computed) {
|
|
1411
|
+
return false;
|
|
1412
|
+
}
|
|
1413
|
+
const methodName = staticMemberName(callee.property);
|
|
1414
|
+
return (!!methodName &&
|
|
1415
|
+
isReactFactoryName(methodName) &&
|
|
1416
|
+
callee.object.type === 'Identifier' &&
|
|
1417
|
+
isReactImport(imports, callee.object.name));
|
|
1418
|
+
};
|
|
1419
|
+
const isKnownOpaqueRuntimeWrapperImport = (binding) => {
|
|
1420
|
+
if (!binding) {
|
|
1421
|
+
return false;
|
|
1422
|
+
}
|
|
1423
|
+
return (binding.imported === 'observer' &&
|
|
1424
|
+
(binding.source === 'mobx-react' || binding.source === 'mobx-react-lite'));
|
|
1425
|
+
};
|
|
1426
|
+
const isKnownOpaqueRuntimeWrapperCallee = (expr, imports) => {
|
|
1427
|
+
const callee = unwrapExpression(expr);
|
|
1428
|
+
if (callee.type === 'Identifier') {
|
|
1429
|
+
return isKnownOpaqueRuntimeWrapperImport(imports.get(callee.name));
|
|
1430
|
+
}
|
|
1431
|
+
return false;
|
|
1432
|
+
};
|
|
1433
|
+
const isKnownOpaqueRuntimeImportSource = (source) => /\.svg(?:$|[?#])/.test(source);
|
|
1434
|
+
const isKnownExternalRuntimeComponentImportSource = (source) => source.startsWith('@radix-ui/react-');
|
|
1435
|
+
const isStaticMetaObjectExpression = (expr) => {
|
|
1436
|
+
const meta = findObjectPropertyValue(expr, '__wyw_meta');
|
|
1437
|
+
return !!meta && findObjectPropertyValue(meta, 'className') !== null;
|
|
1438
|
+
};
|
|
1439
|
+
const isObjectAssignCallee = (program, expr) => {
|
|
1440
|
+
const unwrapped = unwrapExpression(expr);
|
|
1441
|
+
if (unwrapped.type !== 'MemberExpression' || unwrapped.computed) {
|
|
1442
|
+
return false;
|
|
1443
|
+
}
|
|
1444
|
+
const methodName = staticMemberName(unwrapped.property);
|
|
1445
|
+
return (methodName === 'assign' &&
|
|
1446
|
+
unwrapped.object.type === 'Identifier' &&
|
|
1447
|
+
unwrapped.object.name === 'Object' &&
|
|
1448
|
+
!hasTopLevelBinding(program, 'Object'));
|
|
1449
|
+
};
|
|
1450
|
+
const isSafeObjectAssignAliasExpression = (program, expr, seen = new Set()) => {
|
|
1451
|
+
const unwrapped = unwrapExpression(expr);
|
|
1452
|
+
if (unwrapped.type === 'Identifier') {
|
|
1453
|
+
if (seen.has(unwrapped.name)) {
|
|
1454
|
+
return false;
|
|
1455
|
+
}
|
|
1456
|
+
const local = findTopLevelConstExpression(program, unwrapped.name);
|
|
1457
|
+
if (!local) {
|
|
1458
|
+
return false;
|
|
1459
|
+
}
|
|
1460
|
+
seen.add(unwrapped.name);
|
|
1461
|
+
const result = isSafeObjectAssignAliasExpression(program, local, seen);
|
|
1462
|
+
seen.delete(unwrapped.name);
|
|
1463
|
+
return result;
|
|
1464
|
+
}
|
|
1465
|
+
if (unwrapped.type !== 'ObjectExpression') {
|
|
1466
|
+
return false;
|
|
1467
|
+
}
|
|
1468
|
+
return unwrapped.properties.every((property) => {
|
|
1469
|
+
if (property.type === 'SpreadElement') {
|
|
1470
|
+
return false;
|
|
1471
|
+
}
|
|
1472
|
+
const propertyNode = property;
|
|
1473
|
+
if (propertyNode.computed ||
|
|
1474
|
+
propertyNode.method ||
|
|
1475
|
+
!propertyNode.value ||
|
|
1476
|
+
typeof propertyNode.value !== 'object') {
|
|
1477
|
+
return false;
|
|
1478
|
+
}
|
|
1479
|
+
return isSafeStaticExpression(propertyNode.value);
|
|
1480
|
+
});
|
|
1481
|
+
};
|
|
1482
|
+
const objectAssignTargetExpression = (program, expr) => {
|
|
1483
|
+
const unwrapped = unwrapExpression(expr);
|
|
1484
|
+
if (unwrapped.type !== 'CallExpression' ||
|
|
1485
|
+
!isObjectAssignCallee(program, unwrapped.callee) ||
|
|
1486
|
+
unwrapped.arguments.length < 2) {
|
|
1487
|
+
return null;
|
|
1488
|
+
}
|
|
1489
|
+
const [target, ...aliases] = unwrapped.arguments;
|
|
1490
|
+
if (!target || target.type === 'SpreadElement') {
|
|
1491
|
+
return null;
|
|
1492
|
+
}
|
|
1493
|
+
if (aliases.some((alias) => alias.type === 'SpreadElement' ||
|
|
1494
|
+
!isSafeObjectAssignAliasExpression(program, alias))) {
|
|
1495
|
+
return null;
|
|
1496
|
+
}
|
|
1497
|
+
return target;
|
|
1498
|
+
};
|
|
1499
|
+
const objectAssignAliasExpressions = (program, expr) => {
|
|
1500
|
+
const unwrapped = unwrapExpression(expr);
|
|
1501
|
+
if (unwrapped.type !== 'CallExpression' ||
|
|
1502
|
+
!isObjectAssignCallee(program, unwrapped.callee) ||
|
|
1503
|
+
unwrapped.arguments.length < 2) {
|
|
1504
|
+
return null;
|
|
1505
|
+
}
|
|
1506
|
+
const [, ...aliases] = unwrapped.arguments;
|
|
1507
|
+
if (aliases.some((alias) => alias.type === 'SpreadElement' ||
|
|
1508
|
+
!isSafeObjectAssignAliasExpression(program, alias))) {
|
|
1509
|
+
return null;
|
|
1510
|
+
}
|
|
1511
|
+
return aliases;
|
|
1512
|
+
};
|
|
1513
|
+
const isFunctionBoundaryNode = (node) => node.type === 'ArrowFunctionExpression' ||
|
|
1514
|
+
node.type === 'FunctionDeclaration' ||
|
|
1515
|
+
node.type === 'FunctionExpression' ||
|
|
1516
|
+
node.type === 'ClassDeclaration' ||
|
|
1517
|
+
node.type === 'ClassExpression';
|
|
1518
|
+
const callHasArgumentRootName = (expr, targetName) => {
|
|
1519
|
+
const unwrapped = unwrapExpression(expr);
|
|
1520
|
+
return (unwrapped.type === 'CallExpression' &&
|
|
1521
|
+
unwrapped.arguments.some((argument) => {
|
|
1522
|
+
const argumentNode = argument.type === 'SpreadElement' ? argument.argument : argument;
|
|
1523
|
+
return rootIdentifierName(argumentNode) === targetName;
|
|
1524
|
+
}));
|
|
1525
|
+
};
|
|
1526
|
+
const isSafeObjectAssignAliasAugmentation = (program, expr, targetName) => {
|
|
1527
|
+
const unwrapped = unwrapExpression(expr);
|
|
1528
|
+
if (unwrapped.type !== 'CallExpression' ||
|
|
1529
|
+
!isObjectAssignCallee(program, unwrapped.callee) ||
|
|
1530
|
+
unwrapped.arguments.length < 2) {
|
|
1531
|
+
return false;
|
|
1532
|
+
}
|
|
1533
|
+
const [target, ...aliases] = unwrapped.arguments;
|
|
1534
|
+
if (!target || target.type === 'SpreadElement') {
|
|
1535
|
+
return false;
|
|
1536
|
+
}
|
|
1537
|
+
const unwrappedTarget = unwrapExpression(target);
|
|
1538
|
+
if (unwrappedTarget.type !== 'Identifier' ||
|
|
1539
|
+
unwrappedTarget.name !== targetName) {
|
|
1540
|
+
return false;
|
|
1541
|
+
}
|
|
1542
|
+
return aliases.every((alias) => alias.type !== 'SpreadElement' &&
|
|
1543
|
+
isSafeObjectAssignAliasExpression(program, alias));
|
|
1544
|
+
};
|
|
1545
|
+
const hasOnlySafeObjectAssignCallArgumentUses = (program, targetName) => {
|
|
1546
|
+
let hasSafeUse = false;
|
|
1547
|
+
let hasUnsafeUse = false;
|
|
1548
|
+
const visit = (node) => {
|
|
1549
|
+
if (hasUnsafeUse || isFunctionBoundaryNode(node)) {
|
|
1550
|
+
return;
|
|
1551
|
+
}
|
|
1552
|
+
const unwrapped = unwrapExpression(node);
|
|
1553
|
+
if (unwrapped.type === 'CallExpression') {
|
|
1554
|
+
if (callHasArgumentRootName(unwrapped, targetName)) {
|
|
1555
|
+
if (isSafeObjectAssignAliasAugmentation(program, unwrapped, targetName)) {
|
|
1556
|
+
hasSafeUse = true;
|
|
1557
|
+
}
|
|
1558
|
+
else {
|
|
1559
|
+
hasUnsafeUse = true;
|
|
1560
|
+
return;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
getChildren(node).forEach(visit);
|
|
1565
|
+
};
|
|
1566
|
+
topLevelStatements(program).forEach(visit);
|
|
1567
|
+
return hasSafeUse && !hasUnsafeUse;
|
|
1568
|
+
};
|
|
1569
|
+
const objectAssignAugmentationAliasExpressions = (program, targetName) => {
|
|
1570
|
+
const aliases = [];
|
|
1571
|
+
let hasUnsafeUse = false;
|
|
1572
|
+
const visit = (node) => {
|
|
1573
|
+
if (hasUnsafeUse || isFunctionBoundaryNode(node)) {
|
|
1574
|
+
return;
|
|
1575
|
+
}
|
|
1576
|
+
const unwrapped = unwrapExpression(node);
|
|
1577
|
+
if (unwrapped.type === 'CallExpression') {
|
|
1578
|
+
if (callHasArgumentRootName(unwrapped, targetName)) {
|
|
1579
|
+
if (isSafeObjectAssignAliasAugmentation(program, unwrapped, targetName)) {
|
|
1580
|
+
const [, ...nextAliases] = unwrapped.arguments;
|
|
1581
|
+
aliases.push(...nextAliases);
|
|
1582
|
+
}
|
|
1583
|
+
else {
|
|
1584
|
+
hasUnsafeUse = true;
|
|
1585
|
+
}
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
getChildren(node).forEach(visit);
|
|
1590
|
+
};
|
|
1591
|
+
topLevelStatements(program).forEach(visit);
|
|
1592
|
+
return !hasUnsafeUse && aliases.length > 0 ? aliases : null;
|
|
1593
|
+
};
|
|
1594
|
+
const objectAssignAliasExpressionsForTarget = (program, target) => {
|
|
1595
|
+
const aliases = [
|
|
1596
|
+
...(objectAssignAliasExpressions(program, target.expression) ?? []),
|
|
1597
|
+
...(target.localName
|
|
1598
|
+
? objectAssignAugmentationAliasExpressions(program, target.localName) ??
|
|
1599
|
+
[]
|
|
1600
|
+
: []),
|
|
1601
|
+
];
|
|
1602
|
+
return aliases.length > 0 ? aliases : null;
|
|
1603
|
+
};
|
|
1604
|
+
const resolveObjectAssignProcessorExpression = (program, expr) => {
|
|
1605
|
+
const objectAssignTarget = objectAssignTargetExpression(program, expr);
|
|
1606
|
+
const target = objectAssignTarget ?? expr;
|
|
1607
|
+
if (target.type !== 'Identifier') {
|
|
1608
|
+
return target;
|
|
1609
|
+
}
|
|
1610
|
+
return findTopLevelConstExpression(program, target.name) ?? target;
|
|
1611
|
+
};
|
|
1612
|
+
const mergeStaticObjectAssignAliases = (targetValue, aliasValues) => {
|
|
1613
|
+
if (!isPlainObjectRecord(targetValue) || !isStaticWYWMetaValue(targetValue)) {
|
|
1614
|
+
return null;
|
|
1615
|
+
}
|
|
1616
|
+
const result = { ...targetValue };
|
|
1617
|
+
aliasValues.forEach((aliasValue) => {
|
|
1618
|
+
Object.assign(result, aliasValue);
|
|
1619
|
+
});
|
|
1620
|
+
return result;
|
|
1621
|
+
};
|
|
1622
|
+
const objectAssignAliasObjectExpression = (program, alias, seen = new Set()) => {
|
|
1623
|
+
const unwrapped = unwrapExpression(alias);
|
|
1624
|
+
if (unwrapped.type === 'ObjectExpression') {
|
|
1625
|
+
return unwrapped;
|
|
1626
|
+
}
|
|
1627
|
+
if (unwrapped.type !== 'Identifier' || seen.has(unwrapped.name)) {
|
|
1628
|
+
return null;
|
|
1629
|
+
}
|
|
1630
|
+
const local = findTopLevelConstExpression(program, unwrapped.name);
|
|
1631
|
+
if (!local) {
|
|
1632
|
+
return null;
|
|
1633
|
+
}
|
|
1634
|
+
seen.add(unwrapped.name);
|
|
1635
|
+
const result = objectAssignAliasObjectExpression(program, local, seen);
|
|
1636
|
+
seen.delete(unwrapped.name);
|
|
1637
|
+
return result;
|
|
1638
|
+
};
|
|
1639
|
+
const objectAssignAliasPropertyEntries = (program, alias) => {
|
|
1640
|
+
const aliasObject = objectAssignAliasObjectExpression(program, alias);
|
|
1641
|
+
if (!aliasObject || aliasObject.type !== 'ObjectExpression') {
|
|
1642
|
+
return null;
|
|
1643
|
+
}
|
|
1644
|
+
const entries = [];
|
|
1645
|
+
for (const property of aliasObject.properties) {
|
|
1646
|
+
if (property.type === 'SpreadElement') {
|
|
1647
|
+
return null;
|
|
1648
|
+
}
|
|
1649
|
+
const propertyNode = property;
|
|
1650
|
+
if (propertyNode.computed ||
|
|
1651
|
+
propertyNode.method ||
|
|
1652
|
+
!propertyNode.key ||
|
|
1653
|
+
!propertyNode.value ||
|
|
1654
|
+
typeof propertyNode.key !== 'object' ||
|
|
1655
|
+
typeof propertyNode.value !== 'object') {
|
|
1656
|
+
return null;
|
|
1657
|
+
}
|
|
1658
|
+
const key = objectPropertyKeyName(propertyNode.key);
|
|
1659
|
+
if (!key) {
|
|
1660
|
+
return null;
|
|
1661
|
+
}
|
|
1662
|
+
entries.push({
|
|
1663
|
+
key,
|
|
1664
|
+
value: propertyNode.value,
|
|
1665
|
+
});
|
|
1666
|
+
}
|
|
1667
|
+
return entries;
|
|
1668
|
+
};
|
|
1669
|
+
function* resolveObjectAssignAliasExpressionValue(action, filename, code, program, expression, ignoredMutableCallArgumentNames, stack, memo) {
|
|
1670
|
+
const staticDependencies = collectStaticExpressionDependencies(program, {
|
|
1671
|
+
expression,
|
|
1672
|
+
kind: 'expression',
|
|
1673
|
+
}, {
|
|
1674
|
+
allowMetadataCalls: true,
|
|
1675
|
+
ignoredMutableCallArgumentNames,
|
|
1676
|
+
});
|
|
1677
|
+
if (!staticDependencies) {
|
|
1678
|
+
return null;
|
|
1679
|
+
}
|
|
1680
|
+
const env = new Map();
|
|
1681
|
+
const dependencies = new Set();
|
|
1682
|
+
const sideEffectDependencies = new Set();
|
|
1683
|
+
for (const binding of staticDependencies.imports) {
|
|
1684
|
+
const resolved = yield* resolveImportValue(action, filename, binding, stack, memo);
|
|
1685
|
+
if (!resolved ||
|
|
1686
|
+
!bindStaticResolvedValue(env, expression, binding.local, resolved)) {
|
|
1687
|
+
return null;
|
|
1688
|
+
}
|
|
1689
|
+
resolved.dependencies.forEach((item) => dependencies.add(item));
|
|
1690
|
+
resolved.sideEffectDependencies?.forEach((item) => sideEffectDependencies.add(item));
|
|
1691
|
+
}
|
|
1692
|
+
const value = evaluateOxcStaticExpressionAt(code, filename, {
|
|
1693
|
+
end: expression.end,
|
|
1694
|
+
start: expression.start,
|
|
1695
|
+
}, env);
|
|
1696
|
+
return isStaticObjectAssignAliasValue(value)
|
|
1697
|
+
? {
|
|
1698
|
+
dependencies: [...dependencies],
|
|
1699
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
1700
|
+
value,
|
|
1701
|
+
}
|
|
1702
|
+
: null;
|
|
1703
|
+
}
|
|
1704
|
+
function* resolveObjectAssignAliasPropertyValue(action, filename, code, program, expression, ignoredMutableCallArgumentNames, stack, memo) {
|
|
1705
|
+
const expressionValue = yield* resolveObjectAssignAliasExpressionValue(action, filename, code, program, expression, ignoredMutableCallArgumentNames, stack, memo);
|
|
1706
|
+
if (expressionValue) {
|
|
1707
|
+
return expressionValue;
|
|
1708
|
+
}
|
|
1709
|
+
const unwrapped = unwrapExpression(expression);
|
|
1710
|
+
if (unwrapped.type !== 'Identifier' ||
|
|
1711
|
+
!findExportTarget(program, unwrapped.name)) {
|
|
1712
|
+
return null;
|
|
1713
|
+
}
|
|
1714
|
+
const resolved = yield* resolveStaticExport(action, filename, unwrapped.name, stack, memo);
|
|
1715
|
+
return resolved && isStaticObjectAssignAliasValue(resolved.value)
|
|
1716
|
+
? {
|
|
1717
|
+
dependencies: resolved.dependencies,
|
|
1718
|
+
sideEffectDependencies: resolved.sideEffectDependencies ?? [],
|
|
1719
|
+
value: resolved.value,
|
|
1720
|
+
}
|
|
1721
|
+
: null;
|
|
1722
|
+
}
|
|
1723
|
+
function* resolveObjectAssignAliasValue(action, filename, code, program, alias, ignoredMutableCallArgumentNames, stack, memo) {
|
|
1724
|
+
const aliasValue = yield* resolveObjectAssignAliasExpressionValue(action, filename, code, program, alias, ignoredMutableCallArgumentNames, stack, memo);
|
|
1725
|
+
if (aliasValue && isPlainObjectRecord(aliasValue.value)) {
|
|
1726
|
+
return Object.values(aliasValue.value).every(isStaticObjectAssignAliasValue)
|
|
1727
|
+
? {
|
|
1728
|
+
dependencies: aliasValue.dependencies,
|
|
1729
|
+
sideEffectDependencies: aliasValue.sideEffectDependencies,
|
|
1730
|
+
value: aliasValue.value,
|
|
1731
|
+
}
|
|
1732
|
+
: null;
|
|
1733
|
+
}
|
|
1734
|
+
const entries = objectAssignAliasPropertyEntries(program, alias);
|
|
1735
|
+
if (!entries) {
|
|
1736
|
+
return null;
|
|
1737
|
+
}
|
|
1738
|
+
const dependencies = new Set();
|
|
1739
|
+
const sideEffectDependencies = new Set();
|
|
1740
|
+
const value = {};
|
|
1741
|
+
for (const entry of entries) {
|
|
1742
|
+
const resolved = yield* resolveObjectAssignAliasPropertyValue(action, filename, code, program, entry.value, ignoredMutableCallArgumentNames, stack, memo);
|
|
1743
|
+
if (!resolved || !isStaticObjectAssignAliasValue(resolved.value)) {
|
|
1744
|
+
return null;
|
|
1745
|
+
}
|
|
1746
|
+
value[entry.key] = resolved.value;
|
|
1747
|
+
resolved.dependencies.forEach((item) => dependencies.add(item));
|
|
1748
|
+
resolved.sideEffectDependencies.forEach((item) => sideEffectDependencies.add(item));
|
|
1749
|
+
}
|
|
1750
|
+
return {
|
|
1751
|
+
dependencies: [...dependencies],
|
|
1752
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
1753
|
+
value,
|
|
1754
|
+
};
|
|
1755
|
+
}
|
|
1756
|
+
function* resolveObjectAssignAliasValues(action, filename, code, program, aliases, stack, memo) {
|
|
1757
|
+
const dependencies = new Set();
|
|
1758
|
+
const sideEffectDependencies = new Set();
|
|
1759
|
+
const values = [];
|
|
1760
|
+
const ignoredMutableCallArgumentNames = new Set();
|
|
1761
|
+
aliases.forEach((alias) => {
|
|
1762
|
+
const name = rootIdentifierName(alias);
|
|
1763
|
+
if (name) {
|
|
1764
|
+
ignoredMutableCallArgumentNames.add(name);
|
|
1765
|
+
}
|
|
1766
|
+
});
|
|
1767
|
+
for (const alias of aliases) {
|
|
1768
|
+
const aliasValue = yield* resolveObjectAssignAliasValue(action, filename, code, program, alias, ignoredMutableCallArgumentNames, stack, memo);
|
|
1769
|
+
if (!aliasValue) {
|
|
1770
|
+
return null;
|
|
1771
|
+
}
|
|
1772
|
+
aliasValue.dependencies.forEach((item) => dependencies.add(item));
|
|
1773
|
+
aliasValue.sideEffectDependencies.forEach((item) => sideEffectDependencies.add(item));
|
|
1774
|
+
values.push(aliasValue.value);
|
|
1775
|
+
}
|
|
1776
|
+
return {
|
|
1777
|
+
dependencies: [...dependencies],
|
|
1778
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
1779
|
+
values,
|
|
1780
|
+
};
|
|
1781
|
+
}
|
|
1782
|
+
const isOpaqueRuntimeComponentExpression = (program, expr, opaqueImportNames = new Set(), seen = new Set()) => {
|
|
1783
|
+
const imports = collectImportBindings(program, { includeNamespace: true });
|
|
1784
|
+
const unwrapped = unwrapExpression(expr);
|
|
1785
|
+
if (isStaticMetaObjectExpression(unwrapped)) {
|
|
1786
|
+
return false;
|
|
1787
|
+
}
|
|
1788
|
+
if (unwrapped.type === 'ArrowFunctionExpression' ||
|
|
1789
|
+
unwrapped.type === 'FunctionExpression' ||
|
|
1790
|
+
unwrapped.type === 'ClassExpression') {
|
|
1791
|
+
return true;
|
|
1792
|
+
}
|
|
1793
|
+
if (isKnownReactFactoryCall(unwrapped, imports)) {
|
|
1794
|
+
return true;
|
|
1795
|
+
}
|
|
1796
|
+
if (unwrapped.type === 'CallExpression' &&
|
|
1797
|
+
unwrapped.arguments.length === 1 &&
|
|
1798
|
+
isKnownOpaqueRuntimeWrapperCallee(unwrapped.callee, imports)) {
|
|
1799
|
+
const [argument] = unwrapped.arguments;
|
|
1800
|
+
return argument.type !== 'SpreadElement'
|
|
1801
|
+
? isOpaqueRuntimeComponentExpression(program, argument, opaqueImportNames, seen)
|
|
1802
|
+
: false;
|
|
1803
|
+
}
|
|
1804
|
+
if (unwrapped.type === 'CallExpression' &&
|
|
1805
|
+
unwrapped.callee.type === 'Identifier') {
|
|
1806
|
+
const allowParams = unwrapped.arguments.every((argument) => argument.type !== 'SpreadElement' && isSafeStaticExpression(argument));
|
|
1807
|
+
const local = findTopLevelConstExpression(program, unwrapped.callee.name);
|
|
1808
|
+
const returned = local
|
|
1809
|
+
? functionReturnExpression(local, { allowParams })
|
|
1810
|
+
: null;
|
|
1811
|
+
return returned
|
|
1812
|
+
? isOpaqueRuntimeComponentExpression(program, returned, opaqueImportNames, seen)
|
|
1813
|
+
: false;
|
|
1814
|
+
}
|
|
1815
|
+
if (unwrapped.type === 'MemberExpression' && !unwrapped.computed) {
|
|
1816
|
+
const name = rootIdentifierName(unwrapped);
|
|
1817
|
+
const imported = name ? imports.get(name) : undefined;
|
|
1818
|
+
return (!!name &&
|
|
1819
|
+
!!imported &&
|
|
1820
|
+
(opaqueImportNames.has(name) ||
|
|
1821
|
+
isKnownExternalRuntimeComponentImportSource(imported.source)));
|
|
1822
|
+
}
|
|
1823
|
+
if (unwrapped.type !== 'Identifier') {
|
|
1824
|
+
return false;
|
|
1825
|
+
}
|
|
1826
|
+
const { name } = unwrapped;
|
|
1827
|
+
if (seen.has(name)) {
|
|
1828
|
+
return false;
|
|
1829
|
+
}
|
|
1830
|
+
seen.add(name);
|
|
1831
|
+
const imported = imports.get(name);
|
|
1832
|
+
if (imported) {
|
|
1833
|
+
return (opaqueImportNames.has(name) ||
|
|
1834
|
+
isKnownOpaqueRuntimeImportSource(imported.source) ||
|
|
1835
|
+
isKnownExternalRuntimeComponentImportSource(imported.source));
|
|
1836
|
+
}
|
|
1837
|
+
if (isTopLevelFunctionOrClass(program, name)) {
|
|
1838
|
+
return true;
|
|
1839
|
+
}
|
|
1840
|
+
const local = findTopLevelConstExpression(program, name);
|
|
1841
|
+
return local
|
|
1842
|
+
? isOpaqueRuntimeComponentExpression(program, local, opaqueImportNames, seen)
|
|
1843
|
+
: false;
|
|
1844
|
+
};
|
|
1845
|
+
const collectOpaqueRuntimeReferenceNames = (program, expr, names, seenHelpers = new Set()) => {
|
|
1846
|
+
const unwrapped = unwrapExpression(expr);
|
|
1847
|
+
if (unwrapped.type === 'CallExpression' &&
|
|
1848
|
+
unwrapped.callee.type === 'Identifier') {
|
|
1849
|
+
const allowParams = unwrapped.arguments.every((argument) => argument.type !== 'SpreadElement' && isSafeStaticExpression(argument));
|
|
1850
|
+
if (seenHelpers.has(unwrapped.callee.name)) {
|
|
1851
|
+
return;
|
|
1852
|
+
}
|
|
1853
|
+
const local = findTopLevelConstExpression(program, unwrapped.callee.name);
|
|
1854
|
+
const returned = local
|
|
1855
|
+
? functionReturnExpression(local, { allowParams })
|
|
1856
|
+
: null;
|
|
1857
|
+
if (returned) {
|
|
1858
|
+
seenHelpers.add(unwrapped.callee.name);
|
|
1859
|
+
collectOpaqueRuntimeReferenceNames(program, returned, names, seenHelpers);
|
|
1860
|
+
seenHelpers.delete(unwrapped.callee.name);
|
|
1861
|
+
return;
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
if (unwrapped.type === 'Identifier') {
|
|
1865
|
+
names.add(unwrapped.name);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
getChildren(unwrapped).forEach((child) => collectOpaqueRuntimeReferenceNames(program, child, names, seenHelpers));
|
|
1869
|
+
};
|
|
1870
|
+
const collectWYWMetaExtendsHelperNames = (program) => {
|
|
1871
|
+
const result = new Set();
|
|
1872
|
+
const visit = (node) => {
|
|
1873
|
+
if (node.type === 'ObjectExpression') {
|
|
1874
|
+
const extendsExpression = findWYWMetaExtendsExpression(node);
|
|
1875
|
+
const unwrapped = extendsExpression
|
|
1876
|
+
? unwrapExpression(extendsExpression)
|
|
1877
|
+
: null;
|
|
1878
|
+
if (unwrapped?.type === 'CallExpression' &&
|
|
1879
|
+
unwrapped.callee.type === 'Identifier' &&
|
|
1880
|
+
unwrapped.arguments.length === 0) {
|
|
1881
|
+
result.add(unwrapped.callee.name);
|
|
1882
|
+
}
|
|
1883
|
+
}
|
|
1884
|
+
getChildren(node).forEach(visit);
|
|
1885
|
+
};
|
|
1886
|
+
visit(program);
|
|
1887
|
+
return result;
|
|
1888
|
+
};
|
|
1889
|
+
const replaceExpressionChildren = (code, expression, replacements) => {
|
|
1890
|
+
const expressionCode = code.slice(expression.start, expression.end);
|
|
1891
|
+
return applyReplacements(expressionCode, replacements.map(({ child, replacement }) => ({
|
|
1892
|
+
end: child.end - expression.start,
|
|
1893
|
+
start: child.start - expression.start,
|
|
1894
|
+
text: replacement,
|
|
1895
|
+
})));
|
|
1896
|
+
};
|
|
1897
|
+
const parseSyntheticExpression = (expressionCode, filename) => {
|
|
1898
|
+
const program = parseProgram(`const __wyw_static_target = ${expressionCode};`, filename);
|
|
1899
|
+
const declaration = program.body[0];
|
|
1900
|
+
if (declaration?.type !== 'VariableDeclaration') {
|
|
1901
|
+
return null;
|
|
1902
|
+
}
|
|
1903
|
+
const [declarator] = declaration.declarations;
|
|
1904
|
+
return declarator?.init ?? null;
|
|
1905
|
+
};
|
|
1906
|
+
const prepareProcessorTarget = (code, filename, program, target, opaqueImportNames = new Set()) => {
|
|
1907
|
+
const ignoredMutableCallArgumentNames = target.localName &&
|
|
1908
|
+
hasOnlySafeObjectAssignCallArgumentUses(program, target.localName)
|
|
1909
|
+
? new Set([target.localName])
|
|
1910
|
+
: undefined;
|
|
1911
|
+
const dependencyOptions = {
|
|
1912
|
+
allowMetadataCalls: true,
|
|
1913
|
+
ignoredMutableCallArgumentNames,
|
|
1914
|
+
};
|
|
1915
|
+
const expression = resolveObjectAssignProcessorExpression(program, target.expression);
|
|
1916
|
+
const extendsExpressions = collectWYWMetaExtendsExpressions(expression);
|
|
1917
|
+
const opaqueExtendsExpressions = extendsExpressions.filter((extendsExpression) => isOpaqueRuntimeComponentExpression(program, extendsExpression, opaqueImportNames));
|
|
1918
|
+
if (opaqueExtendsExpressions.length > 0) {
|
|
1919
|
+
const replacements = opaqueExtendsExpressions.map((extendsExpression) => ({
|
|
1920
|
+
child: extendsExpression,
|
|
1921
|
+
replacement: 'null',
|
|
1922
|
+
}));
|
|
1923
|
+
const expressionCode = replaceExpressionChildren(code, expression, replacements);
|
|
1924
|
+
const syntheticExpression = parseSyntheticExpression(expressionCode, filename);
|
|
1925
|
+
if (!syntheticExpression) {
|
|
1926
|
+
return null;
|
|
1927
|
+
}
|
|
1928
|
+
const dependencies = collectStaticExpressionDependencies(program, {
|
|
1929
|
+
...target,
|
|
1930
|
+
expression: syntheticExpression,
|
|
1931
|
+
}, dependencyOptions);
|
|
1932
|
+
return dependencies
|
|
1933
|
+
? {
|
|
1934
|
+
dependencies,
|
|
1935
|
+
evaluationCode: applyReplacements(code, replacements.map(({ child, replacement }) => ({
|
|
1936
|
+
end: child.end,
|
|
1937
|
+
start: child.start,
|
|
1938
|
+
text: replacement,
|
|
1939
|
+
}))),
|
|
1940
|
+
evaluationSpan: {
|
|
1941
|
+
end: expression.end +
|
|
1942
|
+
replacements.reduce((delta, { child, replacement }) => delta + replacement.length - (child.end - child.start), 0),
|
|
1943
|
+
start: expression.start,
|
|
1944
|
+
},
|
|
1945
|
+
expression,
|
|
1946
|
+
opaqueRuntimeBase: true,
|
|
1947
|
+
}
|
|
1948
|
+
: null;
|
|
1949
|
+
}
|
|
1950
|
+
const dependencies = collectStaticExpressionDependencies(program, {
|
|
1951
|
+
...target,
|
|
1952
|
+
expression,
|
|
1953
|
+
}, dependencyOptions);
|
|
1954
|
+
return dependencies
|
|
1955
|
+
? {
|
|
1956
|
+
dependencies,
|
|
1957
|
+
expression,
|
|
1958
|
+
opaqueRuntimeBase: false,
|
|
1959
|
+
}
|
|
1960
|
+
: null;
|
|
1961
|
+
};
|
|
1962
|
+
const collectStaticExpressionDependencies = (program, target, options = {}) => {
|
|
1963
|
+
const imports = collectImportBindings(program);
|
|
1964
|
+
const locals = collectLocalConstExpressions(program);
|
|
1965
|
+
const collectedImports = new Map();
|
|
1966
|
+
const referencedNames = new Set();
|
|
1967
|
+
const mutableReferencedNames = new Set();
|
|
1968
|
+
const visitedLocals = new Set();
|
|
1969
|
+
const visitingLocals = new Set();
|
|
1970
|
+
const markMutable = (name, expression) => {
|
|
1971
|
+
if (expressionMayProduceMutableValue(expression, locals, new Set())) {
|
|
1972
|
+
mutableReferencedNames.add(name);
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
const collectLocal = (name) => {
|
|
1976
|
+
const expression = locals.get(name);
|
|
1977
|
+
if (!expression || visitingLocals.has(name)) {
|
|
1978
|
+
return false;
|
|
1979
|
+
}
|
|
1980
|
+
referencedNames.add(name);
|
|
1981
|
+
markMutable(name, expression);
|
|
1982
|
+
if (visitedLocals.has(name)) {
|
|
1983
|
+
return true;
|
|
1984
|
+
}
|
|
1985
|
+
visitingLocals.add(name);
|
|
1986
|
+
const result = collectExpression(expression);
|
|
1987
|
+
visitingLocals.delete(name);
|
|
1988
|
+
if (result) {
|
|
1989
|
+
visitedLocals.add(name);
|
|
1990
|
+
}
|
|
1991
|
+
return result;
|
|
1992
|
+
};
|
|
1993
|
+
const collectExpression = (expr) => {
|
|
1994
|
+
if (!isSafeStaticExpression(expr, options)) {
|
|
1995
|
+
return false;
|
|
1996
|
+
}
|
|
1997
|
+
const references = new Set();
|
|
1998
|
+
if (!collectStaticExpressionReferences(expr, references, options)) {
|
|
1999
|
+
return false;
|
|
2000
|
+
}
|
|
2001
|
+
for (const reference of references) {
|
|
2002
|
+
referencedNames.add(reference);
|
|
2003
|
+
const importBinding = imports.get(reference);
|
|
2004
|
+
if (importBinding) {
|
|
2005
|
+
collectedImports.set(`${importBinding.source}\0${importBinding.imported}\0${importBinding.local}`, importBinding);
|
|
2006
|
+
mutableReferencedNames.add(reference);
|
|
2007
|
+
continue;
|
|
2008
|
+
}
|
|
2009
|
+
if (!collectLocal(reference)) {
|
|
2010
|
+
return false;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
return true;
|
|
2014
|
+
};
|
|
2015
|
+
if (target.localName) {
|
|
2016
|
+
referencedNames.add(target.localName);
|
|
2017
|
+
markMutable(target.localName, target.expression);
|
|
2018
|
+
}
|
|
2019
|
+
if (!collectExpression(target.expression)) {
|
|
2020
|
+
return null;
|
|
2021
|
+
}
|
|
2022
|
+
const mutationHints = collectTopLevelMutationHints(program);
|
|
2023
|
+
for (const name of referencedNames) {
|
|
2024
|
+
if (mutationHints.mutatedNames.has(name)) {
|
|
2025
|
+
return null;
|
|
2026
|
+
}
|
|
2027
|
+
}
|
|
2028
|
+
for (const name of mutableReferencedNames) {
|
|
2029
|
+
if (mutationHints.callArgumentNames.has(name) &&
|
|
2030
|
+
!options.ignoredMutableCallArgumentNames?.has(name)) {
|
|
2031
|
+
return null;
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
return {
|
|
2035
|
+
imports: [...collectedImports.values()],
|
|
2036
|
+
};
|
|
2037
|
+
};
|
|
2038
|
+
const getExportSpecifierNames = (specifier) => ({
|
|
2039
|
+
exported: moduleExportName(specifier.exported),
|
|
2040
|
+
local: moduleExportName(specifier.local),
|
|
2041
|
+
});
|
|
2042
|
+
const findExportTarget = (program, exportedName) => {
|
|
2043
|
+
const imports = collectImportBindings(program);
|
|
2044
|
+
const locals = collectLocalConstExpressions(program);
|
|
2045
|
+
for (const statement of program.body) {
|
|
2046
|
+
if (statement.type === 'ExportNamedDeclaration') {
|
|
2047
|
+
if (statement.source) {
|
|
2048
|
+
for (const specifier of statement.specifiers) {
|
|
2049
|
+
if (specifier.type !== 'ExportSpecifier') {
|
|
2050
|
+
continue;
|
|
2051
|
+
}
|
|
2052
|
+
const names = getExportSpecifierNames(specifier);
|
|
2053
|
+
if (names.exported === exportedName) {
|
|
2054
|
+
return {
|
|
2055
|
+
imported: names.local,
|
|
2056
|
+
kind: 'import',
|
|
2057
|
+
source: statement.source.value,
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
continue;
|
|
2062
|
+
}
|
|
2063
|
+
if (statement.declaration?.type === 'VariableDeclaration') {
|
|
2064
|
+
for (const declarator of statement.declaration.declarations) {
|
|
2065
|
+
if (declarator.id.type === 'Identifier' &&
|
|
2066
|
+
declarator.id.name === exportedName &&
|
|
2067
|
+
declarator.init) {
|
|
2068
|
+
return {
|
|
2069
|
+
expression: declarator.init,
|
|
2070
|
+
kind: 'expression',
|
|
2071
|
+
localName: declarator.id.name,
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
}
|
|
2075
|
+
continue;
|
|
2076
|
+
}
|
|
2077
|
+
for (const specifier of statement.specifiers) {
|
|
2078
|
+
if (specifier.type !== 'ExportSpecifier') {
|
|
2079
|
+
continue;
|
|
2080
|
+
}
|
|
2081
|
+
const names = getExportSpecifierNames(specifier);
|
|
2082
|
+
if (names.exported !== exportedName) {
|
|
2083
|
+
continue;
|
|
2084
|
+
}
|
|
2085
|
+
const importBinding = imports.get(names.local);
|
|
2086
|
+
if (importBinding) {
|
|
2087
|
+
return {
|
|
2088
|
+
imported: importBinding.imported,
|
|
2089
|
+
kind: 'import',
|
|
2090
|
+
source: importBinding.source,
|
|
2091
|
+
};
|
|
2092
|
+
}
|
|
2093
|
+
const local = locals.get(names.local);
|
|
2094
|
+
if (local) {
|
|
2095
|
+
return {
|
|
2096
|
+
expression: local,
|
|
2097
|
+
kind: 'expression',
|
|
2098
|
+
localName: names.local,
|
|
2099
|
+
};
|
|
2100
|
+
}
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
if (exportedName === 'default' &&
|
|
2104
|
+
statement.type === 'ExportDefaultDeclaration') {
|
|
2105
|
+
const { declaration } = statement;
|
|
2106
|
+
if (declaration.type === 'Identifier') {
|
|
2107
|
+
const importBinding = imports.get(declaration.name);
|
|
2108
|
+
if (importBinding) {
|
|
2109
|
+
return {
|
|
2110
|
+
imported: importBinding.imported,
|
|
2111
|
+
kind: 'import',
|
|
2112
|
+
source: importBinding.source,
|
|
2113
|
+
};
|
|
2114
|
+
}
|
|
2115
|
+
const local = locals.get(declaration.name);
|
|
2116
|
+
if (local) {
|
|
2117
|
+
return {
|
|
2118
|
+
expression: local,
|
|
2119
|
+
kind: 'expression',
|
|
2120
|
+
localName: declaration.name,
|
|
2121
|
+
};
|
|
2122
|
+
}
|
|
2123
|
+
return null;
|
|
2124
|
+
}
|
|
2125
|
+
return {
|
|
2126
|
+
expression: declaration,
|
|
2127
|
+
kind: 'expression',
|
|
2128
|
+
};
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
return null;
|
|
2132
|
+
};
|
|
2133
|
+
const exportedLocalName = (program, exportedName) => {
|
|
2134
|
+
for (const statement of program.body) {
|
|
2135
|
+
if (statement.type === 'ExportNamedDeclaration') {
|
|
2136
|
+
if (statement.source || statement.declaration) {
|
|
2137
|
+
continue;
|
|
2138
|
+
}
|
|
2139
|
+
for (const specifier of statement.specifiers) {
|
|
2140
|
+
if (specifier.type !== 'ExportSpecifier') {
|
|
2141
|
+
continue;
|
|
2142
|
+
}
|
|
2143
|
+
const names = getExportSpecifierNames(specifier);
|
|
2144
|
+
if (names.exported === exportedName) {
|
|
2145
|
+
return names.local;
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
if (exportedName === 'default' &&
|
|
2150
|
+
statement.type === 'ExportDefaultDeclaration' &&
|
|
2151
|
+
statement.declaration.type === 'Identifier') {
|
|
2152
|
+
return statement.declaration.name;
|
|
2153
|
+
}
|
|
2154
|
+
}
|
|
2155
|
+
return null;
|
|
2156
|
+
};
|
|
2157
|
+
const isIdentifierNamed = (node, name) => node.type === 'Identifier' && node.name === name;
|
|
2158
|
+
const enumLiteralValue = (node) => {
|
|
2159
|
+
const unwrapped = unwrapExpression(node);
|
|
2160
|
+
if (unwrapped.type === 'Literal') {
|
|
2161
|
+
const { value } = unwrapped;
|
|
2162
|
+
return typeof value === 'string' || typeof value === 'number'
|
|
2163
|
+
? value
|
|
2164
|
+
: null;
|
|
2165
|
+
}
|
|
2166
|
+
if (unwrapped.type === 'UnaryExpression') {
|
|
2167
|
+
const argument = unwrapExpression(unwrapped.argument);
|
|
2168
|
+
if ((unwrapped.operator === '-' || unwrapped.operator === '+') &&
|
|
2169
|
+
argument.type === 'Literal' &&
|
|
2170
|
+
typeof argument.value === 'number') {
|
|
2171
|
+
return unwrapped.operator === '-' ? -argument.value : argument.value;
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
return null;
|
|
2175
|
+
};
|
|
2176
|
+
const enumMemberKey = (node, computed) => {
|
|
2177
|
+
const unwrapped = unwrapExpression(node);
|
|
2178
|
+
if (!computed && unwrapped.type === 'Identifier') {
|
|
2179
|
+
return unwrapped.name;
|
|
2180
|
+
}
|
|
2181
|
+
const value = enumLiteralValue(unwrapped);
|
|
2182
|
+
return typeof value === 'string' || typeof value === 'number'
|
|
2183
|
+
? String(value)
|
|
2184
|
+
: null;
|
|
2185
|
+
};
|
|
2186
|
+
const enumSimpleAssignment = (node, enumParamName) => {
|
|
2187
|
+
const unwrapped = unwrapExpression(node);
|
|
2188
|
+
if (unwrapped.type !== 'AssignmentExpression' || unwrapped.operator !== '=') {
|
|
2189
|
+
return null;
|
|
2190
|
+
}
|
|
2191
|
+
const left = unwrapExpression(unwrapped.left);
|
|
2192
|
+
if (left.type !== 'MemberExpression' ||
|
|
2193
|
+
!isIdentifierNamed(unwrapExpression(left.object), enumParamName)) {
|
|
2194
|
+
return null;
|
|
2195
|
+
}
|
|
2196
|
+
const key = enumMemberKey(left.property, left.computed);
|
|
2197
|
+
const value = enumLiteralValue(unwrapped.right);
|
|
2198
|
+
return key !== null && value !== null ? { key, value } : null;
|
|
2199
|
+
};
|
|
2200
|
+
const collectEnumIifeAssignments = (call, localName) => {
|
|
2201
|
+
const unwrapped = unwrapExpression(call.type === 'ExpressionStatement' ? call.expression : call);
|
|
2202
|
+
if (unwrapped.type !== 'CallExpression' || unwrapped.arguments.length !== 1) {
|
|
2203
|
+
return null;
|
|
2204
|
+
}
|
|
2205
|
+
const callee = unwrapExpression(unwrapped.callee);
|
|
2206
|
+
if (callee.type !== 'FunctionExpression' ||
|
|
2207
|
+
callee.async ||
|
|
2208
|
+
!callee.body ||
|
|
2209
|
+
callee.params.length !== 1 ||
|
|
2210
|
+
callee.params[0]?.type !== 'Identifier') {
|
|
2211
|
+
return null;
|
|
2212
|
+
}
|
|
2213
|
+
const enumParamName = callee.params[0].name;
|
|
2214
|
+
const argument = unwrapExpression(unwrapped.arguments[0]);
|
|
2215
|
+
if (argument.type !== 'LogicalExpression' || argument.operator !== '||') {
|
|
2216
|
+
return null;
|
|
2217
|
+
}
|
|
2218
|
+
const fallback = unwrapExpression(argument.right);
|
|
2219
|
+
if (!isIdentifierNamed(unwrapExpression(argument.left), localName) ||
|
|
2220
|
+
fallback.type !== 'AssignmentExpression' ||
|
|
2221
|
+
fallback.operator !== '=' ||
|
|
2222
|
+
!isIdentifierNamed(unwrapExpression(fallback.left), localName) ||
|
|
2223
|
+
unwrapExpression(fallback.right).type !== 'ObjectExpression') {
|
|
2224
|
+
return null;
|
|
2225
|
+
}
|
|
2226
|
+
const result = {};
|
|
2227
|
+
for (const statement of callee.body.body) {
|
|
2228
|
+
if (statement.type !== 'ExpressionStatement') {
|
|
2229
|
+
return null;
|
|
2230
|
+
}
|
|
2231
|
+
const expression = unwrapExpression(statement.expression);
|
|
2232
|
+
if (expression.type !== 'AssignmentExpression' ||
|
|
2233
|
+
expression.operator !== '=') {
|
|
2234
|
+
return null;
|
|
2235
|
+
}
|
|
2236
|
+
const left = unwrapExpression(expression.left);
|
|
2237
|
+
if (left.type === 'MemberExpression' &&
|
|
2238
|
+
isIdentifierNamed(unwrapExpression(left.object), enumParamName)) {
|
|
2239
|
+
const numericEnumAssignment = enumSimpleAssignment(left.property, enumParamName);
|
|
2240
|
+
const reverseValue = enumLiteralValue(expression.right);
|
|
2241
|
+
if (numericEnumAssignment &&
|
|
2242
|
+
typeof numericEnumAssignment.value === 'number' &&
|
|
2243
|
+
typeof reverseValue === 'string') {
|
|
2244
|
+
result[numericEnumAssignment.key] = numericEnumAssignment.value;
|
|
2245
|
+
result[String(numericEnumAssignment.value)] = reverseValue;
|
|
2246
|
+
continue;
|
|
2247
|
+
}
|
|
2248
|
+
}
|
|
2249
|
+
const assignment = enumSimpleAssignment(expression, enumParamName);
|
|
2250
|
+
if (!assignment) {
|
|
2251
|
+
return null;
|
|
2252
|
+
}
|
|
2253
|
+
result[assignment.key] = assignment.value;
|
|
2254
|
+
}
|
|
2255
|
+
return Object.keys(result).length > 0 ? result : null;
|
|
2256
|
+
};
|
|
2257
|
+
const enumIifeLocalName = (statement) => {
|
|
2258
|
+
if (statement.type !== 'ExpressionStatement') {
|
|
2259
|
+
return null;
|
|
2260
|
+
}
|
|
2261
|
+
const expression = unwrapExpression(statement.expression);
|
|
2262
|
+
if (expression.type !== 'CallExpression' ||
|
|
2263
|
+
expression.arguments.length !== 1) {
|
|
2264
|
+
return null;
|
|
2265
|
+
}
|
|
2266
|
+
const argument = unwrapExpression(expression.arguments[0]);
|
|
2267
|
+
if (argument.type !== 'LogicalExpression' || argument.operator !== '||') {
|
|
2268
|
+
return null;
|
|
2269
|
+
}
|
|
2270
|
+
const fallback = unwrapExpression(argument.right);
|
|
2271
|
+
if (argument.left.type !== 'Identifier' ||
|
|
2272
|
+
fallback.type !== 'AssignmentExpression' ||
|
|
2273
|
+
fallback.left.type !== 'Identifier') {
|
|
2274
|
+
return null;
|
|
2275
|
+
}
|
|
2276
|
+
return argument.left.name === fallback.left.name ? argument.left.name : null;
|
|
2277
|
+
};
|
|
2278
|
+
const isEnumVarDeclaration = (statement) => statement.type === 'VariableDeclaration' &&
|
|
2279
|
+
statement.kind === 'var' &&
|
|
2280
|
+
statement.declarations.length > 0 &&
|
|
2281
|
+
statement.declarations.every((declarator) => declarator.id.type === 'Identifier' && declarator.init === null);
|
|
2282
|
+
const isTypeScriptEnumOnlyModule = (program) => program.body.every((statement) => {
|
|
2283
|
+
if (isEnumVarDeclaration(statement)) {
|
|
2284
|
+
return true;
|
|
2285
|
+
}
|
|
2286
|
+
const localName = enumIifeLocalName(statement);
|
|
2287
|
+
if (localName) {
|
|
2288
|
+
return collectEnumIifeAssignments(statement, localName) !== null;
|
|
2289
|
+
}
|
|
2290
|
+
if (statement.type === 'ExportDefaultDeclaration') {
|
|
2291
|
+
return statement.declaration.type === 'Identifier';
|
|
2292
|
+
}
|
|
2293
|
+
return (statement.type === 'ExportNamedDeclaration' &&
|
|
2294
|
+
!statement.source &&
|
|
2295
|
+
!statement.declaration &&
|
|
2296
|
+
statement.specifiers.every((specifier) => specifier.type === 'ExportSpecifier'));
|
|
2297
|
+
});
|
|
2298
|
+
const typeScriptEnumStaticExportValue = (program, exportedName) => {
|
|
2299
|
+
if (!isTypeScriptEnumOnlyModule(program)) {
|
|
2300
|
+
return null;
|
|
2301
|
+
}
|
|
2302
|
+
const localName = exportedLocalName(program, exportedName);
|
|
2303
|
+
if (!localName) {
|
|
2304
|
+
return null;
|
|
2305
|
+
}
|
|
2306
|
+
const hasDeclaration = program.body.some((statement) => isEnumVarDeclaration(statement) &&
|
|
2307
|
+
statement.declarations.some((declarator) => declarator.id.type === 'Identifier' &&
|
|
2308
|
+
declarator.id.name === localName));
|
|
2309
|
+
if (!hasDeclaration) {
|
|
2310
|
+
return null;
|
|
2311
|
+
}
|
|
2312
|
+
for (const statement of program.body) {
|
|
2313
|
+
const enumValue = collectEnumIifeAssignments(statement, localName);
|
|
2314
|
+
if (enumValue) {
|
|
2315
|
+
return enumValue;
|
|
2316
|
+
}
|
|
2317
|
+
}
|
|
2318
|
+
return null;
|
|
2319
|
+
};
|
|
2320
|
+
function* resolveDependency(action, importer, source, imported) {
|
|
2321
|
+
const entrypoint = importer === action.entrypoint.name
|
|
2322
|
+
? action.entrypoint
|
|
2323
|
+
: Entrypoint.createRoot(action.services, importer, [imported], undefined);
|
|
2324
|
+
const imports = new Map([[source, [imported]]]);
|
|
2325
|
+
const [resolved] = yield* action.getNext('resolveImports', entrypoint, {
|
|
2326
|
+
imports,
|
|
2327
|
+
phase: 'initial',
|
|
2328
|
+
});
|
|
2329
|
+
return resolved ?? null;
|
|
2330
|
+
}
|
|
2331
|
+
function* resolveImportValue(action, importer, binding, stack, memo) {
|
|
2332
|
+
const dependency = yield* resolveDependency(action, importer, binding.source, binding.imported);
|
|
2333
|
+
if (!dependency?.resolved) {
|
|
2334
|
+
debugStaticResolve(action, {
|
|
2335
|
+
filename: importer,
|
|
2336
|
+
imported: binding.imported,
|
|
2337
|
+
phase: 'import',
|
|
2338
|
+
reason: 'dependency-unresolved',
|
|
2339
|
+
source: binding.source,
|
|
2340
|
+
status: 'rejected',
|
|
2341
|
+
});
|
|
2342
|
+
return null;
|
|
2343
|
+
}
|
|
2344
|
+
const resolved = yield* resolveStaticExport(action, dependency.resolved, binding.imported, stack, memo);
|
|
2345
|
+
if (!resolved) {
|
|
2346
|
+
debugStaticResolve(action, {
|
|
2347
|
+
dependency: dependency.resolved,
|
|
2348
|
+
filename: importer,
|
|
2349
|
+
imported: binding.imported,
|
|
2350
|
+
phase: 'import',
|
|
2351
|
+
reason: 'resolve-failed',
|
|
2352
|
+
source: binding.source,
|
|
2353
|
+
status: 'rejected',
|
|
2354
|
+
});
|
|
2355
|
+
return null;
|
|
2356
|
+
}
|
|
2357
|
+
debugStaticResolve(action, {
|
|
2358
|
+
dependency: dependency.resolved,
|
|
2359
|
+
filename: importer,
|
|
2360
|
+
imported: binding.imported,
|
|
2361
|
+
phase: 'import',
|
|
2362
|
+
source: binding.source,
|
|
2363
|
+
status: 'resolved',
|
|
2364
|
+
});
|
|
2365
|
+
return {
|
|
2366
|
+
callable: resolved.callable,
|
|
2367
|
+
dependencies: [
|
|
2368
|
+
dependency.resolved,
|
|
2369
|
+
...resolved.dependencies.filter((item) => item !== dependency.resolved),
|
|
2370
|
+
],
|
|
2371
|
+
sideEffectDependencies: resolved.sideEffectDependencies,
|
|
2372
|
+
value: resolved.value,
|
|
2373
|
+
};
|
|
2374
|
+
}
|
|
2375
|
+
function* resolveExportAsOpaqueRuntimeImport(action, filename, exportedName, stack, memo) {
|
|
2376
|
+
const memoKey = `${filename}\0${exportedName}`;
|
|
2377
|
+
if (memo.has(memoKey)) {
|
|
2378
|
+
return memo.get(memoKey) ?? null;
|
|
2379
|
+
}
|
|
2380
|
+
if (stack.has(memoKey)) {
|
|
2381
|
+
memo.set(memoKey, null);
|
|
2382
|
+
return null;
|
|
2383
|
+
}
|
|
2384
|
+
stack.add(memoKey);
|
|
2385
|
+
const loadedAndParsed = action.services.loadAndParseFn(action.services, filename, undefined, action.services.log);
|
|
2386
|
+
if (loadedAndParsed.evaluator === 'ignored' ||
|
|
2387
|
+
loadedAndParsed.evaluator !== oxcShaker) {
|
|
2388
|
+
memo.set(memoKey, null);
|
|
2389
|
+
stack.delete(memoKey);
|
|
2390
|
+
return null;
|
|
2391
|
+
}
|
|
2392
|
+
const program = parseProgram(loadedAndParsed.code, filename);
|
|
2393
|
+
const target = findExportTarget(program, exportedName);
|
|
2394
|
+
if (!target) {
|
|
2395
|
+
memo.set(memoKey, null);
|
|
2396
|
+
stack.delete(memoKey);
|
|
2397
|
+
return null;
|
|
2398
|
+
}
|
|
2399
|
+
if (target.kind === 'import') {
|
|
2400
|
+
const resolved = yield* resolveImportAsOpaqueRuntime(action, filename, target, stack, memo);
|
|
2401
|
+
memo.set(memoKey, resolved);
|
|
2402
|
+
stack.delete(memoKey);
|
|
2403
|
+
return resolved;
|
|
2404
|
+
}
|
|
2405
|
+
if (isOpaqueRuntimeComponentExpression(program, target.expression)) {
|
|
2406
|
+
const resolved = {
|
|
2407
|
+
dependencies: [filename],
|
|
2408
|
+
names: new Set(),
|
|
2409
|
+
};
|
|
2410
|
+
memo.set(memoKey, resolved);
|
|
2411
|
+
stack.delete(memoKey);
|
|
2412
|
+
return resolved;
|
|
2413
|
+
}
|
|
2414
|
+
const imports = collectImportBindings(program, { includeNamespace: true });
|
|
2415
|
+
const referencedNames = new Set();
|
|
2416
|
+
collectOpaqueRuntimeReferenceNames(program, target.expression, referencedNames);
|
|
2417
|
+
const opaqueImportNames = new Set();
|
|
2418
|
+
const dependencies = new Set([filename]);
|
|
2419
|
+
for (const name of referencedNames) {
|
|
2420
|
+
const binding = imports.get(name);
|
|
2421
|
+
if (!binding ||
|
|
2422
|
+
binding.source === 'react' ||
|
|
2423
|
+
isKnownOpaqueRuntimeWrapperImport(binding)) {
|
|
2424
|
+
continue;
|
|
2425
|
+
}
|
|
2426
|
+
const proof = yield* resolveImportAsOpaqueRuntime(action, filename, binding, stack, memo);
|
|
2427
|
+
if (!proof) {
|
|
2428
|
+
continue;
|
|
2429
|
+
}
|
|
2430
|
+
opaqueImportNames.add(name);
|
|
2431
|
+
proof.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
2432
|
+
}
|
|
2433
|
+
const resolved = isOpaqueRuntimeComponentExpression(program, target.expression, opaqueImportNames)
|
|
2434
|
+
? {
|
|
2435
|
+
dependencies: [...dependencies],
|
|
2436
|
+
names: opaqueImportNames,
|
|
2437
|
+
}
|
|
2438
|
+
: null;
|
|
2439
|
+
memo.set(memoKey, resolved);
|
|
2440
|
+
stack.delete(memoKey);
|
|
2441
|
+
return resolved;
|
|
2442
|
+
}
|
|
2443
|
+
const knownOpaqueRuntimeSourceDependency = (importer, source) => {
|
|
2444
|
+
if (!isKnownOpaqueRuntimeImportSource(source)) {
|
|
2445
|
+
return null;
|
|
2446
|
+
}
|
|
2447
|
+
const request = stripQueryAndHash(source);
|
|
2448
|
+
if (isAbsolute(request)) {
|
|
2449
|
+
return request;
|
|
2450
|
+
}
|
|
2451
|
+
return request.startsWith('.')
|
|
2452
|
+
? resolvePath(dirname(importer), request)
|
|
2453
|
+
: null;
|
|
2454
|
+
};
|
|
2455
|
+
function* resolveImportAsOpaqueRuntime(action, importer, binding, stack, memo) {
|
|
2456
|
+
const knownSourceDependency = knownOpaqueRuntimeSourceDependency(importer, binding.source);
|
|
2457
|
+
if (knownSourceDependency) {
|
|
2458
|
+
return {
|
|
2459
|
+
dependencies: [knownSourceDependency],
|
|
2460
|
+
names: new Set(),
|
|
2461
|
+
};
|
|
2462
|
+
}
|
|
2463
|
+
if (isKnownExternalRuntimeComponentImportSource(binding.source)) {
|
|
2464
|
+
return {
|
|
2465
|
+
dependencies: [],
|
|
2466
|
+
names: new Set(),
|
|
2467
|
+
};
|
|
2468
|
+
}
|
|
2469
|
+
const dependency = yield* resolveDependency(action, importer, binding.source, binding.imported);
|
|
2470
|
+
if (!dependency?.resolved) {
|
|
2471
|
+
return null;
|
|
2472
|
+
}
|
|
2473
|
+
if (isKnownOpaqueRuntimeImportSource(binding.source) ||
|
|
2474
|
+
isKnownOpaqueRuntimeImportSource(dependency.resolved)) {
|
|
2475
|
+
return {
|
|
2476
|
+
dependencies: [dependency.resolved],
|
|
2477
|
+
names: new Set(),
|
|
2478
|
+
};
|
|
2479
|
+
}
|
|
2480
|
+
const resolved = yield* resolveExportAsOpaqueRuntimeImport(action, dependency.resolved, binding.imported, stack, memo);
|
|
2481
|
+
return resolved
|
|
2482
|
+
? {
|
|
2483
|
+
dependencies: [
|
|
2484
|
+
dependency.resolved,
|
|
2485
|
+
...resolved.dependencies.filter((item) => item !== dependency.resolved),
|
|
2486
|
+
],
|
|
2487
|
+
names: resolved.names,
|
|
2488
|
+
}
|
|
2489
|
+
: null;
|
|
2490
|
+
}
|
|
2491
|
+
function* collectOpaqueRuntimeImportProof(action, filename, program, expression) {
|
|
2492
|
+
const extendsExpressions = collectWYWMetaExtendsExpressions(expression);
|
|
2493
|
+
if (extendsExpressions.length === 0) {
|
|
2494
|
+
return {
|
|
2495
|
+
dependencies: [],
|
|
2496
|
+
names: new Set(),
|
|
2497
|
+
};
|
|
2498
|
+
}
|
|
2499
|
+
const imports = collectImportBindings(program, { includeNamespace: true });
|
|
2500
|
+
const referencedNames = new Set();
|
|
2501
|
+
extendsExpressions.forEach((extendsExpression) => collectOpaqueRuntimeReferenceNames(program, extendsExpression, referencedNames));
|
|
2502
|
+
const dependencies = new Set();
|
|
2503
|
+
const names = new Set();
|
|
2504
|
+
const memo = new Map();
|
|
2505
|
+
for (const name of referencedNames) {
|
|
2506
|
+
const binding = imports.get(name);
|
|
2507
|
+
if (!binding || binding.source === 'react') {
|
|
2508
|
+
continue;
|
|
2509
|
+
}
|
|
2510
|
+
const proof = yield* resolveImportAsOpaqueRuntime(action, filename, binding, new Set(), memo);
|
|
2511
|
+
if (!proof) {
|
|
2512
|
+
continue;
|
|
2513
|
+
}
|
|
2514
|
+
names.add(name);
|
|
2515
|
+
proof.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
2516
|
+
}
|
|
2517
|
+
return {
|
|
2518
|
+
dependencies: [...dependencies],
|
|
2519
|
+
names,
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
function* resolveProcessorStaticExport(action, filename, code, codeHash, program, exportedName, stack, memo) {
|
|
2523
|
+
const root = action.services.options.root ?? process.cwd();
|
|
2524
|
+
if (!isLocalStaticMetadataFile(filename, root)) {
|
|
2525
|
+
debugStaticResolve(action, {
|
|
2526
|
+
exported: exportedName,
|
|
2527
|
+
filename,
|
|
2528
|
+
phase: 'processor-metadata',
|
|
2529
|
+
reason: 'outside-root',
|
|
2530
|
+
status: 'rejected',
|
|
2531
|
+
});
|
|
2532
|
+
return null;
|
|
2533
|
+
}
|
|
2534
|
+
if (collectProcessorImportLocals(action, program, code, filename).size === 0) {
|
|
2535
|
+
debugStaticResolve(action, {
|
|
2536
|
+
exported: exportedName,
|
|
2537
|
+
filename,
|
|
2538
|
+
phase: 'processor-metadata',
|
|
2539
|
+
reason: 'no-processor-imports',
|
|
2540
|
+
status: 'rejected',
|
|
2541
|
+
});
|
|
2542
|
+
return null;
|
|
2543
|
+
}
|
|
2544
|
+
const preevalResult = getStaticMetadataPreevalResult(action, filename, code, codeHash);
|
|
2545
|
+
if (!preevalResult) {
|
|
2546
|
+
debugStaticResolve(action, {
|
|
2547
|
+
exported: exportedName,
|
|
2548
|
+
filename,
|
|
2549
|
+
phase: 'processor-metadata',
|
|
2550
|
+
reason: 'metadata-preeval-failed',
|
|
2551
|
+
status: 'rejected',
|
|
2552
|
+
});
|
|
2553
|
+
return null;
|
|
2554
|
+
}
|
|
2555
|
+
if (!preevalResult.metadata) {
|
|
2556
|
+
debugStaticResolve(action, {
|
|
2557
|
+
exported: exportedName,
|
|
2558
|
+
filename,
|
|
2559
|
+
phase: 'processor-metadata',
|
|
2560
|
+
reason: 'metadata-missing',
|
|
2561
|
+
status: 'rejected',
|
|
2562
|
+
});
|
|
2563
|
+
return null;
|
|
2564
|
+
}
|
|
2565
|
+
const preevalCode = preevalResult.baseCode;
|
|
2566
|
+
const preevalProgram = parseProgram(preevalCode, filename);
|
|
2567
|
+
const target = findExportTarget(preevalProgram, exportedName);
|
|
2568
|
+
if (!target || target.kind === 'import') {
|
|
2569
|
+
debugStaticResolve(action, {
|
|
2570
|
+
exported: exportedName,
|
|
2571
|
+
filename,
|
|
2572
|
+
phase: 'processor-metadata',
|
|
2573
|
+
reason: 'processor-target-missing',
|
|
2574
|
+
status: 'rejected',
|
|
2575
|
+
});
|
|
2576
|
+
return null;
|
|
2577
|
+
}
|
|
2578
|
+
const processorObjectAssignAliases = objectAssignAliasExpressionsForTarget(preevalProgram, target);
|
|
2579
|
+
const processorExpression = resolveObjectAssignProcessorExpression(preevalProgram, target.expression);
|
|
2580
|
+
const opaqueRuntimeImportProof = yield* collectOpaqueRuntimeImportProof(action, filename, preevalProgram, processorExpression);
|
|
2581
|
+
const preparedTarget = prepareProcessorTarget(preevalCode, filename, preevalProgram, target, opaqueRuntimeImportProof.names);
|
|
2582
|
+
if (!preparedTarget) {
|
|
2583
|
+
debugStaticResolve(action, {
|
|
2584
|
+
exported: exportedName,
|
|
2585
|
+
filename,
|
|
2586
|
+
phase: 'processor-metadata',
|
|
2587
|
+
reason: 'unsupported-processor-expression',
|
|
2588
|
+
status: 'rejected',
|
|
2589
|
+
});
|
|
2590
|
+
return null;
|
|
2591
|
+
}
|
|
2592
|
+
const env = new Map();
|
|
2593
|
+
const dependencies = new Set([filename]);
|
|
2594
|
+
const sideEffectDependencies = new Set();
|
|
2595
|
+
opaqueRuntimeImportProof.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
2596
|
+
for (const binding of preparedTarget.dependencies.imports) {
|
|
2597
|
+
const resolved = yield* resolveImportValue(action, filename, binding, stack, memo);
|
|
2598
|
+
if (!resolved) {
|
|
2599
|
+
debugStaticResolve(action, {
|
|
2600
|
+
exported: exportedName,
|
|
2601
|
+
filename,
|
|
2602
|
+
imported: binding.imported,
|
|
2603
|
+
phase: 'processor-metadata',
|
|
2604
|
+
reason: 'resolve-failed',
|
|
2605
|
+
source: binding.source,
|
|
2606
|
+
status: 'rejected',
|
|
2607
|
+
});
|
|
2608
|
+
return null;
|
|
2609
|
+
}
|
|
2610
|
+
if (!bindStaticResolvedValue(env, preparedTarget.expression, binding.local, resolved, {
|
|
2611
|
+
wrapNonCallable: true,
|
|
2612
|
+
})) {
|
|
2613
|
+
debugStaticResolve(action, {
|
|
2614
|
+
exported: exportedName,
|
|
2615
|
+
filename,
|
|
2616
|
+
imported: binding.imported,
|
|
2617
|
+
phase: 'processor-metadata',
|
|
2618
|
+
reason: 'callable-usage-unsupported',
|
|
2619
|
+
source: binding.source,
|
|
2620
|
+
status: 'rejected',
|
|
2621
|
+
});
|
|
2622
|
+
return null;
|
|
2623
|
+
}
|
|
2624
|
+
resolved.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
2625
|
+
resolved.sideEffectDependencies?.forEach((dependency) => sideEffectDependencies.add(dependency));
|
|
2626
|
+
}
|
|
2627
|
+
const value = preparedTarget.evaluationCode && preparedTarget.evaluationSpan
|
|
2628
|
+
? evaluateOxcStaticExpressionAt(preparedTarget.evaluationCode, filename, preparedTarget.evaluationSpan, env)
|
|
2629
|
+
: evaluateOxcStaticExpressionAt(preevalCode, filename, {
|
|
2630
|
+
end: preparedTarget.expression.end,
|
|
2631
|
+
start: preparedTarget.expression.start,
|
|
2632
|
+
}, env);
|
|
2633
|
+
if (!isOxcStaticSerializableValue(value)) {
|
|
2634
|
+
debugStaticResolve(action, {
|
|
2635
|
+
exported: exportedName,
|
|
2636
|
+
filename,
|
|
2637
|
+
phase: 'processor-metadata',
|
|
2638
|
+
reason: 'non-serializable',
|
|
2639
|
+
status: 'rejected',
|
|
2640
|
+
});
|
|
2641
|
+
return null;
|
|
2642
|
+
}
|
|
2643
|
+
let resolvedValue = value;
|
|
2644
|
+
if (processorObjectAssignAliases && isStaticWYWMetaValue(value)) {
|
|
2645
|
+
const aliasValues = yield* resolveObjectAssignAliasValues(action, filename, preevalCode, preevalProgram, processorObjectAssignAliases, stack, memo);
|
|
2646
|
+
const mergedValue = aliasValues
|
|
2647
|
+
? mergeStaticObjectAssignAliases(value, aliasValues.values)
|
|
2648
|
+
: null;
|
|
2649
|
+
if (mergedValue) {
|
|
2650
|
+
resolvedValue = mergedValue;
|
|
2651
|
+
aliasValues?.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
2652
|
+
aliasValues?.sideEffectDependencies.forEach((dependency) => sideEffectDependencies.add(dependency));
|
|
2653
|
+
}
|
|
2654
|
+
}
|
|
2655
|
+
const isStaticMeta = isStaticWYWMetaValue(resolvedValue);
|
|
2656
|
+
const isStaticMetaTree = !isStaticMeta && isStaticWYWMetaTreeValue(resolvedValue);
|
|
2657
|
+
const processors = preevalResult.metadata
|
|
2658
|
+
.processors;
|
|
2659
|
+
const isSelectorOnly = !isStaticMeta &&
|
|
2660
|
+
!isStaticMetaTree &&
|
|
2661
|
+
isSelectorOnlyProcessorValue(resolvedValue, processors, new Map());
|
|
2662
|
+
const isSideEffectClassValue = !isStaticMeta &&
|
|
2663
|
+
!isStaticMetaTree &&
|
|
2664
|
+
!isSelectorOnly &&
|
|
2665
|
+
isProcessorClassValue(resolvedValue, processors, new Map());
|
|
2666
|
+
if (!isStaticMeta &&
|
|
2667
|
+
!isStaticMetaTree &&
|
|
2668
|
+
!isSelectorOnly &&
|
|
2669
|
+
!isSideEffectClassValue) {
|
|
2670
|
+
debugStaticResolve(action, {
|
|
2671
|
+
exported: exportedName,
|
|
2672
|
+
filename,
|
|
2673
|
+
phase: 'processor-metadata',
|
|
2674
|
+
reason: 'non-empty-css-artifact',
|
|
2675
|
+
status: 'rejected',
|
|
2676
|
+
});
|
|
2677
|
+
return null;
|
|
2678
|
+
}
|
|
2679
|
+
let resolvedReason;
|
|
2680
|
+
if (preparedTarget.opaqueRuntimeBase) {
|
|
2681
|
+
resolvedReason = 'opaque-runtime-component';
|
|
2682
|
+
}
|
|
2683
|
+
else if (isSideEffectClassValue) {
|
|
2684
|
+
resolvedReason = 'non-empty-css-artifact-side-effect';
|
|
2685
|
+
}
|
|
2686
|
+
debugStaticResolve(action, {
|
|
2687
|
+
exported: exportedName,
|
|
2688
|
+
filename,
|
|
2689
|
+
phase: 'processor-metadata',
|
|
2690
|
+
reason: resolvedReason,
|
|
2691
|
+
status: 'resolved',
|
|
2692
|
+
});
|
|
2693
|
+
return {
|
|
2694
|
+
dependencies: [...dependencies],
|
|
2695
|
+
sideEffectDependencies: isSideEffectClassValue
|
|
2696
|
+
? [filename, ...sideEffectDependencies]
|
|
2697
|
+
: [...sideEffectDependencies],
|
|
2698
|
+
value: resolvedValue,
|
|
2699
|
+
};
|
|
2700
|
+
}
|
|
2701
|
+
function* resolveObjectAssignStaticExport(action, filename, code, program, target, stack, memo) {
|
|
2702
|
+
const objectAssignAliases = objectAssignAliasExpressionsForTarget(program, target);
|
|
2703
|
+
const objectAssignTarget = objectAssignTargetExpression(program, target.expression);
|
|
2704
|
+
if (!objectAssignTarget) {
|
|
2705
|
+
return null;
|
|
2706
|
+
}
|
|
2707
|
+
const imports = collectImportBindings(program);
|
|
2708
|
+
if (objectAssignTarget.type === 'Identifier') {
|
|
2709
|
+
const importBinding = imports.get(objectAssignTarget.name);
|
|
2710
|
+
if (importBinding) {
|
|
2711
|
+
const resolved = yield* resolveImportValue(action, filename, importBinding, stack, memo);
|
|
2712
|
+
if (!resolved || !isStaticWYWMetaValue(resolved.value)) {
|
|
2713
|
+
return null;
|
|
2714
|
+
}
|
|
2715
|
+
const dependencies = new Set([
|
|
2716
|
+
filename,
|
|
2717
|
+
...resolved.dependencies.filter((item) => item !== filename),
|
|
2718
|
+
]);
|
|
2719
|
+
const sideEffectDependencies = new Set(resolved.sideEffectDependencies ?? []);
|
|
2720
|
+
const aliasValues = objectAssignAliases
|
|
2721
|
+
? yield* resolveObjectAssignAliasValues(action, filename, code, program, objectAssignAliases, stack, memo)
|
|
2722
|
+
: null;
|
|
2723
|
+
const mergedValue = aliasValues
|
|
2724
|
+
? mergeStaticObjectAssignAliases(resolved.value, aliasValues.values)
|
|
2725
|
+
: null;
|
|
2726
|
+
aliasValues?.dependencies.forEach((item) => dependencies.add(item));
|
|
2727
|
+
aliasValues?.sideEffectDependencies.forEach((item) => sideEffectDependencies.add(item));
|
|
2728
|
+
return {
|
|
2729
|
+
dependencies: [...dependencies],
|
|
2730
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
2731
|
+
value: mergedValue ?? resolved.value,
|
|
2732
|
+
};
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
const expression = objectAssignTarget.type === 'Identifier'
|
|
2736
|
+
? findTopLevelConstExpression(program, objectAssignTarget.name) ??
|
|
2737
|
+
objectAssignTarget
|
|
2738
|
+
: objectAssignTarget;
|
|
2739
|
+
const staticDependencies = collectStaticExpressionDependencies(program, {
|
|
2740
|
+
...target,
|
|
2741
|
+
expression,
|
|
2742
|
+
});
|
|
2743
|
+
if (!staticDependencies) {
|
|
2744
|
+
return null;
|
|
2745
|
+
}
|
|
2746
|
+
const env = new Map();
|
|
2747
|
+
const dependencies = new Set([filename]);
|
|
2748
|
+
const sideEffectDependencies = new Set();
|
|
2749
|
+
for (const binding of staticDependencies.imports) {
|
|
2750
|
+
const resolved = yield* resolveImportValue(action, filename, binding, stack, memo);
|
|
2751
|
+
if (!resolved) {
|
|
2752
|
+
return null;
|
|
2753
|
+
}
|
|
2754
|
+
if (!bindStaticResolvedValue(env, expression, binding.local, resolved)) {
|
|
2755
|
+
return null;
|
|
2756
|
+
}
|
|
2757
|
+
resolved.dependencies.forEach((item) => dependencies.add(item));
|
|
2758
|
+
resolved.sideEffectDependencies?.forEach((item) => sideEffectDependencies.add(item));
|
|
2759
|
+
}
|
|
2760
|
+
const value = evaluateOxcStaticExpressionAt(code, filename, {
|
|
2761
|
+
end: expression.end,
|
|
2762
|
+
start: expression.start,
|
|
2763
|
+
}, env);
|
|
2764
|
+
if (!isStaticWYWMetaValue(value)) {
|
|
2765
|
+
return null;
|
|
2766
|
+
}
|
|
2767
|
+
const aliasValues = objectAssignAliases
|
|
2768
|
+
? yield* resolveObjectAssignAliasValues(action, filename, code, program, objectAssignAliases, stack, memo)
|
|
2769
|
+
: null;
|
|
2770
|
+
const mergedValue = aliasValues
|
|
2771
|
+
? mergeStaticObjectAssignAliases(value, aliasValues.values)
|
|
2772
|
+
: null;
|
|
2773
|
+
aliasValues?.dependencies.forEach((item) => dependencies.add(item));
|
|
2774
|
+
aliasValues?.sideEffectDependencies.forEach((item) => sideEffectDependencies.add(item));
|
|
2775
|
+
return {
|
|
2776
|
+
dependencies: [...dependencies],
|
|
2777
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
2778
|
+
value: mergedValue ?? value,
|
|
2779
|
+
};
|
|
2780
|
+
}
|
|
2781
|
+
const zeroArgFunctionReturnExpression = (expression) => {
|
|
2782
|
+
const unwrapped = unwrapExpression(expression);
|
|
2783
|
+
if (unwrapped.type !== 'ArrowFunctionExpression' &&
|
|
2784
|
+
unwrapped.type !== 'FunctionExpression') {
|
|
2785
|
+
return null;
|
|
2786
|
+
}
|
|
2787
|
+
if (unwrapped.async || unwrapped.params.length !== 0 || !unwrapped.body) {
|
|
2788
|
+
return null;
|
|
2789
|
+
}
|
|
2790
|
+
if (unwrapped.body.type !== 'BlockStatement') {
|
|
2791
|
+
return unwrapped.body;
|
|
2792
|
+
}
|
|
2793
|
+
if (unwrapped.body.body.length !== 1) {
|
|
2794
|
+
return null;
|
|
2795
|
+
}
|
|
2796
|
+
const [statement] = unwrapped.body.body;
|
|
2797
|
+
return statement?.type === 'ReturnStatement' && statement.argument
|
|
2798
|
+
? statement.argument
|
|
2799
|
+
: null;
|
|
2800
|
+
};
|
|
2801
|
+
function* resolveZeroArgFunctionStaticExport(action, filename, code, program, target, stack, memo) {
|
|
2802
|
+
const returnExpression = zeroArgFunctionReturnExpression(target.expression);
|
|
2803
|
+
if (!returnExpression) {
|
|
2804
|
+
return null;
|
|
2805
|
+
}
|
|
2806
|
+
const staticDependencies = collectStaticExpressionDependencies(program, {
|
|
2807
|
+
...target,
|
|
2808
|
+
expression: returnExpression,
|
|
2809
|
+
}, { allowMetadataCalls: true });
|
|
2810
|
+
if (!staticDependencies) {
|
|
2811
|
+
return null;
|
|
2812
|
+
}
|
|
2813
|
+
const env = new Map();
|
|
2814
|
+
const dependencies = new Set([filename]);
|
|
2815
|
+
const sideEffectDependencies = new Set();
|
|
2816
|
+
for (const binding of staticDependencies.imports) {
|
|
2817
|
+
const resolved = yield* resolveImportValue(action, filename, binding, stack, memo);
|
|
2818
|
+
if (!resolved) {
|
|
2819
|
+
return null;
|
|
2820
|
+
}
|
|
2821
|
+
if (!bindStaticResolvedValue(env, returnExpression, binding.local, resolved)) {
|
|
2822
|
+
return null;
|
|
2823
|
+
}
|
|
2824
|
+
resolved.dependencies.forEach((item) => dependencies.add(item));
|
|
2825
|
+
resolved.sideEffectDependencies?.forEach((item) => sideEffectDependencies.add(item));
|
|
2826
|
+
}
|
|
2827
|
+
const value = evaluateOxcStaticExpressionAt(code, filename, {
|
|
2828
|
+
end: returnExpression.end,
|
|
2829
|
+
start: returnExpression.start,
|
|
2830
|
+
}, env);
|
|
2831
|
+
return isOxcStaticSerializableValue(value)
|
|
2832
|
+
? {
|
|
2833
|
+
callable: 'zero-arg',
|
|
2834
|
+
dependencies: [...dependencies],
|
|
2835
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
2836
|
+
value,
|
|
2837
|
+
}
|
|
2838
|
+
: null;
|
|
2839
|
+
}
|
|
2840
|
+
function* resolveStaticExport(action, filename, exportedName, stack, memo) {
|
|
2841
|
+
const memoKey = `${filename}\0${exportedName}`;
|
|
2842
|
+
if (memo.has(memoKey)) {
|
|
2843
|
+
return memo.get(memoKey) ?? null;
|
|
2844
|
+
}
|
|
2845
|
+
if (stack.has(memoKey)) {
|
|
2846
|
+
memo.set(memoKey, null);
|
|
2847
|
+
debugStaticResolve(action, {
|
|
2848
|
+
exported: exportedName,
|
|
2849
|
+
filename,
|
|
2850
|
+
phase: 'export',
|
|
2851
|
+
reason: 'cyclic-export',
|
|
2852
|
+
status: 'rejected',
|
|
2853
|
+
});
|
|
2854
|
+
return null;
|
|
2855
|
+
}
|
|
2856
|
+
stack.add(memoKey);
|
|
2857
|
+
const analysis = getStaticFileAnalysis(action, filename);
|
|
2858
|
+
if (!analysis) {
|
|
2859
|
+
memo.set(memoKey, null);
|
|
2860
|
+
stack.delete(memoKey);
|
|
2861
|
+
debugStaticResolve(action, {
|
|
2862
|
+
exported: exportedName,
|
|
2863
|
+
filename,
|
|
2864
|
+
phase: 'export',
|
|
2865
|
+
reason: 'ignored-or-non-oxc',
|
|
2866
|
+
status: 'rejected',
|
|
2867
|
+
});
|
|
2868
|
+
return null;
|
|
2869
|
+
}
|
|
2870
|
+
const { code, codeHash, program } = analysis;
|
|
2871
|
+
const finish = (result) => {
|
|
2872
|
+
memo.set(memoKey, result);
|
|
2873
|
+
stack.delete(memoKey);
|
|
2874
|
+
setStaticExportCachedResult(action, filename, exportedName, codeHash, result);
|
|
2875
|
+
return result;
|
|
2876
|
+
};
|
|
2877
|
+
const cachedResult = getStaticExportCachedResult(action, filename, exportedName, codeHash);
|
|
2878
|
+
if (cachedResult !== undefined) {
|
|
2879
|
+
memo.set(memoKey, cachedResult);
|
|
2880
|
+
stack.delete(memoKey);
|
|
2881
|
+
return cachedResult;
|
|
2882
|
+
}
|
|
2883
|
+
const enumValue = typeScriptEnumStaticExportValue(program, exportedName);
|
|
2884
|
+
if (enumValue) {
|
|
2885
|
+
debugStaticResolve(action, {
|
|
2886
|
+
exported: exportedName,
|
|
2887
|
+
filename,
|
|
2888
|
+
phase: 'export',
|
|
2889
|
+
reason: 'typescript-enum',
|
|
2890
|
+
status: 'resolved',
|
|
2891
|
+
});
|
|
2892
|
+
return finish({
|
|
2893
|
+
dependencies: [filename],
|
|
2894
|
+
value: enumValue,
|
|
2895
|
+
});
|
|
2896
|
+
}
|
|
2897
|
+
const target = findExportTarget(program, exportedName);
|
|
2898
|
+
if (!target) {
|
|
2899
|
+
debugStaticResolve(action, {
|
|
2900
|
+
exported: exportedName,
|
|
2901
|
+
filename,
|
|
2902
|
+
phase: 'export',
|
|
2903
|
+
reason: 'no-export-target',
|
|
2904
|
+
status: 'rejected',
|
|
2905
|
+
});
|
|
2906
|
+
return finish(null);
|
|
2907
|
+
}
|
|
2908
|
+
if (target.kind === 'import') {
|
|
2909
|
+
const resolved = yield* resolveImportValue(action, filename, target, stack, memo);
|
|
2910
|
+
debugStaticResolve(action, {
|
|
2911
|
+
exported: exportedName,
|
|
2912
|
+
filename,
|
|
2913
|
+
imported: target.imported,
|
|
2914
|
+
phase: 'export',
|
|
2915
|
+
reason: resolved ? undefined : 'resolve-failed',
|
|
2916
|
+
source: target.source,
|
|
2917
|
+
status: resolved ? 'resolved' : 'rejected',
|
|
2918
|
+
});
|
|
2919
|
+
return finish(resolved);
|
|
2920
|
+
}
|
|
2921
|
+
const objectAssignResult = yield* resolveObjectAssignStaticExport(action, filename, code, program, target, stack, memo);
|
|
2922
|
+
if (objectAssignResult) {
|
|
2923
|
+
debugStaticResolve(action, {
|
|
2924
|
+
exported: exportedName,
|
|
2925
|
+
filename,
|
|
2926
|
+
phase: 'export',
|
|
2927
|
+
reason: 'object-assign',
|
|
2928
|
+
status: 'resolved',
|
|
2929
|
+
});
|
|
2930
|
+
return finish(objectAssignResult);
|
|
2931
|
+
}
|
|
2932
|
+
const zeroArgFunctionResult = yield* resolveZeroArgFunctionStaticExport(action, filename, code, program, target, stack, memo);
|
|
2933
|
+
if (zeroArgFunctionResult) {
|
|
2934
|
+
debugStaticResolve(action, {
|
|
2935
|
+
exported: exportedName,
|
|
2936
|
+
filename,
|
|
2937
|
+
phase: 'export',
|
|
2938
|
+
reason: 'zero-arg-function',
|
|
2939
|
+
status: 'resolved',
|
|
2940
|
+
});
|
|
2941
|
+
return finish(zeroArgFunctionResult);
|
|
2942
|
+
}
|
|
2943
|
+
const staticDependencies = collectStaticExpressionDependencies(program, target);
|
|
2944
|
+
if (!staticDependencies) {
|
|
2945
|
+
debugStaticResolve(action, {
|
|
2946
|
+
exported: exportedName,
|
|
2947
|
+
filename,
|
|
2948
|
+
phase: 'export',
|
|
2949
|
+
reason: 'unsupported-expression',
|
|
2950
|
+
status: 'rejected',
|
|
2951
|
+
});
|
|
2952
|
+
const metadataResult = yield* resolveProcessorStaticExport(action, filename, code, codeHash, program, exportedName, stack, memo);
|
|
2953
|
+
debugStaticResolve(action, {
|
|
2954
|
+
exported: exportedName,
|
|
2955
|
+
filename,
|
|
2956
|
+
phase: 'export',
|
|
2957
|
+
reason: metadataResult ? undefined : 'resolve-failed',
|
|
2958
|
+
status: metadataResult ? 'resolved' : 'rejected',
|
|
2959
|
+
});
|
|
2960
|
+
return finish(metadataResult);
|
|
2961
|
+
}
|
|
2962
|
+
const env = new Map();
|
|
2963
|
+
const dependencies = new Set([filename]);
|
|
2964
|
+
const sideEffectDependencies = new Set();
|
|
2965
|
+
for (const binding of staticDependencies.imports) {
|
|
2966
|
+
const resolved = yield* resolveImportValue(action, filename, binding, stack, memo);
|
|
2967
|
+
if (!resolved) {
|
|
2968
|
+
debugStaticResolve(action, {
|
|
2969
|
+
exported: exportedName,
|
|
2970
|
+
filename,
|
|
2971
|
+
imported: binding.imported,
|
|
2972
|
+
phase: 'export',
|
|
2973
|
+
reason: 'resolve-failed',
|
|
2974
|
+
source: binding.source,
|
|
2975
|
+
status: 'rejected',
|
|
2976
|
+
});
|
|
2977
|
+
return finish(null);
|
|
2978
|
+
}
|
|
2979
|
+
if (!bindStaticResolvedValue(env, target.expression, binding.local, resolved)) {
|
|
2980
|
+
debugStaticResolve(action, {
|
|
2981
|
+
exported: exportedName,
|
|
2982
|
+
filename,
|
|
2983
|
+
imported: binding.imported,
|
|
2984
|
+
phase: 'export',
|
|
2985
|
+
reason: 'callable-usage-unsupported',
|
|
2986
|
+
source: binding.source,
|
|
2987
|
+
status: 'rejected',
|
|
2988
|
+
});
|
|
2989
|
+
return finish(null);
|
|
2990
|
+
}
|
|
2991
|
+
resolved.dependencies.forEach((item) => dependencies.add(item));
|
|
2992
|
+
resolved.sideEffectDependencies?.forEach((item) => sideEffectDependencies.add(item));
|
|
2993
|
+
}
|
|
2994
|
+
const value = evaluateOxcStaticExpressionAt(code, filename, {
|
|
2995
|
+
end: target.expression.end,
|
|
2996
|
+
start: target.expression.start,
|
|
2997
|
+
}, env);
|
|
2998
|
+
if (!isOxcStaticSerializableValue(value)) {
|
|
2999
|
+
debugStaticResolve(action, {
|
|
3000
|
+
exported: exportedName,
|
|
3001
|
+
filename,
|
|
3002
|
+
phase: 'export',
|
|
3003
|
+
reason: 'non-serializable',
|
|
3004
|
+
status: 'rejected',
|
|
3005
|
+
});
|
|
3006
|
+
return finish(null);
|
|
3007
|
+
}
|
|
3008
|
+
const result = {
|
|
3009
|
+
dependencies: [...dependencies],
|
|
3010
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
3011
|
+
value,
|
|
3012
|
+
};
|
|
3013
|
+
debugStaticResolve(action, {
|
|
3014
|
+
exported: exportedName,
|
|
3015
|
+
filename,
|
|
3016
|
+
phase: 'export',
|
|
3017
|
+
status: 'resolved',
|
|
3018
|
+
});
|
|
3019
|
+
return finish(result);
|
|
3020
|
+
}
|
|
3021
|
+
function* resolveCandidateValue(action, candidate, filename, memo) {
|
|
3022
|
+
const env = new Map();
|
|
3023
|
+
const dependencies = new Set();
|
|
3024
|
+
const sideEffectDependencies = new Set();
|
|
3025
|
+
const sideEffectImportLocals = new Set();
|
|
3026
|
+
let candidateExpression;
|
|
3027
|
+
for (const item of candidate.imports) {
|
|
3028
|
+
const resolved = yield* resolveImportValue(action, filename, item, new Set(), memo);
|
|
3029
|
+
if (!resolved) {
|
|
3030
|
+
debugStaticResolve(action, {
|
|
3031
|
+
candidate: candidate.name,
|
|
3032
|
+
filename,
|
|
3033
|
+
imported: item.imported,
|
|
3034
|
+
phase: 'candidate',
|
|
3035
|
+
reason: 'candidate-import-unresolved',
|
|
3036
|
+
source: item.source,
|
|
3037
|
+
status: 'rejected',
|
|
3038
|
+
});
|
|
3039
|
+
return null;
|
|
3040
|
+
}
|
|
3041
|
+
if (resolved.callable === 'zero-arg' && candidateExpression === undefined) {
|
|
3042
|
+
candidateExpression = parseStaticExpressionSource(candidate.source, filename);
|
|
3043
|
+
}
|
|
3044
|
+
const expressionForBinding = resolved.callable === 'zero-arg' ? candidateExpression : null;
|
|
3045
|
+
if ((resolved.callable === 'zero-arg' && !expressionForBinding) ||
|
|
3046
|
+
(expressionForBinding &&
|
|
3047
|
+
!bindStaticResolvedValue(env, expressionForBinding, item.local, resolved))) {
|
|
3048
|
+
debugStaticResolve(action, {
|
|
3049
|
+
candidate: candidate.name,
|
|
3050
|
+
filename,
|
|
3051
|
+
imported: item.imported,
|
|
3052
|
+
phase: 'candidate',
|
|
3053
|
+
reason: 'candidate-callable-usage-unsupported',
|
|
3054
|
+
source: item.source,
|
|
3055
|
+
status: 'rejected',
|
|
3056
|
+
});
|
|
3057
|
+
return null;
|
|
3058
|
+
}
|
|
3059
|
+
if (!expressionForBinding) {
|
|
3060
|
+
env.set(item.local, resolved.value);
|
|
3061
|
+
}
|
|
3062
|
+
resolved.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
3063
|
+
resolved.sideEffectDependencies?.forEach((dependency) => {
|
|
3064
|
+
sideEffectDependencies.add(dependency);
|
|
3065
|
+
sideEffectImportLocals.add(item.importLocal ?? item.local);
|
|
3066
|
+
});
|
|
3067
|
+
}
|
|
3068
|
+
const value = evaluateOxcStaticExpression(candidate.source, filename, env);
|
|
3069
|
+
if (!isOxcStaticSerializableValue(value)) {
|
|
3070
|
+
debugStaticResolve(action, {
|
|
3071
|
+
candidate: candidate.name,
|
|
3072
|
+
filename,
|
|
3073
|
+
phase: 'candidate',
|
|
3074
|
+
reason: 'candidate-expression-non-serializable',
|
|
3075
|
+
status: 'rejected',
|
|
3076
|
+
});
|
|
3077
|
+
return null;
|
|
3078
|
+
}
|
|
3079
|
+
debugStaticResolve(action, {
|
|
3080
|
+
candidate: candidate.name,
|
|
3081
|
+
filename,
|
|
3082
|
+
phase: 'candidate',
|
|
3083
|
+
status: 'resolved',
|
|
3084
|
+
});
|
|
3085
|
+
return {
|
|
3086
|
+
dependencies: [...dependencies],
|
|
3087
|
+
sideEffectDependencies: [...sideEffectDependencies],
|
|
3088
|
+
sideEffectImportLocals: [...sideEffectImportLocals],
|
|
3089
|
+
value,
|
|
3090
|
+
};
|
|
3091
|
+
}
|
|
3092
|
+
function* resolveOpaqueRuntimeCandidateValue(action, candidate, filename) {
|
|
3093
|
+
if (candidate.imports.length === 0) {
|
|
3094
|
+
return null;
|
|
3095
|
+
}
|
|
3096
|
+
const dependencies = new Set();
|
|
3097
|
+
const memo = new Map();
|
|
3098
|
+
for (const item of candidate.imports) {
|
|
3099
|
+
const proof = yield* resolveImportAsOpaqueRuntime(action, filename, item, new Set(), memo);
|
|
3100
|
+
if (!proof) {
|
|
3101
|
+
return null;
|
|
3102
|
+
}
|
|
3103
|
+
proof.dependencies.forEach((dependency) => dependencies.add(dependency));
|
|
3104
|
+
}
|
|
3105
|
+
return {
|
|
3106
|
+
dependencies: [...dependencies],
|
|
3107
|
+
value: null,
|
|
3108
|
+
};
|
|
3109
|
+
}
|
|
3110
|
+
export function* resolveStaticOxcPreevalValues() {
|
|
3111
|
+
const preevalResult = this.entrypoint.getPreevalResult();
|
|
3112
|
+
const candidates = preevalResult?.staticValueCandidates ?? [];
|
|
3113
|
+
if (!preevalResult || candidates.length === 0) {
|
|
3114
|
+
return false;
|
|
3115
|
+
}
|
|
3116
|
+
const filename = this.entrypoint.loadedAndParsed.evaluator === 'ignored'
|
|
3117
|
+
? this.entrypoint.name
|
|
3118
|
+
: this.entrypoint.loadedAndParsed.evalConfig.filename ??
|
|
3119
|
+
this.entrypoint.name;
|
|
3120
|
+
if (!isStaticImportValuesEnabled(this, filename)) {
|
|
3121
|
+
debugStaticResolve(this, {
|
|
3122
|
+
filename,
|
|
3123
|
+
phase: 'entrypoint',
|
|
3124
|
+
reason: 'feature-disabled',
|
|
3125
|
+
status: 'skipped',
|
|
3126
|
+
});
|
|
3127
|
+
return false;
|
|
3128
|
+
}
|
|
3129
|
+
const staticValueCache = preevalResult.staticValueCache ?? new Map();
|
|
3130
|
+
const staticDependencies = new Set(preevalResult.staticDependencies ?? []);
|
|
3131
|
+
const staticImportLocals = new Set();
|
|
3132
|
+
const sideEffectImportLocals = new Set();
|
|
3133
|
+
const staticNullWYWMetaExtendsHelpers = new Set(preevalResult.staticNullWYWMetaExtendsHelpers ?? []);
|
|
3134
|
+
const memo = new Map();
|
|
3135
|
+
const opaqueRuntimeBaseHelpers = collectWYWMetaExtendsHelperNames(parseProgram(preevalResult.baseCode ?? preevalResult.code, filename));
|
|
3136
|
+
const evalDependencyNames = new Set(preevalResult.dependencyNames ?? []);
|
|
3137
|
+
let changed = false;
|
|
3138
|
+
let hasKnownStaticCandidate = false;
|
|
3139
|
+
for (const candidate of candidates) {
|
|
3140
|
+
const isOpaqueRuntimeBaseHelper = opaqueRuntimeBaseHelpers.has(candidate.name);
|
|
3141
|
+
if (!evalDependencyNames.has(candidate.name) &&
|
|
3142
|
+
!isOpaqueRuntimeBaseHelper &&
|
|
3143
|
+
!staticValueCache.has(candidate.name)) {
|
|
3144
|
+
debugStaticResolve(this, {
|
|
3145
|
+
candidate: candidate.name,
|
|
3146
|
+
filename,
|
|
3147
|
+
phase: 'candidate',
|
|
3148
|
+
reason: 'not-eval-dependency',
|
|
3149
|
+
status: 'skipped',
|
|
3150
|
+
});
|
|
3151
|
+
continue;
|
|
3152
|
+
}
|
|
3153
|
+
if (staticValueCache.has(candidate.name)) {
|
|
3154
|
+
hasKnownStaticCandidate = true;
|
|
3155
|
+
candidate.imports.forEach((item) => staticImportLocals.add(item.importLocal ?? item.local));
|
|
3156
|
+
if (isOpaqueRuntimeBaseHelper &&
|
|
3157
|
+
staticValueCache.get(candidate.name) === null) {
|
|
3158
|
+
staticNullWYWMetaExtendsHelpers.add(candidate.name);
|
|
3159
|
+
}
|
|
3160
|
+
debugStaticResolve(this, {
|
|
3161
|
+
candidate: candidate.name,
|
|
3162
|
+
filename,
|
|
3163
|
+
phase: 'candidate',
|
|
3164
|
+
reason: 'already-static',
|
|
3165
|
+
status: 'skipped',
|
|
3166
|
+
});
|
|
3167
|
+
continue;
|
|
3168
|
+
}
|
|
3169
|
+
let resolved;
|
|
3170
|
+
let resolvedOpaqueRuntimeBase = false;
|
|
3171
|
+
if (isOpaqueRuntimeBaseHelper) {
|
|
3172
|
+
resolved = yield* resolveOpaqueRuntimeCandidateValue(this, candidate, filename);
|
|
3173
|
+
resolvedOpaqueRuntimeBase = !!resolved;
|
|
3174
|
+
if (!resolved) {
|
|
3175
|
+
resolved = yield* resolveCandidateValue(this, candidate, filename, memo);
|
|
3176
|
+
}
|
|
3177
|
+
}
|
|
3178
|
+
else {
|
|
3179
|
+
resolved = yield* resolveCandidateValue(this, candidate, filename, memo);
|
|
3180
|
+
}
|
|
3181
|
+
if (!resolved) {
|
|
3182
|
+
continue;
|
|
3183
|
+
}
|
|
3184
|
+
if (resolvedOpaqueRuntimeBase) {
|
|
3185
|
+
debugStaticResolve(this, {
|
|
3186
|
+
candidate: candidate.name,
|
|
3187
|
+
filename,
|
|
3188
|
+
phase: 'candidate',
|
|
3189
|
+
reason: 'opaque-runtime-component',
|
|
3190
|
+
status: 'resolved',
|
|
3191
|
+
});
|
|
3192
|
+
staticNullWYWMetaExtendsHelpers.add(candidate.name);
|
|
3193
|
+
}
|
|
3194
|
+
staticValueCache.set(candidate.name, resolved.value);
|
|
3195
|
+
hasKnownStaticCandidate = true;
|
|
3196
|
+
candidate.imports.forEach((item) => staticImportLocals.add(item.importLocal ?? item.local));
|
|
3197
|
+
resolved.dependencies.forEach((dependency) => staticDependencies.add(dependency));
|
|
3198
|
+
resolved.sideEffectImportLocals?.forEach((local) => sideEffectImportLocals.add(local));
|
|
3199
|
+
changed = true;
|
|
3200
|
+
}
|
|
3201
|
+
if (!changed && !hasKnownStaticCandidate) {
|
|
3202
|
+
return false;
|
|
3203
|
+
}
|
|
3204
|
+
const dependencyNames = (preevalResult.dependencyNames ?? []).filter((name) => !staticValueCache.has(name));
|
|
3205
|
+
preevalResult.dependencyNames = dependencyNames;
|
|
3206
|
+
preevalResult.staticValueCache = staticValueCache;
|
|
3207
|
+
preevalResult.staticDependencies = [...staticDependencies];
|
|
3208
|
+
preevalResult.staticNullWYWMetaExtendsHelpers = [
|
|
3209
|
+
...staticNullWYWMetaExtendsHelpers,
|
|
3210
|
+
];
|
|
3211
|
+
const originalBaseCode = preevalResult.baseCode ?? preevalResult.code;
|
|
3212
|
+
const staticExtendsHelperValues = new Map(staticValueCache);
|
|
3213
|
+
staticNullWYWMetaExtendsHelpers.forEach((name) => {
|
|
3214
|
+
if (!staticExtendsHelperValues.has(name)) {
|
|
3215
|
+
staticExtendsHelperValues.set(name, null);
|
|
3216
|
+
}
|
|
3217
|
+
});
|
|
3218
|
+
const baseCode = pruneStaticPreevalCode(originalBaseCode, filename, new Set(staticValueCache.keys()), staticImportLocals, staticExtendsHelperValues, sideEffectImportLocals);
|
|
3219
|
+
const evalBaseCode = sideEffectImportLocals.size > 0
|
|
3220
|
+
? pruneStaticPreevalCode(originalBaseCode, filename, new Set(staticValueCache.keys()), staticImportLocals, staticExtendsHelperValues, new Set())
|
|
3221
|
+
: baseCode;
|
|
3222
|
+
preevalResult.baseCode = baseCode;
|
|
3223
|
+
preevalResult.code = appendOxcWywPreval(baseCode, filename, dependencyNames);
|
|
3224
|
+
preevalResult.evalCode = appendOxcWywPreval(evalBaseCode, filename, dependencyNames);
|
|
3225
|
+
preevalResult.staticSideEffectImportLocals = [...sideEffectImportLocals];
|
|
3226
|
+
for (const dependency of staticDependencies) {
|
|
3227
|
+
this.entrypoint.addInvalidationDependency({
|
|
3228
|
+
only: ['*'],
|
|
3229
|
+
resolved: dependency,
|
|
3230
|
+
source: dependency,
|
|
3231
|
+
});
|
|
3232
|
+
this.entrypoint.markInvalidateOnDependencyChange(dependency);
|
|
3233
|
+
}
|
|
3234
|
+
return true;
|
|
3235
|
+
}
|