@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,1759 @@
|
|
|
1
|
+
/* eslint-disable no-underscore-dangle */
|
|
2
|
+
/* global BigInt */
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import { Console } from "node:console";
|
|
5
|
+
import { Writable } from "node:stream";
|
|
6
|
+
import vm from "node:vm";
|
|
7
|
+
import path from "node:path";
|
|
8
|
+
import NativeModule, { createRequire } from "node:module";
|
|
9
|
+
import { pathToFileURL } from "node:url";
|
|
10
|
+
import { Minimatch } from "minimatch";
|
|
11
|
+
class LruCache {
|
|
12
|
+
constructor(maxSize) {
|
|
13
|
+
this.maxSize = Math.max(1, maxSize);
|
|
14
|
+
this.map = new Map();
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
if (!this.map.has(key)) return undefined;
|
|
18
|
+
const value = this.map.get(key);
|
|
19
|
+
this.map.delete(key);
|
|
20
|
+
this.map.set(key, value);
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
set(key, value) {
|
|
24
|
+
if (this.map.has(key)) {
|
|
25
|
+
this.map.delete(key);
|
|
26
|
+
}
|
|
27
|
+
this.map.set(key, value);
|
|
28
|
+
if (this.map.size > this.maxSize) {
|
|
29
|
+
const firstKey = this.map.keys().next().value;
|
|
30
|
+
if (firstKey !== undefined) {
|
|
31
|
+
this.map.delete(firstKey);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
delete(key) {
|
|
36
|
+
this.map.delete(key);
|
|
37
|
+
}
|
|
38
|
+
clear() {
|
|
39
|
+
this.map.clear();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const NOOP = () => {};
|
|
43
|
+
// stdout is reserved for the JSON IPC protocol; host-side logs must not share it.
|
|
44
|
+
const prefixStream = (getPrefix) => new Writable({ write(chunk, _enc, cb) {
|
|
45
|
+
const p = getPrefix();
|
|
46
|
+
const s = chunk.toString();
|
|
47
|
+
// Prefix interior newlines but not the trailing one — avoids
|
|
48
|
+
// double-prefix when consecutive writes each start with a prefix.
|
|
49
|
+
const tail = s.endsWith("\n") ? "\n" : "";
|
|
50
|
+
const body = tail ? s.slice(0, -1) : s;
|
|
51
|
+
process.stderr.write(p + body.replaceAll("\n", `\n${p}`) + tail, cb);
|
|
52
|
+
} });
|
|
53
|
+
// require'd modules outside vm use host console — must not write to stdout (IPC channel).
|
|
54
|
+
global.console = new Console({
|
|
55
|
+
stdout: prefixStream(() => "[wyw-runner:host stdout] "),
|
|
56
|
+
stderr: prefixStream(() => "[wyw-runner:host stderr] ")
|
|
57
|
+
});
|
|
58
|
+
const VITE_VIRTUAL_PREFIX = "/@";
|
|
59
|
+
const REACT_REFRESH_VIRTUAL_ID = "/@react-refresh";
|
|
60
|
+
const reactRefreshRuntime = { createSignatureFunctionForTransform: () => () => {} };
|
|
61
|
+
const builtins = {
|
|
62
|
+
assert: true,
|
|
63
|
+
buffer: true,
|
|
64
|
+
child_process: false,
|
|
65
|
+
cluster: false,
|
|
66
|
+
console: true,
|
|
67
|
+
constants: true,
|
|
68
|
+
crypto: true,
|
|
69
|
+
dgram: false,
|
|
70
|
+
dns: false,
|
|
71
|
+
domain: true,
|
|
72
|
+
events: true,
|
|
73
|
+
fs: false,
|
|
74
|
+
http: true,
|
|
75
|
+
https: true,
|
|
76
|
+
module: false,
|
|
77
|
+
net: false,
|
|
78
|
+
os: true,
|
|
79
|
+
path: true,
|
|
80
|
+
punycode: true,
|
|
81
|
+
process: true,
|
|
82
|
+
querystring: true,
|
|
83
|
+
readline: false,
|
|
84
|
+
repl: false,
|
|
85
|
+
stream: true,
|
|
86
|
+
string_decoder: true,
|
|
87
|
+
sys: true,
|
|
88
|
+
timers: true,
|
|
89
|
+
tls: false,
|
|
90
|
+
tty: true,
|
|
91
|
+
url: true,
|
|
92
|
+
util: true,
|
|
93
|
+
vm: true,
|
|
94
|
+
zlib: true
|
|
95
|
+
};
|
|
96
|
+
const RESOLVE_CACHE_SIZE = 5e3;
|
|
97
|
+
const LOAD_CACHE_SIZE = 1e3;
|
|
98
|
+
const MODULE_VARIANT_LIMIT = 8;
|
|
99
|
+
const isBuiltinSpecifier = (specifier) => {
|
|
100
|
+
const normalized = specifier.startsWith("node:") ? specifier.slice(5) : specifier;
|
|
101
|
+
return NativeModule.builtinModules?.includes(normalized) || NativeModule.builtinModules?.includes(`node:${normalized}`);
|
|
102
|
+
};
|
|
103
|
+
const packageTypeCache = new Map();
|
|
104
|
+
const getPackageType = (filename) => {
|
|
105
|
+
let dir = path.dirname(filename);
|
|
106
|
+
while (dir && dir !== path.dirname(dir)) {
|
|
107
|
+
const cached = packageTypeCache.get(dir);
|
|
108
|
+
if (cached === "module" || cached === "commonjs") return cached;
|
|
109
|
+
const pkgPath = path.join(dir, "package.json");
|
|
110
|
+
if (fs.existsSync(pkgPath)) {
|
|
111
|
+
try {
|
|
112
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
113
|
+
const type = pkg?.type === "module" ? "module" : "commonjs";
|
|
114
|
+
packageTypeCache.set(dir, type);
|
|
115
|
+
return type;
|
|
116
|
+
} catch {
|
|
117
|
+
packageTypeCache.set(dir, null);
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
packageTypeCache.set(dir, null);
|
|
122
|
+
dir = path.dirname(dir);
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
};
|
|
126
|
+
const shouldPreferImport = (resolvedFile) => {
|
|
127
|
+
if (!resolvedFile) return false;
|
|
128
|
+
if (!path.isAbsolute(resolvedFile)) return false;
|
|
129
|
+
if (resolvedFile.endsWith(".mjs")) return true;
|
|
130
|
+
if (resolvedFile.endsWith(".cjs")) return false;
|
|
131
|
+
if (!resolvedFile.endsWith(".js")) return false;
|
|
132
|
+
return getPackageType(resolvedFile) === "module";
|
|
133
|
+
};
|
|
134
|
+
const isPlainObject = (value) => {
|
|
135
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
const prototype = Object.getPrototypeOf(value);
|
|
139
|
+
if (prototype === null || prototype === Object.prototype) {
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
return Object.getPrototypeOf(prototype) === null;
|
|
143
|
+
};
|
|
144
|
+
const ENCODED_GLOBAL_ENVELOPE_KEY = "__wyw_eval_global";
|
|
145
|
+
const ENCODED_GLOBAL_SIGNATURE = "wyw-eval-global";
|
|
146
|
+
const ENCODED_GLOBAL_VERSION = 1;
|
|
147
|
+
const IDENTIFIER_RE = /^[A-Za-z_$][\w$]*$/u;
|
|
148
|
+
const ARRAY_INDEX_RE = /^(?:0|[1-9]\d*)$/;
|
|
149
|
+
const IPC_SUPPORTED_VALUE_HINT = "Use importOverrides to mock the import or return plain data: null, booleans, strings, numbers, bigint, undefined, arrays, plain objects, and Error.";
|
|
150
|
+
const getObjectTypeName = (value) => {
|
|
151
|
+
const { constructor } = value ?? {};
|
|
152
|
+
if (constructor && typeof constructor.name === "string" && constructor.name.length > 0) {
|
|
153
|
+
return constructor.name;
|
|
154
|
+
}
|
|
155
|
+
const tag = Object.prototype.toString.call(value);
|
|
156
|
+
return tag.slice(8, -1) || "Object";
|
|
157
|
+
};
|
|
158
|
+
const getBoxedPrimitiveValue = (value) => {
|
|
159
|
+
const tag = Object.prototype.toString.call(value);
|
|
160
|
+
if (tag === "[object String]") {
|
|
161
|
+
return {
|
|
162
|
+
kind: "string",
|
|
163
|
+
value: String(value.valueOf())
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
if (tag === "[object Number]") {
|
|
167
|
+
return {
|
|
168
|
+
kind: "number",
|
|
169
|
+
value: Number(value.valueOf())
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (tag === "[object Boolean]") {
|
|
173
|
+
return {
|
|
174
|
+
kind: "boolean",
|
|
175
|
+
value: Boolean(value.valueOf())
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
return null;
|
|
179
|
+
};
|
|
180
|
+
const formatPath = (rootLabel, pathSegments) => pathSegments.reduce((acc, segment) => {
|
|
181
|
+
if (typeof segment === "number") {
|
|
182
|
+
return `${acc}[${segment}]`;
|
|
183
|
+
}
|
|
184
|
+
if (typeof segment === "symbol") {
|
|
185
|
+
return `${acc}[${String(segment)}]`;
|
|
186
|
+
}
|
|
187
|
+
if (IDENTIFIER_RE.test(segment)) {
|
|
188
|
+
return `${acc}.${segment}`;
|
|
189
|
+
}
|
|
190
|
+
return `${acc}[${JSON.stringify(segment)}]`;
|
|
191
|
+
}, rootLabel);
|
|
192
|
+
const formatGlobalsPath = (pathSegments) => formatPath("eval.globals", pathSegments);
|
|
193
|
+
const restoreGlobalFunction = (source, pathSegments) => {
|
|
194
|
+
try {
|
|
195
|
+
// eslint-disable-next-line no-eval
|
|
196
|
+
const restored = eval(`(${source})`);
|
|
197
|
+
if (typeof restored !== "function") {
|
|
198
|
+
throw new TypeError("decoded source is not a function");
|
|
199
|
+
}
|
|
200
|
+
return restored;
|
|
201
|
+
} catch (error) {
|
|
202
|
+
throw new Error(`[wyw-in-js] Failed to restore eval.globals function at ${formatGlobalsPath(pathSegments)}. ` + `Ensure the value is a user-defined function expression/arrow function. ` + `Native and bound functions are not supported. ` + `Original error: ${String(error)}`);
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
const isEncodedGlobalPayload = (value) => {
|
|
206
|
+
if (!isPlainObject(value)) {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
if (value.signature !== ENCODED_GLOBAL_SIGNATURE || value.version !== ENCODED_GLOBAL_VERSION) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
if (value.kind === "function") {
|
|
213
|
+
return typeof value.source === "string";
|
|
214
|
+
}
|
|
215
|
+
if (value.kind === "symbol") {
|
|
216
|
+
return typeof value.description === "string";
|
|
217
|
+
}
|
|
218
|
+
return false;
|
|
219
|
+
};
|
|
220
|
+
const isEncodedGlobalEnvelope = (value) => {
|
|
221
|
+
if (!isPlainObject(value)) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
const keys = Object.keys(value);
|
|
225
|
+
if (keys.length !== 1 || keys[0] !== ENCODED_GLOBAL_ENVELOPE_KEY) {
|
|
226
|
+
return false;
|
|
227
|
+
}
|
|
228
|
+
return isEncodedGlobalPayload(value[ENCODED_GLOBAL_ENVELOPE_KEY]);
|
|
229
|
+
};
|
|
230
|
+
const canonicalizeForSignature = (value) => {
|
|
231
|
+
if (Array.isArray(value)) {
|
|
232
|
+
return value.map((item) => canonicalizeForSignature(item));
|
|
233
|
+
}
|
|
234
|
+
if (isPlainObject(value)) {
|
|
235
|
+
return Object.fromEntries(Object.keys(value).sort().map((key) => [key, canonicalizeForSignature(value[key])]));
|
|
236
|
+
}
|
|
237
|
+
return value;
|
|
238
|
+
};
|
|
239
|
+
const decodeGlobals = (value, pathSegments = []) => {
|
|
240
|
+
if (Array.isArray(value)) {
|
|
241
|
+
return value.map((item, index) => decodeGlobals(item, [...pathSegments, index]));
|
|
242
|
+
}
|
|
243
|
+
if (isEncodedGlobalEnvelope(value)) {
|
|
244
|
+
const payload = value[ENCODED_GLOBAL_ENVELOPE_KEY];
|
|
245
|
+
if (payload.kind === "function") {
|
|
246
|
+
return restoreGlobalFunction(payload.source, pathSegments);
|
|
247
|
+
}
|
|
248
|
+
return Symbol(payload.description);
|
|
249
|
+
}
|
|
250
|
+
if (isPlainObject(value)) {
|
|
251
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, decodeGlobals(item, [...pathSegments, key])]));
|
|
252
|
+
}
|
|
253
|
+
return value;
|
|
254
|
+
};
|
|
255
|
+
const getEnumerableSymbolKeys = (value) => Object.getOwnPropertySymbols(value).filter((key) => Object.prototype.propertyIsEnumerable.call(value, key));
|
|
256
|
+
const isLikeError = (value) => typeof value === "object" && value !== null && !isPlainObject(value) && "message" in value && typeof value.message === "string" && ("stack" in value || "name" in value);
|
|
257
|
+
const throwUnsupportedIpcValue = (rootLabel, pathSegments, description) => {
|
|
258
|
+
throw new Error(`[wyw-in-js] ${rootLabel} contains ${description} at ${formatPath(rootLabel, pathSegments)}. ${IPC_SUPPORTED_VALUE_HINT}`);
|
|
259
|
+
};
|
|
260
|
+
const serializeValueAtPath = (value, rootLabel, pathSegments, seen, allowFunctions, allowSymbols) => {
|
|
261
|
+
if (value === null) {
|
|
262
|
+
return { kind: "null" };
|
|
263
|
+
}
|
|
264
|
+
if (value === undefined) return { kind: "undefined" };
|
|
265
|
+
if (typeof value === "boolean") {
|
|
266
|
+
return {
|
|
267
|
+
kind: "boolean",
|
|
268
|
+
value
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
if (typeof value === "string") {
|
|
272
|
+
return {
|
|
273
|
+
kind: "string",
|
|
274
|
+
value
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
if (typeof value === "number") {
|
|
278
|
+
if (Number.isNaN(value)) return { kind: "nan" };
|
|
279
|
+
if (value === Infinity) return { kind: "infinity" };
|
|
280
|
+
if (value === -Infinity) return { kind: "-infinity" };
|
|
281
|
+
return {
|
|
282
|
+
kind: "number",
|
|
283
|
+
value
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if (typeof value === "bigint") {
|
|
287
|
+
return {
|
|
288
|
+
kind: "bigint",
|
|
289
|
+
value: value.toString()
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
if (typeof value === "function") {
|
|
293
|
+
if (allowFunctions) {
|
|
294
|
+
// __wywPreval consumers only rely on function-ness, not implementation
|
|
295
|
+
// identity. Preserve that signal explicitly instead of letting JSON
|
|
296
|
+
// coerce to null/undefined.
|
|
297
|
+
return { kind: "function" };
|
|
298
|
+
}
|
|
299
|
+
throwUnsupportedIpcValue(rootLabel, pathSegments, "an unsupported function");
|
|
300
|
+
}
|
|
301
|
+
if (typeof value === "symbol") {
|
|
302
|
+
if (allowSymbols) {
|
|
303
|
+
return {
|
|
304
|
+
kind: "symbol",
|
|
305
|
+
description: value.description ?? ""
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
throwUnsupportedIpcValue(rootLabel, pathSegments, "an unsupported symbol");
|
|
309
|
+
}
|
|
310
|
+
if (typeof value === "object" && value !== null) {
|
|
311
|
+
const boxed = getBoxedPrimitiveValue(value);
|
|
312
|
+
if (boxed) {
|
|
313
|
+
if (boxed.kind === "number") {
|
|
314
|
+
if (Number.isNaN(boxed.value)) return { kind: "nan" };
|
|
315
|
+
if (boxed.value === Infinity) return { kind: "infinity" };
|
|
316
|
+
if (boxed.value === -Infinity) return { kind: "-infinity" };
|
|
317
|
+
}
|
|
318
|
+
return boxed;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
if (isLikeError(value)) {
|
|
322
|
+
return {
|
|
323
|
+
kind: "error",
|
|
324
|
+
error: {
|
|
325
|
+
message: value.message,
|
|
326
|
+
name: value.name,
|
|
327
|
+
stack: value.stack
|
|
328
|
+
}
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
const currentPath = formatPath(rootLabel, pathSegments);
|
|
332
|
+
const seenAt = seen.get(value);
|
|
333
|
+
if (seenAt) {
|
|
334
|
+
throw new Error(`[wyw-in-js] ${rootLabel} contains a circular reference at ${currentPath} (from ${seenAt}). ${IPC_SUPPORTED_VALUE_HINT}`);
|
|
335
|
+
}
|
|
336
|
+
if (Array.isArray(value)) {
|
|
337
|
+
const symbolKeys = getEnumerableSymbolKeys(value);
|
|
338
|
+
if (symbolKeys.length > 0) {
|
|
339
|
+
throwUnsupportedIpcValue(rootLabel, [...pathSegments, symbolKeys[0]], "an unsupported symbol-keyed property");
|
|
340
|
+
}
|
|
341
|
+
const extraKey = Object.keys(value).find((key) => !ARRAY_INDEX_RE.test(key) || Number(key) >= value.length);
|
|
342
|
+
if (extraKey !== undefined) {
|
|
343
|
+
throwUnsupportedIpcValue(rootLabel, [...pathSegments, extraKey], "an unsupported non-index array property");
|
|
344
|
+
}
|
|
345
|
+
seen.set(value, currentPath);
|
|
346
|
+
try {
|
|
347
|
+
return {
|
|
348
|
+
kind: "array",
|
|
349
|
+
items: Array.from({ length: value.length }, (_, index) => serializeValueAtPath(value[index], rootLabel, [...pathSegments, index], seen, allowFunctions, allowSymbols))
|
|
350
|
+
};
|
|
351
|
+
} finally {
|
|
352
|
+
seen.delete(value);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
if (!isPlainObject(value)) {
|
|
356
|
+
throwUnsupportedIpcValue(rootLabel, pathSegments, `an unsupported non-plain object (${getObjectTypeName(value)})`);
|
|
357
|
+
}
|
|
358
|
+
const symbolKeys = getEnumerableSymbolKeys(value);
|
|
359
|
+
if (symbolKeys.length > 0) {
|
|
360
|
+
throwUnsupportedIpcValue(rootLabel, [...pathSegments, symbolKeys[0]], "an unsupported symbol-keyed property");
|
|
361
|
+
}
|
|
362
|
+
seen.set(value, currentPath);
|
|
363
|
+
try {
|
|
364
|
+
return {
|
|
365
|
+
kind: "object",
|
|
366
|
+
entries: Object.fromEntries(Object.entries(value).map(([key, item]) => [key, serializeValueAtPath(item, rootLabel, [...pathSegments, key], seen, allowFunctions, allowSymbols)]))
|
|
367
|
+
};
|
|
368
|
+
} finally {
|
|
369
|
+
seen.delete(value);
|
|
370
|
+
}
|
|
371
|
+
};
|
|
372
|
+
const isErrRequireEsm = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ERR_REQUIRE_ESM";
|
|
373
|
+
const serializeValue = (value, options = {}) => serializeValueAtPath(value, options.rootLabel ?? "value", options.path ?? [], new WeakMap(), options.allowFunctions ?? false, options.allowSymbols ?? false);
|
|
374
|
+
const deserializeValue = (value) => {
|
|
375
|
+
switch (value?.kind) {
|
|
376
|
+
case "null": return null;
|
|
377
|
+
case "boolean":
|
|
378
|
+
case "string":
|
|
379
|
+
case "number": return value.value;
|
|
380
|
+
case "undefined": return undefined;
|
|
381
|
+
case "bigint": return BigInt(value.value);
|
|
382
|
+
case "nan": return Number.NaN;
|
|
383
|
+
case "infinity": return Infinity;
|
|
384
|
+
case "-infinity": return -Infinity;
|
|
385
|
+
case "function": return () => {};
|
|
386
|
+
case "symbol":
|
|
387
|
+
// eslint-disable-next-line symbol-description
|
|
388
|
+
return value.description ? Symbol.for(value.description) : Symbol();
|
|
389
|
+
case "error": {
|
|
390
|
+
const error = new Error(value.error?.message ?? "");
|
|
391
|
+
if (value.error?.name) {
|
|
392
|
+
error.name = value.error.name;
|
|
393
|
+
}
|
|
394
|
+
if (value.error?.stack) {
|
|
395
|
+
error.stack = value.error.stack;
|
|
396
|
+
}
|
|
397
|
+
return error;
|
|
398
|
+
}
|
|
399
|
+
case "array": return value.items.map((item) => deserializeValue(item));
|
|
400
|
+
case "object": return Object.fromEntries(Object.entries(value.entries).map(([key, item]) => [key, deserializeValue(item)]));
|
|
401
|
+
case "value":
|
|
402
|
+
default: return value?.value;
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
const IMPORT_META_ENV = "__wyw_import_meta_env";
|
|
406
|
+
let importMetaEnvWarned = false;
|
|
407
|
+
let happyDomLoadWarned = false;
|
|
408
|
+
let happyDomUnavailable = false;
|
|
409
|
+
let happyDomImportPromise = null;
|
|
410
|
+
const debugEnabled = Boolean(process.env.WYW_EVAL_RUNNER_DEBUG);
|
|
411
|
+
const debug = (...args) => {
|
|
412
|
+
if (!debugEnabled) return;
|
|
413
|
+
// eslint-disable-next-line no-console
|
|
414
|
+
console.warn("[wyw-eval-runner:debug]", ...args);
|
|
415
|
+
};
|
|
416
|
+
const processShim = {
|
|
417
|
+
nextTick: (fn) => setTimeout(fn, 0),
|
|
418
|
+
platform: "browser",
|
|
419
|
+
arch: "browser",
|
|
420
|
+
execPath: "browser",
|
|
421
|
+
title: "browser",
|
|
422
|
+
pid: 1,
|
|
423
|
+
browser: true,
|
|
424
|
+
argv: [],
|
|
425
|
+
binding() {
|
|
426
|
+
throw new Error("No such module. (Possibly not yet loaded)");
|
|
427
|
+
},
|
|
428
|
+
cwd: () => "/",
|
|
429
|
+
exit: NOOP,
|
|
430
|
+
kill: NOOP,
|
|
431
|
+
chdir: NOOP,
|
|
432
|
+
umask: NOOP,
|
|
433
|
+
dlopen: NOOP,
|
|
434
|
+
uptime: NOOP,
|
|
435
|
+
memoryUsage: NOOP,
|
|
436
|
+
uvCounters: NOOP,
|
|
437
|
+
features: {},
|
|
438
|
+
env: process.env
|
|
439
|
+
};
|
|
440
|
+
const createImportMetaEnvProxy = () => {
|
|
441
|
+
const target = Object.create(null);
|
|
442
|
+
const warnOnce = () => {
|
|
443
|
+
if (importMetaEnvWarned) return;
|
|
444
|
+
importMetaEnvWarned = true;
|
|
445
|
+
// eslint-disable-next-line no-console
|
|
446
|
+
console.warn([
|
|
447
|
+
`[wyw-in-js] import.meta.env was accessed during build-time evaluation, but no env values were provided.`,
|
|
448
|
+
``,
|
|
449
|
+
`If you're using Vite, make sure @wyw-in-js/vite plugin is enabled (it injects Vite env for evaluation).`,
|
|
450
|
+
`Otherwise provide "__wyw_import_meta_env" via pluginOptions.overrideContext.`
|
|
451
|
+
].join("\n"));
|
|
452
|
+
};
|
|
453
|
+
return new Proxy(target, {
|
|
454
|
+
get(obj, key) {
|
|
455
|
+
if (typeof key === "symbol") return Reflect.get(obj, key);
|
|
456
|
+
warnOnce();
|
|
457
|
+
return obj[key];
|
|
458
|
+
},
|
|
459
|
+
has(obj, key) {
|
|
460
|
+
if (typeof key === "symbol") return Reflect.has(obj, key);
|
|
461
|
+
warnOnce();
|
|
462
|
+
return Reflect.has(obj, key);
|
|
463
|
+
},
|
|
464
|
+
getOwnPropertyDescriptor(obj, key) {
|
|
465
|
+
return Reflect.getOwnPropertyDescriptor(obj, key);
|
|
466
|
+
},
|
|
467
|
+
ownKeys(obj) {
|
|
468
|
+
return Reflect.ownKeys(obj);
|
|
469
|
+
},
|
|
470
|
+
set(obj, key, value) {
|
|
471
|
+
if (typeof key === "symbol") return Reflect.set(obj, key, value);
|
|
472
|
+
warnOnce();
|
|
473
|
+
return Reflect.set(obj, key, value);
|
|
474
|
+
}
|
|
475
|
+
});
|
|
476
|
+
};
|
|
477
|
+
const HAPPY_DOM_TIMEOUT_MS = Number(process.env.WYW_EVAL_HAPPYDOM_INIT_TIMEOUT_MS ?? process.env.WYW_HAPPYDOM_TIMEOUT_MS ?? 15e3);
|
|
478
|
+
const withTimeout = (promise, timeoutMs, label) => {
|
|
479
|
+
if (!timeoutMs || timeoutMs <= 0) return promise;
|
|
480
|
+
let timeoutId;
|
|
481
|
+
const timeout = new Promise((_, reject) => {
|
|
482
|
+
timeoutId = setTimeout(() => {
|
|
483
|
+
const error = new Error(`[wyw-in-js] Timed out while waiting for ${label}.`);
|
|
484
|
+
error.code = "WYW_HAPPYDOM_TIMEOUT";
|
|
485
|
+
reject(error);
|
|
486
|
+
}, timeoutMs);
|
|
487
|
+
});
|
|
488
|
+
return Promise.race([promise, timeout]).finally(() => {
|
|
489
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
490
|
+
});
|
|
491
|
+
};
|
|
492
|
+
const loadHappyDom = async () => {
|
|
493
|
+
if (!happyDomImportPromise) {
|
|
494
|
+
happyDomImportPromise = import("happy-dom");
|
|
495
|
+
}
|
|
496
|
+
return happyDomImportPromise;
|
|
497
|
+
};
|
|
498
|
+
const createWindow = async () => {
|
|
499
|
+
if (happyDomUnavailable) return undefined;
|
|
500
|
+
try {
|
|
501
|
+
debug("happyDom:import:start");
|
|
502
|
+
const importStart = Date.now();
|
|
503
|
+
const { Window, GlobalWindow } = await withTimeout(loadHappyDom(), HAPPY_DOM_TIMEOUT_MS, "happy-dom import");
|
|
504
|
+
debug("happyDom:import:done", Date.now() - importStart);
|
|
505
|
+
const HappyWindow = GlobalWindow || Window;
|
|
506
|
+
const windowStart = Date.now();
|
|
507
|
+
const win = new HappyWindow();
|
|
508
|
+
debug("happyDom:window:done", Date.now() - windowStart);
|
|
509
|
+
win.Buffer = Buffer;
|
|
510
|
+
win.Uint8Array = Uint8Array;
|
|
511
|
+
return win;
|
|
512
|
+
} catch (error) {
|
|
513
|
+
happyDomUnavailable = true;
|
|
514
|
+
happyDomImportPromise = null;
|
|
515
|
+
if (!happyDomLoadWarned) {
|
|
516
|
+
happyDomLoadWarned = true;
|
|
517
|
+
// eslint-disable-next-line no-console
|
|
518
|
+
console.warn([
|
|
519
|
+
`[wyw-in-js] DOM emulation is enabled (features.happyDOM), but "happy-dom" could not be loaded in this build-time runtime.`,
|
|
520
|
+
`WyW will continue without DOM emulation (as if features.happyDOM:false).`,
|
|
521
|
+
``,
|
|
522
|
+
`To silence this warning: set features: { happyDOM: false }.`,
|
|
523
|
+
`To restore DOM emulation, ensure "happy-dom" can be imported in the build-time runtime.`
|
|
524
|
+
].join("\n"));
|
|
525
|
+
}
|
|
526
|
+
return undefined;
|
|
527
|
+
}
|
|
528
|
+
};
|
|
529
|
+
const setReferencePropertyIfNotPresent = (context, key) => {
|
|
530
|
+
if (context[key] === context) return;
|
|
531
|
+
context[key] = context;
|
|
532
|
+
};
|
|
533
|
+
const createBaseContext = (win, additionalContext) => {
|
|
534
|
+
const baseContext = win ?? {};
|
|
535
|
+
setReferencePropertyIfNotPresent(baseContext, "window");
|
|
536
|
+
setReferencePropertyIfNotPresent(baseContext, "self");
|
|
537
|
+
setReferencePropertyIfNotPresent(baseContext, "top");
|
|
538
|
+
setReferencePropertyIfNotPresent(baseContext, "parent");
|
|
539
|
+
setReferencePropertyIfNotPresent(baseContext, "global");
|
|
540
|
+
setReferencePropertyIfNotPresent(baseContext, "process");
|
|
541
|
+
baseContext.document = win?.document;
|
|
542
|
+
baseContext.process = processShim;
|
|
543
|
+
baseContext.clearImmediate = NOOP;
|
|
544
|
+
baseContext.clearInterval = NOOP;
|
|
545
|
+
baseContext.clearTimeout = NOOP;
|
|
546
|
+
baseContext.setImmediate = NOOP;
|
|
547
|
+
baseContext.requestAnimationFrame = NOOP;
|
|
548
|
+
baseContext.setInterval = NOOP;
|
|
549
|
+
baseContext.setTimeout = NOOP;
|
|
550
|
+
Object.assign(baseContext, additionalContext);
|
|
551
|
+
return baseContext;
|
|
552
|
+
};
|
|
553
|
+
const featureMatchers = new Map();
|
|
554
|
+
const isFeatureEnabled = (features, featureName, filename) => {
|
|
555
|
+
const value = features?.[featureName] ?? false;
|
|
556
|
+
if (typeof value === "boolean") return value;
|
|
557
|
+
if (value === "*" || value === "**/*") return true;
|
|
558
|
+
const array = Array.isArray(value) ? value : [value];
|
|
559
|
+
return array.map((pattern) => {
|
|
560
|
+
let matcher = featureMatchers.get(pattern);
|
|
561
|
+
if (!matcher) {
|
|
562
|
+
matcher = [pattern.startsWith("!"), new Minimatch(pattern)];
|
|
563
|
+
featureMatchers.set(pattern, matcher);
|
|
564
|
+
}
|
|
565
|
+
return [matcher[0], matcher[1].match(filename)];
|
|
566
|
+
}).reduce((acc, [negated, match]) => negated ? acc && match : acc || match, false);
|
|
567
|
+
};
|
|
568
|
+
const createVmContext = async (filename, features, globals) => {
|
|
569
|
+
const isHappyDomEnabled = isFeatureEnabled(features, "happyDOM", filename);
|
|
570
|
+
const win = isHappyDomEnabled ? await createWindow() : undefined;
|
|
571
|
+
const envContext = { [IMPORT_META_ENV]: createImportMetaEnvProxy() };
|
|
572
|
+
const baseContext = createBaseContext(win, {
|
|
573
|
+
__filename: filename,
|
|
574
|
+
...envContext,
|
|
575
|
+
...globals
|
|
576
|
+
});
|
|
577
|
+
// Evaluated code must never write to stdout — it is the IPC channel.
|
|
578
|
+
const vmIdent = () => `vm(${path.basename(baseContext.__filename ?? "?")})`;
|
|
579
|
+
baseContext.console = new Console({
|
|
580
|
+
stdout: prefixStream(() => `[wyw-runner:${vmIdent()} stdout] `),
|
|
581
|
+
stderr: prefixStream(() => `[wyw-runner:${vmIdent()} stderr] `)
|
|
582
|
+
});
|
|
583
|
+
const context = vm.createContext(baseContext);
|
|
584
|
+
return {
|
|
585
|
+
context,
|
|
586
|
+
teardown: () => {
|
|
587
|
+
if (win?.happyDOM) {
|
|
588
|
+
win.happyDOM.abort();
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
};
|
|
592
|
+
};
|
|
593
|
+
const stripQueryAndHash = (value) => value.split("?")[0]?.split("#")[0] ?? value;
|
|
594
|
+
const normalizeResolvedId = (resolvedId, specifier, importer, extensions) => {
|
|
595
|
+
const stripped = stripQueryAndHash(resolvedId);
|
|
596
|
+
if (!stripped) return resolvedId;
|
|
597
|
+
if (path.extname(stripped)) return resolvedId;
|
|
598
|
+
const isFileSpecifier = specifier.startsWith(".") || path.isAbsolute(specifier);
|
|
599
|
+
if (!isFileSpecifier && !path.isAbsolute(stripped)) {
|
|
600
|
+
return resolvedId;
|
|
601
|
+
}
|
|
602
|
+
let candidate = stripped;
|
|
603
|
+
if (!path.isAbsolute(candidate)) {
|
|
604
|
+
if (!importer) {
|
|
605
|
+
return resolvedId;
|
|
606
|
+
}
|
|
607
|
+
const importerFile = stripQueryAndHash(importer);
|
|
608
|
+
candidate = path.resolve(path.dirname(importerFile), candidate);
|
|
609
|
+
}
|
|
610
|
+
const suffix = resolvedId.slice(stripped.length);
|
|
611
|
+
const resolvedExtensions = extensions ?? [];
|
|
612
|
+
for (let index = 0; index < resolvedExtensions.length; index += 1) {
|
|
613
|
+
const ext = resolvedExtensions[index];
|
|
614
|
+
const fileCandidate = `${candidate}${ext}`;
|
|
615
|
+
if (fs.existsSync(fileCandidate)) {
|
|
616
|
+
return `${fileCandidate}${suffix}`;
|
|
617
|
+
}
|
|
618
|
+
const indexCandidate = path.join(candidate, `index${ext}`);
|
|
619
|
+
if (fs.existsSync(indexCandidate)) {
|
|
620
|
+
return `${indexCandidate}${suffix}`;
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
if (importer) {
|
|
624
|
+
try {
|
|
625
|
+
const importerFile = stripQueryAndHash(importer);
|
|
626
|
+
const nodeRequire = createRequire(pathToFileURL(importerFile).href);
|
|
627
|
+
const resolved = nodeRequire.resolve(stripQueryAndHash(specifier));
|
|
628
|
+
if (resolved && resolved !== stripped) {
|
|
629
|
+
return `${resolved}${suffix}`;
|
|
630
|
+
}
|
|
631
|
+
} catch {}
|
|
632
|
+
}
|
|
633
|
+
return resolvedId;
|
|
634
|
+
};
|
|
635
|
+
const isNodeModulesId = (id) => {
|
|
636
|
+
if (!id) return false;
|
|
637
|
+
const normalized = stripQueryAndHash(id).replace(/\\/g, "/");
|
|
638
|
+
return normalized.includes("/node_modules/");
|
|
639
|
+
};
|
|
640
|
+
const mergeOnly = (current, next) => {
|
|
641
|
+
if (!current || current.length === 0) return next ?? [];
|
|
642
|
+
if (!next || next.length === 0) return current;
|
|
643
|
+
if (current.includes("*") || next.includes("*")) {
|
|
644
|
+
return ["*"];
|
|
645
|
+
}
|
|
646
|
+
return Array.from(new Set([...current, ...next]));
|
|
647
|
+
};
|
|
648
|
+
const toCanonicalFileKey = (resolved, root) => {
|
|
649
|
+
const rootDir = root ? path.resolve(root) : process.cwd();
|
|
650
|
+
const normalizedResolved = path.resolve(resolved);
|
|
651
|
+
let relative = path.relative(rootDir, normalizedResolved);
|
|
652
|
+
if (path.sep !== path.posix.sep) {
|
|
653
|
+
relative = relative.split(path.sep).join(path.posix.sep);
|
|
654
|
+
}
|
|
655
|
+
if (!relative.startsWith(".")) {
|
|
656
|
+
relative = `./${relative}`;
|
|
657
|
+
}
|
|
658
|
+
return relative;
|
|
659
|
+
};
|
|
660
|
+
const toImportKey = ({ source, resolved, root }) => {
|
|
661
|
+
const isFileImport = source.startsWith(".") || path.isAbsolute(source);
|
|
662
|
+
if (isFileImport && resolved) {
|
|
663
|
+
return {
|
|
664
|
+
key: toCanonicalFileKey(resolved, root),
|
|
665
|
+
kind: "file"
|
|
666
|
+
};
|
|
667
|
+
}
|
|
668
|
+
return {
|
|
669
|
+
key: source,
|
|
670
|
+
kind: "package"
|
|
671
|
+
};
|
|
672
|
+
};
|
|
673
|
+
const minimatchOptions = {
|
|
674
|
+
dot: true,
|
|
675
|
+
nocomment: true,
|
|
676
|
+
nonegate: true
|
|
677
|
+
};
|
|
678
|
+
const compileImportOverrides = (importOverrides) => {
|
|
679
|
+
const matchers = Object.entries(importOverrides).map(([pattern, override]) => ({
|
|
680
|
+
matcher: new Minimatch(pattern, minimatchOptions),
|
|
681
|
+
override,
|
|
682
|
+
pattern
|
|
683
|
+
})).sort((a, b) => b.pattern.length - a.pattern.length);
|
|
684
|
+
return { matchers };
|
|
685
|
+
};
|
|
686
|
+
const compiledOverridesCache = new WeakMap();
|
|
687
|
+
const getImportOverride = (importOverrides, key) => {
|
|
688
|
+
if (!importOverrides) return undefined;
|
|
689
|
+
const direct = importOverrides[key];
|
|
690
|
+
if (direct) return direct;
|
|
691
|
+
let compiled = compiledOverridesCache.get(importOverrides);
|
|
692
|
+
if (!compiled) {
|
|
693
|
+
compiled = compileImportOverrides(importOverrides);
|
|
694
|
+
compiledOverridesCache.set(importOverrides, compiled);
|
|
695
|
+
}
|
|
696
|
+
return compiled.matchers.find(({ matcher }) => matcher.match(key))?.override;
|
|
697
|
+
};
|
|
698
|
+
const resolveMockSpecifier = ({ mock, importer, root }) => {
|
|
699
|
+
const specifier = mock.startsWith(".") && root ? path.resolve(root, mock) : mock;
|
|
700
|
+
const nodeRequire = createRequire(pathToFileURL(importer).href);
|
|
701
|
+
return nodeRequire.resolve(specifier);
|
|
702
|
+
};
|
|
703
|
+
const state = {
|
|
704
|
+
context: null,
|
|
705
|
+
teardown: null,
|
|
706
|
+
happyDomEnabled: null,
|
|
707
|
+
globalsSignature: null,
|
|
708
|
+
evalOptions: {
|
|
709
|
+
mode: "strict",
|
|
710
|
+
require: "warn-and-run",
|
|
711
|
+
globals: {},
|
|
712
|
+
importOverrides: undefined,
|
|
713
|
+
root: undefined,
|
|
714
|
+
extensions: []
|
|
715
|
+
},
|
|
716
|
+
features: {},
|
|
717
|
+
entrypoint: "eval-runner"
|
|
718
|
+
};
|
|
719
|
+
const moduleCache = new LruCache(LOAD_CACHE_SIZE);
|
|
720
|
+
const moduleHashes = new Map();
|
|
721
|
+
const moduleData = new Map();
|
|
722
|
+
const moduleOnly = new Map();
|
|
723
|
+
const moduleVariants = new Map();
|
|
724
|
+
const moduleLastVariant = new Map();
|
|
725
|
+
const linkPromises = new Map();
|
|
726
|
+
const loadInFlight = new Map();
|
|
727
|
+
const externalInFlight = new Map();
|
|
728
|
+
const resolveCache = new LruCache(RESOLVE_CACHE_SIZE);
|
|
729
|
+
const resolveInFlight = new Map();
|
|
730
|
+
const pending = new Map();
|
|
731
|
+
const loadResultChunks = new Map();
|
|
732
|
+
let nextId = 0;
|
|
733
|
+
const stdoutWriteQueue = [];
|
|
734
|
+
let stdoutWriteInFlight = false;
|
|
735
|
+
let stdoutWriteFailed = null;
|
|
736
|
+
let shutdownRequested = false;
|
|
737
|
+
let shutdownFinished = false;
|
|
738
|
+
const resetModuleState = () => {
|
|
739
|
+
moduleCache.clear();
|
|
740
|
+
moduleHashes.clear();
|
|
741
|
+
moduleData.clear();
|
|
742
|
+
moduleOnly.clear();
|
|
743
|
+
moduleVariants.clear();
|
|
744
|
+
moduleLastVariant.clear();
|
|
745
|
+
linkPromises.clear();
|
|
746
|
+
loadInFlight.clear();
|
|
747
|
+
externalInFlight.clear();
|
|
748
|
+
resolveInFlight.clear();
|
|
749
|
+
resolveCache.clear();
|
|
750
|
+
sentNamespaceIdentifiers.clear();
|
|
751
|
+
};
|
|
752
|
+
// Tracks the SourceTextModule identifier (versioned with hash) that was last
|
|
753
|
+
// included in an EVAL_RESULT for each id. Reused module variants don't need
|
|
754
|
+
// re-serialization across eval sessions — same variant = same namespace =
|
|
755
|
+
// same exports the broker already has cached.
|
|
756
|
+
const sentNamespaceIdentifiers = new Map();
|
|
757
|
+
const resetSingleModuleState = (id, cachedModule = moduleCache.get(id)) => {
|
|
758
|
+
if (cachedModule) {
|
|
759
|
+
linkPromises.delete(cachedModule);
|
|
760
|
+
}
|
|
761
|
+
const variants = moduleVariants.get(id);
|
|
762
|
+
if (variants) {
|
|
763
|
+
variants.forEach((variant) => linkPromises.delete(variant));
|
|
764
|
+
}
|
|
765
|
+
moduleCache.delete(id);
|
|
766
|
+
moduleHashes.delete(id);
|
|
767
|
+
moduleData.delete(id);
|
|
768
|
+
moduleVariants.delete(id);
|
|
769
|
+
moduleLastVariant.delete(id);
|
|
770
|
+
};
|
|
771
|
+
const isFullModuleLoad = (loaded) => !loaded.only || loaded.only.length === 1 && loaded.only[0] === "*";
|
|
772
|
+
const getModuleVariant = (id, hash) => moduleVariants.get(id)?.get(hash);
|
|
773
|
+
const setModuleVariant = (id, hash, module) => {
|
|
774
|
+
let variants = moduleVariants.get(id);
|
|
775
|
+
if (!variants) {
|
|
776
|
+
variants = new Map();
|
|
777
|
+
moduleVariants.set(id, variants);
|
|
778
|
+
}
|
|
779
|
+
variants.set(hash, module);
|
|
780
|
+
moduleLastVariant.set(id, module);
|
|
781
|
+
if (variants.size > MODULE_VARIANT_LIMIT) {
|
|
782
|
+
const oldestHash = variants.keys().next().value;
|
|
783
|
+
if (oldestHash !== undefined) {
|
|
784
|
+
const oldest = variants.get(oldestHash);
|
|
785
|
+
if (oldest) {
|
|
786
|
+
linkPromises.delete(oldest);
|
|
787
|
+
}
|
|
788
|
+
variants.delete(oldestHash);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
const toSourceModuleId = (id) => stripQueryAndHash(String(id));
|
|
793
|
+
const toVersionedModuleIdentifier = (id, hash) => {
|
|
794
|
+
if (!hash) return id;
|
|
795
|
+
const separator = id.includes("?") ? "&" : "?";
|
|
796
|
+
return `${id}${separator}wyw-hash=${hash}`;
|
|
797
|
+
};
|
|
798
|
+
const resetEvaluationState = () => {
|
|
799
|
+
if (state.teardown) {
|
|
800
|
+
state.teardown();
|
|
801
|
+
}
|
|
802
|
+
state.context = null;
|
|
803
|
+
state.teardown = null;
|
|
804
|
+
state.happyDomEnabled = null;
|
|
805
|
+
state.globalsSignature = null;
|
|
806
|
+
resetModuleState();
|
|
807
|
+
};
|
|
808
|
+
const normalizeWriteError = (label, error) => {
|
|
809
|
+
if (error instanceof Error) {
|
|
810
|
+
return error;
|
|
811
|
+
}
|
|
812
|
+
return new Error(`[wyw-in-js] Failed to write to ${label}: ${String(error)}`);
|
|
813
|
+
};
|
|
814
|
+
const keepAlive = setInterval(() => {}, 6e4);
|
|
815
|
+
const finishShutdown = (exitCode = 0) => {
|
|
816
|
+
if (shutdownFinished) {
|
|
817
|
+
return;
|
|
818
|
+
}
|
|
819
|
+
shutdownFinished = true;
|
|
820
|
+
clearInterval(keepAlive);
|
|
821
|
+
if (state.teardown) {
|
|
822
|
+
state.teardown();
|
|
823
|
+
}
|
|
824
|
+
process.exit(exitCode);
|
|
825
|
+
};
|
|
826
|
+
const flushStdoutWriteQueue = () => {
|
|
827
|
+
if (stdoutWriteInFlight || stdoutWriteFailed) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
const next = stdoutWriteQueue.shift();
|
|
831
|
+
if (!next) {
|
|
832
|
+
if (shutdownRequested) {
|
|
833
|
+
finishShutdown(0);
|
|
834
|
+
}
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
stdoutWriteInFlight = true;
|
|
838
|
+
let settled = false;
|
|
839
|
+
let writeCompleted = false;
|
|
840
|
+
let drainCompleted = true;
|
|
841
|
+
let onClose;
|
|
842
|
+
let onDrain;
|
|
843
|
+
let onError;
|
|
844
|
+
const cleanup = () => {
|
|
845
|
+
process.stdout.off("close", onClose);
|
|
846
|
+
process.stdout.off("drain", onDrain);
|
|
847
|
+
process.stdout.off("error", onError);
|
|
848
|
+
};
|
|
849
|
+
const finish = (error) => {
|
|
850
|
+
if (settled) {
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (error) {
|
|
854
|
+
settled = true;
|
|
855
|
+
stdoutWriteInFlight = false;
|
|
856
|
+
cleanup();
|
|
857
|
+
stdoutWriteFailed = normalizeWriteError("eval runner stdout", error);
|
|
858
|
+
next.reject(stdoutWriteFailed);
|
|
859
|
+
while (stdoutWriteQueue.length > 0) {
|
|
860
|
+
stdoutWriteQueue.shift().reject(stdoutWriteFailed);
|
|
861
|
+
}
|
|
862
|
+
process.stderr.write(`[wyw-eval-runner] ${stdoutWriteFailed.message}\n`);
|
|
863
|
+
finishShutdown(1);
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
if (!writeCompleted || !drainCompleted) {
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
869
|
+
settled = true;
|
|
870
|
+
stdoutWriteInFlight = false;
|
|
871
|
+
cleanup();
|
|
872
|
+
next.resolve();
|
|
873
|
+
flushStdoutWriteQueue();
|
|
874
|
+
};
|
|
875
|
+
onClose = () => {
|
|
876
|
+
finish(new Error("eval runner stdout closed before pending write completed"));
|
|
877
|
+
};
|
|
878
|
+
onDrain = () => {
|
|
879
|
+
drainCompleted = true;
|
|
880
|
+
finish();
|
|
881
|
+
};
|
|
882
|
+
onError = (error) => {
|
|
883
|
+
finish(error);
|
|
884
|
+
};
|
|
885
|
+
process.stdout.once("close", onClose);
|
|
886
|
+
process.stdout.once("error", onError);
|
|
887
|
+
const needsDrain = !process.stdout.write(next.chunk, (error) => {
|
|
888
|
+
writeCompleted = true;
|
|
889
|
+
if (error) {
|
|
890
|
+
finish(error);
|
|
891
|
+
return;
|
|
892
|
+
}
|
|
893
|
+
finish();
|
|
894
|
+
});
|
|
895
|
+
if (needsDrain) {
|
|
896
|
+
drainCompleted = false;
|
|
897
|
+
process.stdout.once("drain", onDrain);
|
|
898
|
+
}
|
|
899
|
+
};
|
|
900
|
+
const queueStdoutWrite = (chunk) => new Promise((resolve, reject) => {
|
|
901
|
+
if (stdoutWriteFailed) {
|
|
902
|
+
reject(stdoutWriteFailed);
|
|
903
|
+
return;
|
|
904
|
+
}
|
|
905
|
+
stdoutWriteQueue.push({
|
|
906
|
+
chunk,
|
|
907
|
+
resolve,
|
|
908
|
+
reject
|
|
909
|
+
});
|
|
910
|
+
flushStdoutWriteQueue();
|
|
911
|
+
});
|
|
912
|
+
const sendMessage = (message) => {
|
|
913
|
+
queueStdoutWrite(`${JSON.stringify(message)}\n`).catch(() => {});
|
|
914
|
+
};
|
|
915
|
+
const shutdown = () => {
|
|
916
|
+
shutdownRequested = true;
|
|
917
|
+
if (!stdoutWriteInFlight && stdoutWriteQueue.length === 0) {
|
|
918
|
+
finishShutdown(0);
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
const sendWarn = (warning) => {
|
|
922
|
+
sendMessage({
|
|
923
|
+
type: "WARN",
|
|
924
|
+
payload: warning
|
|
925
|
+
});
|
|
926
|
+
};
|
|
927
|
+
const serializeError = (error) => {
|
|
928
|
+
const result = {
|
|
929
|
+
message: error?.message ?? String(error),
|
|
930
|
+
stack: error?.stack
|
|
931
|
+
};
|
|
932
|
+
if (error?.cause instanceof Error) {
|
|
933
|
+
result.cause = serializeError(error.cause);
|
|
934
|
+
}
|
|
935
|
+
return result;
|
|
936
|
+
};
|
|
937
|
+
const request = (type, payload) => {
|
|
938
|
+
nextId += 1;
|
|
939
|
+
const id = `${nextId}`;
|
|
940
|
+
sendMessage({
|
|
941
|
+
type,
|
|
942
|
+
id,
|
|
943
|
+
payload
|
|
944
|
+
});
|
|
945
|
+
return new Promise((resolve, reject) => {
|
|
946
|
+
pending.set(id, {
|
|
947
|
+
resolve,
|
|
948
|
+
reject
|
|
949
|
+
});
|
|
950
|
+
});
|
|
951
|
+
};
|
|
952
|
+
const resolvePending = (id, payload) => {
|
|
953
|
+
const pendingItem = pending.get(id);
|
|
954
|
+
if (!pendingItem) return;
|
|
955
|
+
pending.delete(id);
|
|
956
|
+
pendingItem.resolve(payload);
|
|
957
|
+
};
|
|
958
|
+
const handleLoadResult = (id, payload) => {
|
|
959
|
+
if (!payload || typeof payload.codeChunk !== "string" || typeof payload.chunkIndex !== "number" || typeof payload.chunkCount !== "number") {
|
|
960
|
+
resolvePending(id, payload);
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
let entry = loadResultChunks.get(id);
|
|
964
|
+
if (!entry) {
|
|
965
|
+
entry = {
|
|
966
|
+
chunks: new Array(payload.chunkCount),
|
|
967
|
+
received: 0,
|
|
968
|
+
meta: null
|
|
969
|
+
};
|
|
970
|
+
loadResultChunks.set(id, entry);
|
|
971
|
+
}
|
|
972
|
+
if (!entry.chunks[payload.chunkIndex]) {
|
|
973
|
+
entry.received += 1;
|
|
974
|
+
}
|
|
975
|
+
entry.chunks[payload.chunkIndex] = payload.codeChunk;
|
|
976
|
+
if (payload.chunkIndex === 0) {
|
|
977
|
+
const { codeChunk, chunkIndex, chunkCount, ...meta } = payload;
|
|
978
|
+
entry.meta = meta;
|
|
979
|
+
}
|
|
980
|
+
if (entry.received >= payload.chunkCount) {
|
|
981
|
+
const code = entry.chunks.join("");
|
|
982
|
+
const finalPayload = {
|
|
983
|
+
...entry.meta ?? {},
|
|
984
|
+
code
|
|
985
|
+
};
|
|
986
|
+
loadResultChunks.delete(id);
|
|
987
|
+
resolvePending(id, finalPayload);
|
|
988
|
+
}
|
|
989
|
+
};
|
|
990
|
+
const buildPreamble = (id) => [
|
|
991
|
+
`const __wyw_module = __wyw_getModule(${JSON.stringify(id)});`,
|
|
992
|
+
`let exports = __wyw_module.exports;`,
|
|
993
|
+
`const module = __wyw_module.module;`,
|
|
994
|
+
`const require = __wyw_module.require;`,
|
|
995
|
+
`const __filename = __wyw_module.filename;`,
|
|
996
|
+
`const __dirname = __wyw_module.dirname;`,
|
|
997
|
+
`const __wyw_dynamic_import = __wyw_module.dynamicImport;`,
|
|
998
|
+
``
|
|
999
|
+
].join("\n");
|
|
1000
|
+
const getImporterPackage = (importer) => {
|
|
1001
|
+
const normalized = importer.replace(/\\/g, "/");
|
|
1002
|
+
const marker = "/node_modules/";
|
|
1003
|
+
const idx = normalized.lastIndexOf(marker);
|
|
1004
|
+
if (idx === -1) return path.basename(importer);
|
|
1005
|
+
const rest = normalized.slice(idx + marker.length);
|
|
1006
|
+
if (rest.startsWith("@")) {
|
|
1007
|
+
const [scope, name] = rest.split("/").slice(0, 2);
|
|
1008
|
+
return `${scope}/${name}`;
|
|
1009
|
+
}
|
|
1010
|
+
return rest.split("/")[0];
|
|
1011
|
+
};
|
|
1012
|
+
const warnedRequires = new Set();
|
|
1013
|
+
const createRequireFn = (importer) => {
|
|
1014
|
+
const importerFile = stripQueryAndHash(importer);
|
|
1015
|
+
const nodeRequire = createRequire(pathToFileURL(importerFile).href);
|
|
1016
|
+
return (specifier, nonLiteralOrResolved, maybeResolved) => {
|
|
1017
|
+
const hasNonLiteralFlag = typeof nonLiteralOrResolved === "boolean";
|
|
1018
|
+
const nonLiteral = hasNonLiteralFlag ? nonLiteralOrResolved : false;
|
|
1019
|
+
const resolvedOverride = hasNonLiteralFlag ? maybeResolved : nonLiteralOrResolved;
|
|
1020
|
+
const hasResolvedOverride = typeof resolvedOverride === "string" && resolvedOverride.length > 0;
|
|
1021
|
+
if (state.evalOptions.require === "off") {
|
|
1022
|
+
throw new Error(`[wyw-in-js] require() fallback is disabled by eval.require: 'off'.`);
|
|
1023
|
+
}
|
|
1024
|
+
if (nonLiteral || typeof specifier !== "string") {
|
|
1025
|
+
if (state.evalOptions.mode === "strict") {
|
|
1026
|
+
throw new Error(`[wyw-in-js] Non-literal require() is not supported during eval.\n` + `importer: ${importerFile}\n` + `hint: make it a string literal or mock the import via importOverrides.`);
|
|
1027
|
+
}
|
|
1028
|
+
sendWarn({
|
|
1029
|
+
code: "require-error",
|
|
1030
|
+
message: "[wyw-in-js] Non-literal require() reached during eval (loose mode).",
|
|
1031
|
+
importer: importerFile
|
|
1032
|
+
});
|
|
1033
|
+
return {};
|
|
1034
|
+
}
|
|
1035
|
+
if (specifier === REACT_REFRESH_VIRTUAL_ID) {
|
|
1036
|
+
return reactRefreshRuntime;
|
|
1037
|
+
}
|
|
1038
|
+
if (specifier.startsWith(VITE_VIRTUAL_PREFIX) || specifier.startsWith("virtual:")) {
|
|
1039
|
+
return {};
|
|
1040
|
+
}
|
|
1041
|
+
const normalized = specifier.startsWith("node:") ? specifier.slice(5) : specifier;
|
|
1042
|
+
if (NativeModule.builtinModules?.includes(normalized) || NativeModule.builtinModules?.includes(`node:${normalized}`)) {
|
|
1043
|
+
if (normalized in builtins) {
|
|
1044
|
+
if (builtins[normalized]) {
|
|
1045
|
+
return nodeRequire(normalized);
|
|
1046
|
+
}
|
|
1047
|
+
return null;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
const extensions = NativeModule._extensions;
|
|
1051
|
+
const added = [];
|
|
1052
|
+
try {
|
|
1053
|
+
state.evalOptions.extensions?.forEach((ext) => {
|
|
1054
|
+
if (ext === ".cjs" || ext === ".mjs") return;
|
|
1055
|
+
if (ext in extensions) return;
|
|
1056
|
+
extensions[ext] = NOOP;
|
|
1057
|
+
added.push(ext);
|
|
1058
|
+
});
|
|
1059
|
+
let resolved = hasResolvedOverride ? stripQueryAndHash(resolvedOverride) : nodeRequire.resolve(stripQueryAndHash(specifier));
|
|
1060
|
+
const isFileSpecifier = specifier.startsWith(".") || path.isAbsolute(specifier);
|
|
1061
|
+
if (isFileSpecifier && path.extname(specifier) === "" && resolved.endsWith(".cjs")) {
|
|
1062
|
+
const candidate = `${resolved.slice(0, -4)}.js`;
|
|
1063
|
+
if (fs.existsSync(candidate)) {
|
|
1064
|
+
resolved = candidate;
|
|
1065
|
+
}
|
|
1066
|
+
}
|
|
1067
|
+
const keyInfo = toImportKey({
|
|
1068
|
+
source: specifier,
|
|
1069
|
+
resolved,
|
|
1070
|
+
root: state.evalOptions.root
|
|
1071
|
+
});
|
|
1072
|
+
const override = getImportOverride(state.evalOptions.importOverrides, keyInfo.key);
|
|
1073
|
+
let finalResolved = resolved;
|
|
1074
|
+
if (override?.mock) {
|
|
1075
|
+
finalResolved = resolveMockSpecifier({
|
|
1076
|
+
mock: override.mock,
|
|
1077
|
+
importer: importerFile,
|
|
1078
|
+
root: state.evalOptions.root,
|
|
1079
|
+
stack: [importerFile]
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
const basePolicy = state.evalOptions.require === "warn-and-run" ? "warn" : "error";
|
|
1083
|
+
let policy = override?.unknown ?? (override ? "allow" : basePolicy);
|
|
1084
|
+
if (state.evalOptions.require === "off" && policy !== "error") {
|
|
1085
|
+
policy = "error";
|
|
1086
|
+
}
|
|
1087
|
+
if (policy === "error") {
|
|
1088
|
+
throw new Error([
|
|
1089
|
+
`[wyw-in-js] require() fallback reached during eval but eval.require='error'.`,
|
|
1090
|
+
``,
|
|
1091
|
+
`importer: ${importerFile}`,
|
|
1092
|
+
`source: ${specifier}`,
|
|
1093
|
+
`hint: add importOverrides or set eval.require to "warn-and-run".`
|
|
1094
|
+
].join("\n"));
|
|
1095
|
+
}
|
|
1096
|
+
if (policy === "warn") {
|
|
1097
|
+
const key = `${specifier}::${getImporterPackage(importerFile)}`;
|
|
1098
|
+
if (!warnedRequires.has(key)) {
|
|
1099
|
+
warnedRequires.add(key);
|
|
1100
|
+
sendWarn({
|
|
1101
|
+
code: "require-fallback",
|
|
1102
|
+
message: [
|
|
1103
|
+
`[wyw-in-js] Runtime require() fallback during eval`,
|
|
1104
|
+
``,
|
|
1105
|
+
`importer: ${importerFile}`,
|
|
1106
|
+
`source: ${specifier}`,
|
|
1107
|
+
`resolved: ${resolved}`,
|
|
1108
|
+
override?.mock ? `mock: ${override.mock} -> ${finalResolved}` : ``,
|
|
1109
|
+
``,
|
|
1110
|
+
`hint: use importOverrides to mock runtime-only deps and avoid eval-time requires.`
|
|
1111
|
+
].filter(Boolean).join("\n"),
|
|
1112
|
+
importer: importerFile,
|
|
1113
|
+
specifier,
|
|
1114
|
+
resolved
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
return nodeRequire(finalResolved);
|
|
1119
|
+
} finally {
|
|
1120
|
+
added.forEach((ext) => delete extensions[ext]);
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
};
|
|
1124
|
+
function createSyntheticModule(id, exportsValue, cache = true) {
|
|
1125
|
+
const exportNames = new Set(Object.keys(exportsValue));
|
|
1126
|
+
if (!exportNames.has("default")) {
|
|
1127
|
+
exportNames.add("default");
|
|
1128
|
+
}
|
|
1129
|
+
const module = new vm.SyntheticModule([...exportNames], function init() {
|
|
1130
|
+
exportNames.forEach((key) => {
|
|
1131
|
+
const value = key === "default" ? exportsValue.default : exportsValue[key];
|
|
1132
|
+
this.setExport(key, value);
|
|
1133
|
+
});
|
|
1134
|
+
}, {
|
|
1135
|
+
context: state.context,
|
|
1136
|
+
identifier: id
|
|
1137
|
+
});
|
|
1138
|
+
if (cache) {
|
|
1139
|
+
moduleCache.set(id, module);
|
|
1140
|
+
}
|
|
1141
|
+
return module;
|
|
1142
|
+
}
|
|
1143
|
+
const toSyntheticExports = (value) => {
|
|
1144
|
+
if (value && (typeof value === "object" || typeof value === "function")) {
|
|
1145
|
+
const exportsValue = {};
|
|
1146
|
+
Object.keys(value).forEach((key) => {
|
|
1147
|
+
exportsValue[key] = value[key];
|
|
1148
|
+
});
|
|
1149
|
+
exportsValue.default = Object.prototype.hasOwnProperty.call(value, "default") || Object.prototype.hasOwnProperty.call(exportsValue, "default") ? value.default : value;
|
|
1150
|
+
return exportsValue;
|
|
1151
|
+
}
|
|
1152
|
+
return { default: value };
|
|
1153
|
+
};
|
|
1154
|
+
const loadExternalModule = async (resolvedId, importer, specifier) => {
|
|
1155
|
+
const cacheId = resolvedId ?? specifier;
|
|
1156
|
+
const cached = moduleCache.get(cacheId);
|
|
1157
|
+
if (cached) return cached;
|
|
1158
|
+
const inFlight = externalInFlight.get(cacheId);
|
|
1159
|
+
if (inFlight) return inFlight;
|
|
1160
|
+
const task = (async () => {
|
|
1161
|
+
const start = Date.now();
|
|
1162
|
+
debug("external:start", {
|
|
1163
|
+
specifier,
|
|
1164
|
+
resolvedId,
|
|
1165
|
+
importer
|
|
1166
|
+
});
|
|
1167
|
+
const requireFn = createRequireFn(importer);
|
|
1168
|
+
let value;
|
|
1169
|
+
let hasValue = false;
|
|
1170
|
+
const resolvedFile = resolvedId ? stripQueryAndHash(resolvedId) : null;
|
|
1171
|
+
const importTarget = resolvedFile && path.isAbsolute(resolvedFile) ? pathToFileURL(resolvedFile).href : specifier;
|
|
1172
|
+
if (shouldPreferImport(resolvedFile)) {
|
|
1173
|
+
value = await import(importTarget);
|
|
1174
|
+
hasValue = true;
|
|
1175
|
+
}
|
|
1176
|
+
if (!hasValue) {
|
|
1177
|
+
try {
|
|
1178
|
+
value = requireFn(specifier, resolvedId ?? null);
|
|
1179
|
+
hasValue = true;
|
|
1180
|
+
} catch (error) {
|
|
1181
|
+
if (!isErrRequireEsm(error)) {
|
|
1182
|
+
throw error;
|
|
1183
|
+
}
|
|
1184
|
+
const isFileSpecifier = specifier.startsWith(".") || path.isAbsolute(specifier);
|
|
1185
|
+
const isPackageSpecifier = !isFileSpecifier && !isBuiltinSpecifier(specifier);
|
|
1186
|
+
if (resolvedId && isPackageSpecifier) {
|
|
1187
|
+
try {
|
|
1188
|
+
value = requireFn(specifier, null);
|
|
1189
|
+
hasValue = true;
|
|
1190
|
+
} catch (retryError) {
|
|
1191
|
+
if (!isErrRequireEsm(retryError)) {
|
|
1192
|
+
throw retryError;
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
if (!hasValue) {
|
|
1197
|
+
value = await import(importTarget);
|
|
1198
|
+
hasValue = true;
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
const module = createSyntheticModule(cacheId, toSyntheticExports(value));
|
|
1203
|
+
debug("external:done", {
|
|
1204
|
+
specifier,
|
|
1205
|
+
resolvedId,
|
|
1206
|
+
durationMs: Date.now() - start
|
|
1207
|
+
});
|
|
1208
|
+
return module;
|
|
1209
|
+
})();
|
|
1210
|
+
externalInFlight.set(cacheId, task);
|
|
1211
|
+
try {
|
|
1212
|
+
return await task;
|
|
1213
|
+
} finally {
|
|
1214
|
+
externalInFlight.delete(cacheId);
|
|
1215
|
+
}
|
|
1216
|
+
};
|
|
1217
|
+
let resolveModule;
|
|
1218
|
+
let loadModule;
|
|
1219
|
+
const linkModule = async (module) => {
|
|
1220
|
+
const cached = linkPromises.get(module);
|
|
1221
|
+
if (cached) return cached;
|
|
1222
|
+
if (module.status !== "unlinked") return module;
|
|
1223
|
+
const linking = (async () => {
|
|
1224
|
+
try {
|
|
1225
|
+
await module.link((specifier, referencingModule) => resolveModule(specifier, referencingModule.identifier, "import"));
|
|
1226
|
+
return module;
|
|
1227
|
+
} catch (error) {
|
|
1228
|
+
// ERR_VM_MODULE_LINK_FAILURE means a dependency is in "errored" state.
|
|
1229
|
+
// Node chains .cause through the link failure hierarchy. Walk to the
|
|
1230
|
+
// deepest cause to surface the original evaluation error (e.g. a
|
|
1231
|
+
// TypeError in user code), not intermediate "resolved to errored" hops.
|
|
1232
|
+
if (error?.code === "ERR_VM_MODULE_LINK_FAILURE") {
|
|
1233
|
+
let rootCause = error;
|
|
1234
|
+
while (rootCause.cause instanceof Error) {
|
|
1235
|
+
rootCause = rootCause.cause;
|
|
1236
|
+
}
|
|
1237
|
+
if (rootCause !== error) {
|
|
1238
|
+
const enhanced = new Error(`${error.message}\n` + ` Root cause: ${rootCause.name ?? "Error"}: ${rootCause.message}`);
|
|
1239
|
+
enhanced.cause = rootCause;
|
|
1240
|
+
throw enhanced;
|
|
1241
|
+
}
|
|
1242
|
+
}
|
|
1243
|
+
throw error;
|
|
1244
|
+
} finally {
|
|
1245
|
+
linkPromises.delete(module);
|
|
1246
|
+
}
|
|
1247
|
+
})();
|
|
1248
|
+
linkPromises.set(module, linking);
|
|
1249
|
+
return linking;
|
|
1250
|
+
};
|
|
1251
|
+
resolveModule = async (specifier, importer, kind) => {
|
|
1252
|
+
const importerId = toSourceModuleId(importer);
|
|
1253
|
+
if (process.env.WYW_DEBUG_EVAL_RESOLVE) {
|
|
1254
|
+
process.stderr.write(`[wyw-eval-runner:resolve] ${JSON.stringify({
|
|
1255
|
+
specifier,
|
|
1256
|
+
importer: importerId,
|
|
1257
|
+
kind
|
|
1258
|
+
})}\n`);
|
|
1259
|
+
}
|
|
1260
|
+
if (specifier === REACT_REFRESH_VIRTUAL_ID) {
|
|
1261
|
+
return createSyntheticModule(specifier, reactRefreshRuntime);
|
|
1262
|
+
}
|
|
1263
|
+
if (specifier.startsWith(VITE_VIRTUAL_PREFIX) || specifier.startsWith("virtual:")) {
|
|
1264
|
+
return createSyntheticModule(specifier, { default: {} });
|
|
1265
|
+
}
|
|
1266
|
+
const key = `${kind}:${importerId}:${specifier}`;
|
|
1267
|
+
const cached = resolveCache.get(key);
|
|
1268
|
+
if (cached) {
|
|
1269
|
+
if (!cached.resolvedId) {
|
|
1270
|
+
if (state.evalOptions.mode === "loose") {
|
|
1271
|
+
return createSyntheticModule(specifier, { default: undefined });
|
|
1272
|
+
}
|
|
1273
|
+
throw new Error([
|
|
1274
|
+
`[wyw-in-js] Unable to resolve "${specifier}" during evaluation.`,
|
|
1275
|
+
``,
|
|
1276
|
+
`importer: ${importerId}`,
|
|
1277
|
+
`hint: check eval.resolver/customResolver or add importOverrides for this specifier.`
|
|
1278
|
+
].join("\n"));
|
|
1279
|
+
}
|
|
1280
|
+
const treatExternal = cached.external || isBuiltinSpecifier(specifier) || isNodeModulesId(cached.resolvedId);
|
|
1281
|
+
if (treatExternal) {
|
|
1282
|
+
const normalized = normalizeResolvedId(cached.resolvedId, specifier, importerId, state.evalOptions.extensions);
|
|
1283
|
+
const externalModule = await loadExternalModule(normalized, importerId, specifier);
|
|
1284
|
+
return externalModule;
|
|
1285
|
+
}
|
|
1286
|
+
const normalized = normalizeResolvedId(cached.resolvedId, specifier, importerId, state.evalOptions.extensions);
|
|
1287
|
+
return loadModule(normalized, importerId, specifier);
|
|
1288
|
+
}
|
|
1289
|
+
const inFlight = resolveInFlight.get(key);
|
|
1290
|
+
if (inFlight) return inFlight;
|
|
1291
|
+
const task = (async () => {
|
|
1292
|
+
const resolved = await request("RESOLVE", {
|
|
1293
|
+
specifier,
|
|
1294
|
+
importerId,
|
|
1295
|
+
kind
|
|
1296
|
+
});
|
|
1297
|
+
if (resolved.error) {
|
|
1298
|
+
throw new Error(resolved.error.message);
|
|
1299
|
+
}
|
|
1300
|
+
const normalized = resolved.resolvedId ? normalizeResolvedId(resolved.resolvedId, specifier, importerId, state.evalOptions.extensions) : resolved.resolvedId;
|
|
1301
|
+
if (process.env.WYW_DEBUG_EVAL_RESOLVE) {
|
|
1302
|
+
process.stderr.write(`[wyw-eval-runner:resolved] ${JSON.stringify({
|
|
1303
|
+
specifier,
|
|
1304
|
+
importer: importerId,
|
|
1305
|
+
resolved: resolved.resolvedId ?? null,
|
|
1306
|
+
normalized: normalized ?? null,
|
|
1307
|
+
external: Boolean(resolved.external)
|
|
1308
|
+
})}\n`);
|
|
1309
|
+
}
|
|
1310
|
+
resolveCache.set(key, {
|
|
1311
|
+
resolvedId: normalized,
|
|
1312
|
+
external: Boolean(resolved.external)
|
|
1313
|
+
});
|
|
1314
|
+
if (!normalized) {
|
|
1315
|
+
if (state.evalOptions.mode === "loose") {
|
|
1316
|
+
return createSyntheticModule(specifier, { default: undefined });
|
|
1317
|
+
}
|
|
1318
|
+
throw new Error([
|
|
1319
|
+
`[wyw-in-js] Unable to resolve "${specifier}" during evaluation.`,
|
|
1320
|
+
``,
|
|
1321
|
+
`importer: ${importerId}`,
|
|
1322
|
+
`hint: check eval.resolver/customResolver or add importOverrides for this specifier.`
|
|
1323
|
+
].join("\n"));
|
|
1324
|
+
}
|
|
1325
|
+
const treatExternal = resolved.external || isBuiltinSpecifier(specifier) || isNodeModulesId(normalized);
|
|
1326
|
+
if (treatExternal) {
|
|
1327
|
+
return loadExternalModule(normalized, importerId, specifier);
|
|
1328
|
+
}
|
|
1329
|
+
return loadModule(normalized, importerId, specifier);
|
|
1330
|
+
})();
|
|
1331
|
+
resolveInFlight.set(key, task);
|
|
1332
|
+
try {
|
|
1333
|
+
return await task;
|
|
1334
|
+
} finally {
|
|
1335
|
+
resolveInFlight.delete(key);
|
|
1336
|
+
}
|
|
1337
|
+
};
|
|
1338
|
+
loadModule = async (id, importer, requestSpec) => {
|
|
1339
|
+
let cached = moduleCache.get(id);
|
|
1340
|
+
const inFlight = loadInFlight.get(id);
|
|
1341
|
+
if (inFlight) {
|
|
1342
|
+
await inFlight;
|
|
1343
|
+
cached = moduleCache.get(id);
|
|
1344
|
+
}
|
|
1345
|
+
const task = (async () => {
|
|
1346
|
+
const loadStart = Date.now();
|
|
1347
|
+
const loaded = await request("LOAD", {
|
|
1348
|
+
id,
|
|
1349
|
+
importerId: importer,
|
|
1350
|
+
request: requestSpec ?? null
|
|
1351
|
+
});
|
|
1352
|
+
debug("load:done", {
|
|
1353
|
+
id,
|
|
1354
|
+
importer,
|
|
1355
|
+
durationMs: Date.now() - loadStart
|
|
1356
|
+
});
|
|
1357
|
+
if (loaded.error) {
|
|
1358
|
+
throw new Error(loaded.error.message);
|
|
1359
|
+
}
|
|
1360
|
+
if (loaded.only) {
|
|
1361
|
+
const current = moduleOnly.get(id) ?? [];
|
|
1362
|
+
moduleOnly.set(id, mergeOnly(current, loaded.only));
|
|
1363
|
+
}
|
|
1364
|
+
if (loaded.exports) {
|
|
1365
|
+
// Serialized exports are a narrow slice — only the keys the importer
|
|
1366
|
+
// requested. If we have a fully evaluated module (in moduleCache or as
|
|
1367
|
+
// a variant), prefer it: its namespace has ALL exports, so any consumer
|
|
1368
|
+
// can link against it without "does not provide export" errors.
|
|
1369
|
+
//
|
|
1370
|
+
// An evaluated variant is only safe to reuse when its namespace covers
|
|
1371
|
+
// the serialized key set. A narrow variant that was evaluated first may
|
|
1372
|
+
// lack exports that a wider consumer needs (the 4df6e915 race).
|
|
1373
|
+
const requiredKeys = Object.keys(loaded.exports);
|
|
1374
|
+
const coversKeys = (mod) => {
|
|
1375
|
+
const ns = mod.namespace;
|
|
1376
|
+
return requiredKeys.every((k) => k in ns);
|
|
1377
|
+
};
|
|
1378
|
+
let evaluated = cached && cached.status === "evaluated" && coversKeys(cached) ? cached : undefined;
|
|
1379
|
+
if (!evaluated) {
|
|
1380
|
+
const variants = moduleVariants.get(id);
|
|
1381
|
+
if (variants) {
|
|
1382
|
+
for (const variant of variants.values()) {
|
|
1383
|
+
if (variant.status === "evaluated" && coversKeys(variant)) {
|
|
1384
|
+
evaluated = variant;
|
|
1385
|
+
break;
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
}
|
|
1390
|
+
if (evaluated) {
|
|
1391
|
+
return evaluated;
|
|
1392
|
+
}
|
|
1393
|
+
// Reuse a previously created SyntheticModule for this exact serialized set
|
|
1394
|
+
if (loaded.hash) {
|
|
1395
|
+
const existing = getModuleVariant(id, loaded.hash);
|
|
1396
|
+
if (existing) {
|
|
1397
|
+
return existing;
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
const exportsValue = {};
|
|
1401
|
+
Object.entries(loaded.exports).forEach(([key, serialized]) => {
|
|
1402
|
+
exportsValue[key] = deserializeValue(serialized);
|
|
1403
|
+
});
|
|
1404
|
+
const module = createSyntheticModule(id, exportsValue, false);
|
|
1405
|
+
if (loaded.hash) {
|
|
1406
|
+
setModuleVariant(id, loaded.hash, module);
|
|
1407
|
+
}
|
|
1408
|
+
return module;
|
|
1409
|
+
}
|
|
1410
|
+
const usePrimaryCache = isFullModuleLoad(loaded);
|
|
1411
|
+
if (usePrimaryCache) {
|
|
1412
|
+
if (cached && loaded.hash && moduleHashes.get(id) === loaded.hash) {
|
|
1413
|
+
return cached;
|
|
1414
|
+
}
|
|
1415
|
+
} else if (loaded.hash) {
|
|
1416
|
+
const variant = getModuleVariant(id, loaded.hash);
|
|
1417
|
+
if (variant) {
|
|
1418
|
+
return variant;
|
|
1419
|
+
}
|
|
1420
|
+
}
|
|
1421
|
+
// The broker only ships empty `code` when it expects the runner to reuse
|
|
1422
|
+
// a cached module via the hash-match short-circuit above. Reaching this
|
|
1423
|
+
// point with no code means the broker's "what runner has" mirror is out
|
|
1424
|
+
// of sync with our actual moduleCache/moduleVariants — fail loudly rather
|
|
1425
|
+
// than feeding empty source into vm.SourceTextModule.
|
|
1426
|
+
if (loaded.code == null || loaded.code === "") {
|
|
1427
|
+
throw new Error(`[wyw-in-js] LoadResult for ${id} has empty code but no cached module ` + `matched hash ${loaded.hash ?? "(none)"}. ` + `This indicates a broker/runner cache desync.`);
|
|
1428
|
+
}
|
|
1429
|
+
if (usePrimaryCache) {
|
|
1430
|
+
resetSingleModuleState(id, cached);
|
|
1431
|
+
}
|
|
1432
|
+
const module = new vm.SourceTextModule(`${buildPreamble(id)}${loaded.code ?? ""}`, {
|
|
1433
|
+
context: state.context,
|
|
1434
|
+
identifier: toVersionedModuleIdentifier(id, loaded.hash),
|
|
1435
|
+
initializeImportMeta(meta, targetModule) {
|
|
1436
|
+
const identifier = typeof targetModule.identifier === "string" ? targetModule.identifier : id;
|
|
1437
|
+
const fileId = stripQueryAndHash(identifier);
|
|
1438
|
+
// eslint-disable-next-line no-param-reassign
|
|
1439
|
+
meta.url = path.isAbsolute(fileId) ? pathToFileURL(fileId).href : fileId;
|
|
1440
|
+
},
|
|
1441
|
+
importModuleDynamically(specifier, referencingModule) {
|
|
1442
|
+
return resolveModule(specifier, referencingModule.identifier, "dynamic-import");
|
|
1443
|
+
}
|
|
1444
|
+
});
|
|
1445
|
+
if (usePrimaryCache) {
|
|
1446
|
+
moduleCache.set(id, module);
|
|
1447
|
+
if (loaded.hash) {
|
|
1448
|
+
moduleHashes.set(id, loaded.hash);
|
|
1449
|
+
}
|
|
1450
|
+
} else if (loaded.hash) {
|
|
1451
|
+
setModuleVariant(id, loaded.hash, module);
|
|
1452
|
+
}
|
|
1453
|
+
return module;
|
|
1454
|
+
})();
|
|
1455
|
+
loadInFlight.set(id, task);
|
|
1456
|
+
try {
|
|
1457
|
+
return await task;
|
|
1458
|
+
} finally {
|
|
1459
|
+
loadInFlight.delete(id);
|
|
1460
|
+
}
|
|
1461
|
+
};
|
|
1462
|
+
const createDynamicImportFn = (importer) => {
|
|
1463
|
+
return async (specifier) => {
|
|
1464
|
+
if (typeof specifier !== "string") {
|
|
1465
|
+
sendWarn({
|
|
1466
|
+
code: "eval-error",
|
|
1467
|
+
message: "[wyw-in-js] Dynamic import with non-string specifier during eval.",
|
|
1468
|
+
importer
|
|
1469
|
+
});
|
|
1470
|
+
if (state.evalOptions.mode === "strict") {
|
|
1471
|
+
throw new Error(`[wyw-in-js] Dynamic import with non-string specifier is not supported during eval.\n` + `importer: ${importer}\n` + `hint: make it a string literal or mock the import via importOverrides.`);
|
|
1472
|
+
}
|
|
1473
|
+
return createSyntheticModule(`dynamic:${String(specifier)}`, { default: undefined });
|
|
1474
|
+
}
|
|
1475
|
+
sendWarn({
|
|
1476
|
+
code: "dynamic-import",
|
|
1477
|
+
message: `[wyw-in-js] Dynamic import executed during eval: ${specifier}`,
|
|
1478
|
+
importer,
|
|
1479
|
+
specifier
|
|
1480
|
+
});
|
|
1481
|
+
const resolved = await resolveModule(specifier, importer, "dynamic-import");
|
|
1482
|
+
await linkModule(resolved);
|
|
1483
|
+
await resolved.evaluate();
|
|
1484
|
+
return resolved;
|
|
1485
|
+
};
|
|
1486
|
+
};
|
|
1487
|
+
const getModuleData = (id) => {
|
|
1488
|
+
const cached = moduleData.get(id);
|
|
1489
|
+
if (cached) return cached;
|
|
1490
|
+
const filename = stripQueryAndHash(id);
|
|
1491
|
+
const exportsValue = {};
|
|
1492
|
+
const moduleObj = { exports: exportsValue };
|
|
1493
|
+
const data = {
|
|
1494
|
+
exports: exportsValue,
|
|
1495
|
+
module: moduleObj,
|
|
1496
|
+
require: createRequireFn(id),
|
|
1497
|
+
filename,
|
|
1498
|
+
dirname: path.dirname(filename),
|
|
1499
|
+
dynamicImport: createDynamicImportFn(id)
|
|
1500
|
+
};
|
|
1501
|
+
moduleData.set(id, data);
|
|
1502
|
+
return data;
|
|
1503
|
+
};
|
|
1504
|
+
const resolveExportValue = (source, key) => {
|
|
1505
|
+
if (key === "default") {
|
|
1506
|
+
if (source && typeof source === "object" && "default" in source) {
|
|
1507
|
+
return source.default;
|
|
1508
|
+
}
|
|
1509
|
+
return source;
|
|
1510
|
+
}
|
|
1511
|
+
if (source && (typeof source === "object" || typeof source === "function")) {
|
|
1512
|
+
if (key in source) {
|
|
1513
|
+
return source[key];
|
|
1514
|
+
}
|
|
1515
|
+
if (source.default && typeof source.default === "object" && key in source.default) {
|
|
1516
|
+
return source.default[key];
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
return undefined;
|
|
1520
|
+
};
|
|
1521
|
+
const collectModuleExports = () => {
|
|
1522
|
+
const exportsByModule = {};
|
|
1523
|
+
moduleOnly.forEach((only, id) => {
|
|
1524
|
+
if (!only || only.length === 0) return;
|
|
1525
|
+
const module = moduleCache.get(id) ?? moduleLastVariant.get(id);
|
|
1526
|
+
const data = moduleData.get(id);
|
|
1527
|
+
if (!module || !data) return;
|
|
1528
|
+
// The broker already has the serialized exports for this exact variant
|
|
1529
|
+
// from a prior eval session. Re-serializing here just wastes CPU on the
|
|
1530
|
+
// runner side and bloats the EVAL_RESULT payload. Same variant identifier
|
|
1531
|
+
// ⇒ same namespace ⇒ no change to send.
|
|
1532
|
+
const moduleIdentifier = typeof module.identifier === "string" ? module.identifier : id;
|
|
1533
|
+
if (sentNamespaceIdentifiers.get(id) === moduleIdentifier) {
|
|
1534
|
+
return;
|
|
1535
|
+
}
|
|
1536
|
+
// .namespace is only safe on fully evaluated modules. Modules that
|
|
1537
|
+
// errored or were never evaluated (stale from a prior failed session
|
|
1538
|
+
// with reuseModules) have TDZ bindings that crash Object.keys().
|
|
1539
|
+
if (module.status !== "evaluated") {
|
|
1540
|
+
sendWarn({
|
|
1541
|
+
code: "eval-stale-module",
|
|
1542
|
+
message: `[wyw-in-js] Skipping export collection for ${id}: ` + `module status is "${module.status}" (expected "evaluated"). ` + `Cached exports for this module may be stale.`
|
|
1543
|
+
});
|
|
1544
|
+
return;
|
|
1545
|
+
}
|
|
1546
|
+
const { namespace } = module;
|
|
1547
|
+
const hasNamespace = namespace && typeof namespace === "object" && Object.keys(namespace).length;
|
|
1548
|
+
const source = hasNamespace ? namespace : data.module.exports;
|
|
1549
|
+
const discoveredKeys = Object.keys(source ?? {}).filter((key) => key !== "__wywPreval" && key !== "side-effect" && key !== "*");
|
|
1550
|
+
const requestedKeys = only.filter((key) => key !== "__wywPreval" && key !== "side-effect" && key !== "*");
|
|
1551
|
+
const keys = Array.from(new Set([...requestedKeys, ...discoveredKeys]));
|
|
1552
|
+
if (keys.length === 0) return;
|
|
1553
|
+
const serialized = {};
|
|
1554
|
+
keys.forEach((key) => {
|
|
1555
|
+
const value = resolveExportValue(source, key);
|
|
1556
|
+
try {
|
|
1557
|
+
serialized[key] = serializeValue(value, {
|
|
1558
|
+
rootLabel: "module exports",
|
|
1559
|
+
path: [id, key]
|
|
1560
|
+
});
|
|
1561
|
+
} catch {}
|
|
1562
|
+
});
|
|
1563
|
+
if (Object.keys(serialized).length) {
|
|
1564
|
+
exportsByModule[id] = serialized;
|
|
1565
|
+
sentNamespaceIdentifiers.set(id, moduleIdentifier);
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
return exportsByModule;
|
|
1569
|
+
};
|
|
1570
|
+
async function evaluateEntrypoint(id) {
|
|
1571
|
+
const evalStart = Date.now();
|
|
1572
|
+
debug("eval:start", id);
|
|
1573
|
+
const module = await loadModule(id, id, id);
|
|
1574
|
+
debug("eval:loaded", {
|
|
1575
|
+
id,
|
|
1576
|
+
durationMs: Date.now() - evalStart
|
|
1577
|
+
});
|
|
1578
|
+
await linkModule(module);
|
|
1579
|
+
debug("eval:linked", {
|
|
1580
|
+
id,
|
|
1581
|
+
durationMs: Date.now() - evalStart
|
|
1582
|
+
});
|
|
1583
|
+
await module.evaluate();
|
|
1584
|
+
debug("eval:evaluated", {
|
|
1585
|
+
id,
|
|
1586
|
+
durationMs: Date.now() - evalStart
|
|
1587
|
+
});
|
|
1588
|
+
const data = getModuleData(id);
|
|
1589
|
+
const exportsValue = data.module.exports;
|
|
1590
|
+
const hasPrevalExport = exportsValue && typeof exportsValue === "object" && "__wywPreval" in exportsValue;
|
|
1591
|
+
const { namespace } = module;
|
|
1592
|
+
const hasPrevalNamespace = namespace && typeof namespace === "object" && "__wywPreval" in namespace;
|
|
1593
|
+
const modules = collectModuleExports();
|
|
1594
|
+
if (!hasPrevalExport && !hasPrevalNamespace) {
|
|
1595
|
+
return {
|
|
1596
|
+
values: null,
|
|
1597
|
+
modules
|
|
1598
|
+
};
|
|
1599
|
+
}
|
|
1600
|
+
const preval = hasPrevalExport ? exportsValue.__wywPreval : namespace.__wywPreval;
|
|
1601
|
+
if (!preval || typeof preval !== "object") {
|
|
1602
|
+
return {
|
|
1603
|
+
values: null,
|
|
1604
|
+
modules
|
|
1605
|
+
};
|
|
1606
|
+
}
|
|
1607
|
+
const values = {};
|
|
1608
|
+
Object.entries(preval).forEach(([key, lazy]) => {
|
|
1609
|
+
let value;
|
|
1610
|
+
try {
|
|
1611
|
+
value = typeof lazy === "function" ? lazy() : lazy;
|
|
1612
|
+
} catch (error) {
|
|
1613
|
+
value = error;
|
|
1614
|
+
}
|
|
1615
|
+
values[key] = serializeValue(value, {
|
|
1616
|
+
allowFunctions: true,
|
|
1617
|
+
allowSymbols: true,
|
|
1618
|
+
rootLabel: "__wywPreval",
|
|
1619
|
+
path: [key]
|
|
1620
|
+
});
|
|
1621
|
+
});
|
|
1622
|
+
return {
|
|
1623
|
+
values,
|
|
1624
|
+
modules
|
|
1625
|
+
};
|
|
1626
|
+
}
|
|
1627
|
+
const handleMessage = async (message) => {
|
|
1628
|
+
switch (message.type) {
|
|
1629
|
+
case "INIT": {
|
|
1630
|
+
try {
|
|
1631
|
+
const initStart = Date.now();
|
|
1632
|
+
debug("init:start", message.payload.entrypoint ?? "eval-runner");
|
|
1633
|
+
const encodedGlobals = message.payload.evalOptions.globals ?? {};
|
|
1634
|
+
const nextGlobalsSignature = JSON.stringify(canonicalizeForSignature(encodedGlobals));
|
|
1635
|
+
const nextFeatures = message.payload.features ?? {};
|
|
1636
|
+
const nextEntrypoint = message.payload.entrypoint ?? "eval-runner";
|
|
1637
|
+
const nextHappyDomEnabled = isFeatureEnabled(nextFeatures, "happyDOM", nextEntrypoint);
|
|
1638
|
+
const globalsChanged = state.globalsSignature !== null && state.globalsSignature !== nextGlobalsSignature;
|
|
1639
|
+
const nextGlobals = !globalsChanged && state.globalsSignature !== null ? state.evalOptions.globals : decodeGlobals(encodedGlobals);
|
|
1640
|
+
const nextEvalOptions = {
|
|
1641
|
+
...state.evalOptions,
|
|
1642
|
+
...message.payload.evalOptions,
|
|
1643
|
+
globals: nextGlobals
|
|
1644
|
+
};
|
|
1645
|
+
const canReuseContext = state.context && state.happyDomEnabled === nextHappyDomEnabled && !globalsChanged;
|
|
1646
|
+
const reuseModules = Boolean(message.payload.reuseModules);
|
|
1647
|
+
if (canReuseContext) {
|
|
1648
|
+
const modulesReset = !reuseModules;
|
|
1649
|
+
if (modulesReset) {
|
|
1650
|
+
resetModuleState();
|
|
1651
|
+
} else {
|
|
1652
|
+
// Clear resolution caches between sessions even when reusing modules.
|
|
1653
|
+
// The broker rebuilds onlyByModule from scratch each session (cleared
|
|
1654
|
+
// in evaluate()). If the runner's resolveCache persists, RESOLVE
|
|
1655
|
+
// requests for previously-seen (importer, specifier) pairs are
|
|
1656
|
+
// skipped, preventing the broker from learning what exports are
|
|
1657
|
+
// needed. This can cause a barrel module to be served with a stale
|
|
1658
|
+
// `only` set that's missing exports a consumer actually imports,
|
|
1659
|
+
// leading to "does not provide an export named 'X'" link errors.
|
|
1660
|
+
resolveCache.clear();
|
|
1661
|
+
resolveInFlight.clear();
|
|
1662
|
+
loadInFlight.clear();
|
|
1663
|
+
}
|
|
1664
|
+
state.evalOptions = nextEvalOptions;
|
|
1665
|
+
state.features = nextFeatures;
|
|
1666
|
+
state.entrypoint = nextEntrypoint;
|
|
1667
|
+
Object.assign(state.context, {
|
|
1668
|
+
__dirname: path.dirname(nextEntrypoint),
|
|
1669
|
+
__filename: nextEntrypoint,
|
|
1670
|
+
...nextEvalOptions.globals,
|
|
1671
|
+
__wyw_getModule: (moduleId) => getModuleData(moduleId)
|
|
1672
|
+
});
|
|
1673
|
+
state.globalsSignature = nextGlobalsSignature;
|
|
1674
|
+
debug("init:reuse", Date.now() - initStart);
|
|
1675
|
+
sendMessage({
|
|
1676
|
+
type: "INIT_ACK",
|
|
1677
|
+
id: message.id,
|
|
1678
|
+
modulesReset
|
|
1679
|
+
});
|
|
1680
|
+
break;
|
|
1681
|
+
}
|
|
1682
|
+
resetEvaluationState();
|
|
1683
|
+
state.evalOptions = nextEvalOptions;
|
|
1684
|
+
state.features = nextFeatures;
|
|
1685
|
+
state.entrypoint = nextEntrypoint;
|
|
1686
|
+
debug("init:globals", Date.now() - initStart);
|
|
1687
|
+
const windowStart = Date.now();
|
|
1688
|
+
const { context, teardown } = await createVmContext(state.entrypoint, state.features, {
|
|
1689
|
+
...state.evalOptions.globals,
|
|
1690
|
+
__wyw_getModule: (moduleId) => getModuleData(moduleId)
|
|
1691
|
+
});
|
|
1692
|
+
debug("init:context", Date.now() - windowStart);
|
|
1693
|
+
state.context = context;
|
|
1694
|
+
state.teardown = teardown;
|
|
1695
|
+
state.happyDomEnabled = nextHappyDomEnabled;
|
|
1696
|
+
state.globalsSignature = nextGlobalsSignature;
|
|
1697
|
+
// Full context rebuild ⇒ moduleCache was cleared by resetEvaluationState.
|
|
1698
|
+
sendMessage({
|
|
1699
|
+
type: "INIT_ACK",
|
|
1700
|
+
id: message.id,
|
|
1701
|
+
modulesReset: true
|
|
1702
|
+
});
|
|
1703
|
+
debug("init:done", Date.now() - initStart);
|
|
1704
|
+
} catch (error) {
|
|
1705
|
+
sendMessage({
|
|
1706
|
+
type: "INIT_ACK",
|
|
1707
|
+
id: message.id,
|
|
1708
|
+
error: serializeError(error)
|
|
1709
|
+
});
|
|
1710
|
+
}
|
|
1711
|
+
break;
|
|
1712
|
+
}
|
|
1713
|
+
case "EVAL": {
|
|
1714
|
+
try {
|
|
1715
|
+
const { values, modules } = await evaluateEntrypoint(message.payload.id);
|
|
1716
|
+
sendMessage({
|
|
1717
|
+
type: "EVAL_RESULT",
|
|
1718
|
+
id: message.id,
|
|
1719
|
+
payload: {
|
|
1720
|
+
values,
|
|
1721
|
+
modules
|
|
1722
|
+
}
|
|
1723
|
+
});
|
|
1724
|
+
} catch (error) {
|
|
1725
|
+
sendMessage({
|
|
1726
|
+
type: "EVAL_RESULT",
|
|
1727
|
+
id: message.id,
|
|
1728
|
+
payload: { values: null },
|
|
1729
|
+
error: serializeError(error)
|
|
1730
|
+
});
|
|
1731
|
+
}
|
|
1732
|
+
break;
|
|
1733
|
+
}
|
|
1734
|
+
case "RESOLVE_RESULT": {
|
|
1735
|
+
resolvePending(message.id, message.payload);
|
|
1736
|
+
break;
|
|
1737
|
+
}
|
|
1738
|
+
case "LOAD_RESULT": {
|
|
1739
|
+
handleLoadResult(message.id, message.payload);
|
|
1740
|
+
break;
|
|
1741
|
+
}
|
|
1742
|
+
default: break;
|
|
1743
|
+
}
|
|
1744
|
+
};
|
|
1745
|
+
let buffer = "";
|
|
1746
|
+
process.stdin.setEncoding("utf8");
|
|
1747
|
+
process.stdin.resume();
|
|
1748
|
+
process.stdin.on("data", (chunk) => {
|
|
1749
|
+
buffer += chunk;
|
|
1750
|
+
const lines = buffer.split("\n");
|
|
1751
|
+
buffer = lines.pop() ?? "";
|
|
1752
|
+
lines.forEach((line) => {
|
|
1753
|
+
if (!line.trim()) return;
|
|
1754
|
+
const message = JSON.parse(line);
|
|
1755
|
+
handleMessage(message);
|
|
1756
|
+
});
|
|
1757
|
+
});
|
|
1758
|
+
process.stdin.on("close", shutdown);
|
|
1759
|
+
//# sourceMappingURL=runner.js.map
|