@wyw-in-js/transform 1.0.6 → 1.0.8

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.
Files changed (98) hide show
  1. package/esm/cache.js +160 -12
  2. package/esm/cache.js.map +1 -1
  3. package/esm/debug/fileReporter.js.map +1 -1
  4. package/esm/module.js +59 -5
  5. package/esm/module.js.map +1 -1
  6. package/esm/plugins/shaker.js +152 -13
  7. package/esm/plugins/shaker.js.map +1 -1
  8. package/esm/shaker.js +51 -23
  9. package/esm/shaker.js.map +1 -1
  10. package/esm/transform/BaseEntrypoint.js +3 -1
  11. package/esm/transform/BaseEntrypoint.js.map +1 -1
  12. package/esm/transform/Entrypoint.js +68 -20
  13. package/esm/transform/Entrypoint.js.map +1 -1
  14. package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
  15. package/esm/transform/actions/BaseAction.js +2 -1
  16. package/esm/transform/actions/BaseAction.js.map +1 -1
  17. package/esm/transform/actions/actionRunner.js +2 -2
  18. package/esm/transform/actions/actionRunner.js.map +1 -1
  19. package/esm/transform/barrelManifest.js +291 -0
  20. package/esm/transform/barrelManifest.js.map +1 -0
  21. package/esm/transform/generators/getExports.js +5 -0
  22. package/esm/transform/generators/getExports.js.map +1 -1
  23. package/esm/transform/generators/processEntrypoint.js +31 -1
  24. package/esm/transform/generators/processEntrypoint.js.map +1 -1
  25. package/esm/transform/generators/resolveImports.js +29 -5
  26. package/esm/transform/generators/resolveImports.js.map +1 -1
  27. package/esm/transform/generators/rewriteBarrelImports.js +733 -0
  28. package/esm/transform/generators/rewriteBarrelImports.js.map +1 -0
  29. package/esm/transform/generators/transform.js +154 -21
  30. package/esm/transform/generators/transform.js.map +1 -1
  31. package/esm/transform/types.js.map +1 -1
  32. package/esm/transform.js +45 -23
  33. package/esm/transform.js.map +1 -1
  34. package/esm/utils/collectTemplateDependencies.js +9 -0
  35. package/esm/utils/collectTemplateDependencies.js.map +1 -1
  36. package/lib/cache.js +163 -12
  37. package/lib/cache.js.map +1 -1
  38. package/lib/debug/fileReporter.js.map +1 -1
  39. package/lib/module.js +61 -7
  40. package/lib/module.js.map +1 -1
  41. package/lib/plugins/shaker.js +152 -13
  42. package/lib/plugins/shaker.js.map +1 -1
  43. package/lib/shaker.js +58 -26
  44. package/lib/shaker.js.map +1 -1
  45. package/lib/transform/BaseEntrypoint.js +3 -1
  46. package/lib/transform/BaseEntrypoint.js.map +1 -1
  47. package/lib/transform/Entrypoint.js +69 -20
  48. package/lib/transform/Entrypoint.js.map +1 -1
  49. package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
  50. package/lib/transform/actions/BaseAction.js +2 -1
  51. package/lib/transform/actions/BaseAction.js.map +1 -1
  52. package/lib/transform/actions/actionRunner.js +2 -2
  53. package/lib/transform/actions/actionRunner.js.map +1 -1
  54. package/lib/transform/barrelManifest.js +300 -0
  55. package/lib/transform/barrelManifest.js.map +1 -0
  56. package/lib/transform/generators/getExports.js +5 -0
  57. package/lib/transform/generators/getExports.js.map +1 -1
  58. package/lib/transform/generators/processEntrypoint.js +31 -1
  59. package/lib/transform/generators/processEntrypoint.js.map +1 -1
  60. package/lib/transform/generators/resolveImports.js +29 -5
  61. package/lib/transform/generators/resolveImports.js.map +1 -1
  62. package/lib/transform/generators/rewriteBarrelImports.js +743 -0
  63. package/lib/transform/generators/rewriteBarrelImports.js.map +1 -0
  64. package/lib/transform/generators/transform.js +158 -22
  65. package/lib/transform/generators/transform.js.map +1 -1
  66. package/lib/transform/types.js.map +1 -1
  67. package/lib/transform.js +45 -23
  68. package/lib/transform.js.map +1 -1
  69. package/lib/utils/collectTemplateDependencies.js +9 -0
  70. package/lib/utils/collectTemplateDependencies.js.map +1 -1
  71. package/package.json +8 -4
  72. package/types/cache.d.ts +23 -2
  73. package/types/cache.js +170 -10
  74. package/types/debug/fileReporter.d.ts +1 -0
  75. package/types/module.d.ts +3 -0
  76. package/types/module.js +65 -5
  77. package/types/plugins/shaker.js +161 -16
  78. package/types/shaker.d.ts +10 -1
  79. package/types/shaker.js +56 -28
  80. package/types/transform/BaseEntrypoint.d.ts +3 -1
  81. package/types/transform/BaseEntrypoint.js +5 -1
  82. package/types/transform/Entrypoint.d.ts +10 -1
  83. package/types/transform/Entrypoint.js +81 -23
  84. package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
  85. package/types/transform/actions/BaseAction.d.ts +2 -1
  86. package/types/transform/actions/BaseAction.js +3 -1
  87. package/types/transform/actions/actionRunner.js +2 -2
  88. package/types/transform/barrelManifest.d.ts +42 -0
  89. package/types/transform/barrelManifest.js +300 -0
  90. package/types/transform/generators/getExports.js +5 -0
  91. package/types/transform/generators/processEntrypoint.js +29 -1
  92. package/types/transform/generators/resolveImports.js +29 -5
  93. package/types/transform/generators/rewriteBarrelImports.d.ts +15 -0
  94. package/types/transform/generators/rewriteBarrelImports.js +815 -0
  95. package/types/transform/generators/transform.js +148 -19
  96. package/types/transform/types.d.ts +3 -0
  97. package/types/transform.js +47 -23
  98. package/types/utils/collectTemplateDependencies.js +9 -0
@@ -1 +1 @@
1
- {"version":3,"file":"transform.js","names":["_shared","require","_loadWywOptions","_cache","_Entrypoint","_actionRunner","_generators","_resolveImports","_withDefaultServices","memoizedSyncResolve","WeakMap","memoizedAsyncResolve","transformSync","partialServices","originalCode","syncResolve","customHandlers","options","pluginOptions","loadWywOptions","services","withDefaultServices","isFeatureEnabled","features","filename","cache","TransformCacheCollection","entrypoint","Entrypoint","createRoot","ignored","code","sourceMap","inputSourceMap","workflowAction","createAction","undefined","has","set","resolveImports","syncResolveImports","call","result","syncActionRunner","baseHandlers","get","log","name","err","console","error","transform","asyncResolve","asyncResolveImports","asyncActionRunner"],"sources":["../src/transform.ts"],"sourcesContent":["/**\n * This file exposes sync and async transform functions that:\n * - parse the passed code to AST\n * - builds a dependency graph for the file\n * - shakes each dependency and removes unused code\n * - runs generated code in a sandbox\n * - collects artifacts\n * - returns transformed code (without WYW template literals), generated CSS, source maps and babel metadata from transform step.\n */\n\nimport { isFeatureEnabled } from '@wyw-in-js/shared';\n\nimport type { PartialOptions } from './transform/helpers/loadWywOptions';\nimport { loadWywOptions } from './transform/helpers/loadWywOptions';\nimport { TransformCacheCollection } from './cache';\nimport { Entrypoint } from './transform/Entrypoint';\nimport {\n asyncActionRunner,\n syncActionRunner,\n} from './transform/actions/actionRunner';\nimport { baseHandlers } from './transform/generators';\nimport {\n asyncResolveImports,\n syncResolveImports,\n} from './transform/generators/resolveImports';\nimport { withDefaultServices } from './transform/helpers/withDefaultServices';\nimport type {\n Handler,\n Handlers,\n IResolveImportsAction,\n Services,\n} from './transform/types';\nimport type { Result } from './types';\n\ntype PartialServices = Partial<Omit<Services, 'options'>> & {\n options: Omit<Services['options'], 'pluginOptions'> & {\n pluginOptions?: PartialOptions;\n };\n};\n\ntype AllHandlers<TMode extends 'async' | 'sync'> = Handlers<TMode>;\n\nconst memoizedSyncResolve = new WeakMap<\n (what: string, importer: string, stack: string[]) => string | null,\n Handler<'sync', IResolveImportsAction>\n>();\n\nconst memoizedAsyncResolve = new WeakMap<\n (what: string, importer: string, stack: string[]) => Promise<string | null>,\n Handler<'async' | 'sync', IResolveImportsAction>\n>();\n\nexport function transformSync(\n partialServices: PartialServices,\n originalCode: string,\n syncResolve: (what: string, importer: string, stack: string[]) => string,\n customHandlers: Partial<AllHandlers<'sync'>> = {}\n): Result {\n const { options } = partialServices;\n const pluginOptions = loadWywOptions(options.pluginOptions);\n const services = withDefaultServices({\n ...partialServices,\n options: {\n ...options,\n pluginOptions,\n },\n });\n\n if (\n !isFeatureEnabled(pluginOptions.features, 'globalCache', options.filename)\n ) {\n // If global cache is disabled, we need to create a new cache for each file\n services.cache = new TransformCacheCollection();\n }\n\n const entrypoint = Entrypoint.createRoot(\n services,\n options.filename,\n ['__wywPreval'],\n originalCode\n );\n\n if (entrypoint.ignored) {\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n const workflowAction = entrypoint.createAction('workflow', undefined);\n\n if (!memoizedSyncResolve.has(syncResolve)) {\n memoizedSyncResolve.set(\n syncResolve,\n function resolveImports(this: IResolveImportsAction) {\n return syncResolveImports.call(this, syncResolve);\n }\n );\n }\n\n try {\n const result = syncActionRunner(workflowAction, {\n ...baseHandlers,\n ...customHandlers,\n resolveImports: memoizedSyncResolve.get(syncResolve)!,\n });\n\n entrypoint.log('%s is ready', entrypoint.name);\n\n return result;\n } catch (err) {\n entrypoint.log('Unhandled error %O', err);\n\n if (\n isFeatureEnabled(pluginOptions.features, 'softErrors', options.filename)\n ) {\n // eslint-disable-next-line no-console\n console.error(`Error during transform of ${entrypoint.name}:`, err);\n\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n throw err;\n }\n}\n\nexport async function transform(\n partialServices: PartialServices,\n originalCode: string,\n asyncResolve: (\n what: string,\n importer: string,\n stack: string[]\n ) => Promise<string | null>,\n customHandlers: Partial<AllHandlers<'sync'>> = {}\n): Promise<Result> {\n const { options } = partialServices;\n const pluginOptions = loadWywOptions(options.pluginOptions);\n const services = withDefaultServices({\n ...partialServices,\n options: {\n ...options,\n pluginOptions,\n },\n });\n\n if (\n !isFeatureEnabled(pluginOptions.features, 'globalCache', options.filename)\n ) {\n // If global cache is disabled, we need to create a new cache for each file\n services.cache = new TransformCacheCollection();\n }\n\n /*\n * This method can be run simultaneously for multiple files.\n * A shared cache is accessible for all runs, but each run has its own queue\n * to maintain the correct processing order. The cache stores the outcome\n * of tree-shaking, and if the result is already stored in the cache\n * but the \"only\" option has changed, the file will be re-processed using\n * the combined \"only\" option.\n */\n const entrypoint = Entrypoint.createRoot(\n services,\n options.filename,\n ['__wywPreval'],\n originalCode\n );\n\n if (entrypoint.ignored) {\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n const workflowAction = entrypoint.createAction('workflow', undefined);\n\n if (!memoizedAsyncResolve.has(asyncResolve)) {\n const resolveImports = function resolveImports(\n this: IResolveImportsAction\n ) {\n return asyncResolveImports.call(this, asyncResolve);\n };\n\n memoizedAsyncResolve.set(asyncResolve, resolveImports);\n }\n\n try {\n const result = await asyncActionRunner(workflowAction, {\n ...baseHandlers,\n ...customHandlers,\n resolveImports: memoizedAsyncResolve.get(asyncResolve)!,\n });\n\n entrypoint.log('%s is ready', entrypoint.name);\n\n return result;\n } catch (err) {\n entrypoint.log('Unhandled error %O', err);\n\n if (\n isFeatureEnabled(pluginOptions.features, 'softErrors', options.filename)\n ) {\n // eslint-disable-next-line no-console\n console.error(`Error during transform of ${entrypoint.name}:`, err);\n\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n throw err;\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"transform.js","names":["_shared","require","_loadWywOptions","_cache","_Entrypoint","_actionRunner","_generators","_resolveImports","_withDefaultServices","memoizedSyncResolve","WeakMap","memoizedAsyncResolve","EMPTY_CUSTOM_HANDLERS","memoizedActionContexts","getActionContext","resolveImportsHandler","customHandlers","customHandlersKey","Object","keys","length","actionContextsByHandlers","get","set","actionContext","transformSync","partialServices","originalCode","syncResolve","options","pluginOptions","loadWywOptions","services","withDefaultServices","isFeatureEnabled","features","filename","cache","TransformCacheCollection","has","resolveImports","syncResolveImports","call","actionHandlers","baseHandlers","entrypoint","Entrypoint","createRoot","ignored","code","sourceMap","inputSourceMap","workflowAction","createAction","undefined","result","syncActionRunner","log","name","err","console","error","transform","asyncResolve","asyncResolveImports","asyncActionRunner"],"sources":["../src/transform.ts"],"sourcesContent":["/**\n * This file exposes sync and async transform functions that:\n * - parse the passed code to AST\n * - builds a dependency graph for the file\n * - shakes each dependency and removes unused code\n * - runs generated code in a sandbox\n * - collects artifacts\n * - returns transformed code (without WYW template literals), generated CSS, source maps and babel metadata from transform step.\n */\n\nimport { isFeatureEnabled } from '@wyw-in-js/shared';\n\nimport type { PartialOptions } from './transform/helpers/loadWywOptions';\nimport { loadWywOptions } from './transform/helpers/loadWywOptions';\nimport { TransformCacheCollection } from './cache';\nimport { Entrypoint } from './transform/Entrypoint';\nimport {\n asyncActionRunner,\n syncActionRunner,\n} from './transform/actions/actionRunner';\nimport { baseHandlers } from './transform/generators';\nimport {\n asyncResolveImports,\n syncResolveImports,\n} from './transform/generators/resolveImports';\nimport { withDefaultServices } from './transform/helpers/withDefaultServices';\nimport type {\n Handler,\n Handlers,\n IResolveImportsAction,\n Services,\n} from './transform/types';\nimport type { Result } from './types';\n\ntype PartialServices = Partial<Omit<Services, 'options'>> & {\n options: Omit<Services['options'], 'pluginOptions'> & {\n pluginOptions?: PartialOptions;\n };\n};\n\ntype AllHandlers<TMode extends 'async' | 'sync'> = Handlers<TMode>;\n\nconst memoizedSyncResolve = new WeakMap<\n (what: string, importer: string, stack: string[]) => string | null,\n Handler<'sync', IResolveImportsAction>\n>();\n\nconst memoizedAsyncResolve = new WeakMap<\n (what: string, importer: string, stack: string[]) => Promise<string | null>,\n Handler<'async' | 'sync', IResolveImportsAction>\n>();\n\nconst EMPTY_CUSTOM_HANDLERS = {};\nconst memoizedActionContexts = new WeakMap<object, WeakMap<object, object>>();\n\nconst getActionContext = (\n resolveImportsHandler: object,\n customHandlers: object\n): object => {\n const customHandlersKey =\n Object.keys(customHandlers).length === 0\n ? EMPTY_CUSTOM_HANDLERS\n : customHandlers;\n let actionContextsByHandlers = memoizedActionContexts.get(\n resolveImportsHandler\n );\n if (!actionContextsByHandlers) {\n actionContextsByHandlers = new WeakMap();\n memoizedActionContexts.set(resolveImportsHandler, actionContextsByHandlers);\n }\n\n let actionContext = actionContextsByHandlers.get(customHandlersKey);\n if (!actionContext) {\n actionContext = {};\n actionContextsByHandlers.set(customHandlersKey, actionContext);\n }\n\n return actionContext;\n};\n\nexport function transformSync(\n partialServices: PartialServices,\n originalCode: string,\n syncResolve: (what: string, importer: string, stack: string[]) => string,\n customHandlers: Partial<AllHandlers<'sync'>> = {}\n): Result {\n const { options } = partialServices;\n const pluginOptions = loadWywOptions(options.pluginOptions);\n const services = withDefaultServices({\n ...partialServices,\n options: {\n ...options,\n pluginOptions,\n },\n });\n\n if (\n !isFeatureEnabled(pluginOptions.features, 'globalCache', options.filename)\n ) {\n // If global cache is disabled, we need to create a new cache for each file\n services.cache = new TransformCacheCollection();\n }\n\n if (!memoizedSyncResolve.has(syncResolve)) {\n memoizedSyncResolve.set(\n syncResolve,\n function resolveImports(this: IResolveImportsAction) {\n return syncResolveImports.call(this, syncResolve);\n }\n );\n }\n\n const resolveImportsHandler = memoizedSyncResolve.get(syncResolve)!;\n const actionHandlers = {\n ...baseHandlers,\n ...customHandlers,\n resolveImports: resolveImportsHandler,\n };\n const actionContext = getActionContext(resolveImportsHandler, customHandlers);\n\n const entrypoint = Entrypoint.createRoot(\n services,\n options.filename,\n ['__wywPreval'],\n originalCode\n );\n\n if (entrypoint.ignored) {\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n const workflowAction = entrypoint.createAction(\n 'workflow',\n undefined,\n null,\n actionContext\n );\n\n try {\n const result = syncActionRunner(workflowAction, actionHandlers);\n\n entrypoint.log('%s is ready', entrypoint.name);\n\n return result;\n } catch (err) {\n entrypoint.log('Unhandled error %O', err);\n\n if (\n isFeatureEnabled(pluginOptions.features, 'softErrors', options.filename)\n ) {\n // eslint-disable-next-line no-console\n console.error(`Error during transform of ${entrypoint.name}:`, err);\n\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n throw err;\n }\n}\n\nexport async function transform(\n partialServices: PartialServices,\n originalCode: string,\n asyncResolve: (\n what: string,\n importer: string,\n stack: string[]\n ) => Promise<string | null>,\n customHandlers: Partial<AllHandlers<'sync'>> = {}\n): Promise<Result> {\n const { options } = partialServices;\n const pluginOptions = loadWywOptions(options.pluginOptions);\n const services = withDefaultServices({\n ...partialServices,\n options: {\n ...options,\n pluginOptions,\n },\n });\n\n if (\n !isFeatureEnabled(pluginOptions.features, 'globalCache', options.filename)\n ) {\n // If global cache is disabled, we need to create a new cache for each file\n services.cache = new TransformCacheCollection();\n }\n\n /*\n * This method can be run simultaneously for multiple files.\n * A shared cache is accessible for all runs, but each run has its own queue\n * to maintain the correct processing order. The cache stores the outcome\n * of tree-shaking, and if the result is already stored in the cache\n * but the \"only\" option has changed, the file will be re-processed using\n * the combined \"only\" option.\n */\n if (!memoizedAsyncResolve.has(asyncResolve)) {\n const resolveImports = function resolveImports(\n this: IResolveImportsAction\n ) {\n return asyncResolveImports.call(this, asyncResolve);\n };\n\n memoizedAsyncResolve.set(asyncResolve, resolveImports);\n }\n\n const resolveImportsHandler = memoizedAsyncResolve.get(asyncResolve)!;\n const actionHandlers = {\n ...baseHandlers,\n ...customHandlers,\n resolveImports: resolveImportsHandler,\n };\n const actionContext = getActionContext(resolveImportsHandler, customHandlers);\n\n const entrypoint = Entrypoint.createRoot(\n services,\n options.filename,\n ['__wywPreval'],\n originalCode\n );\n\n if (entrypoint.ignored) {\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n const workflowAction = entrypoint.createAction(\n 'workflow',\n undefined,\n null,\n actionContext\n );\n\n try {\n const result = await asyncActionRunner(workflowAction, actionHandlers);\n\n entrypoint.log('%s is ready', entrypoint.name);\n\n return result;\n } catch (err) {\n entrypoint.log('Unhandled error %O', err);\n\n if (\n isFeatureEnabled(pluginOptions.features, 'softErrors', options.filename)\n ) {\n // eslint-disable-next-line no-console\n console.error(`Error during transform of ${entrypoint.name}:`, err);\n\n return {\n code: originalCode,\n sourceMap: options.inputSourceMap,\n };\n }\n\n throw err;\n }\n}\n"],"mappings":"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","ignoreList":[]}
@@ -22,6 +22,15 @@ var _valueToLiteral = require("./valueToLiteral");
22
22
 
23
23
  function staticEval(ex, evaluate = false) {
24
24
  if (!evaluate) return undefined;
25
+ if (ex.isIdentifier()) {
26
+ const binding = ex.scope.getBinding(ex.node.name);
27
+
28
+ // Babel may "evaluate" a destructured binding to its source container
29
+ // object/array instead of the bound value, which changes template semantics.
30
+ if (binding !== null && binding !== void 0 && binding.path.isVariableDeclarator() && !binding.path.get('id').isIdentifier()) {
31
+ return undefined;
32
+ }
33
+ }
25
34
  const result = ex.evaluate();
26
35
  if (result.confident && !(0, _shared.hasEvalMeta)(result.value)) {
27
36
  return [result.value];
@@ -1 +1 @@
1
- {"version":3,"file":"collectTemplateDependencies.js","names":["_template","require","_types","_shared","_createId","_findIdentifiers","_getSource","_scopeHelpers","_valueToLiteral","staticEval","ex","evaluate","undefined","result","confident","hasEvalMeta","value","expressionDeclarationTpl","statement","preserveComments","unsupported","reason","buildCodeFrameError","isIdentifier","getUidInRootScope","path","name","node","rootScope","scope","getProgramParent","hasBinding","generateUid","hoistVariableDeclarator","parent","referencedIdentifiers","findIdentifiers","forEach","identifier","hoistIdentifier","bindingIdentifiers","newName","rename","statementInRoot","findParent","p","_p$parentPath","parentPath","isProgram","declaration","type","kind","declarations","cloneNode","inserted","insertBefore","referenceAll","registerDeclaration","idPath","isReferenced","binding","getBinding","includes","bindingPath","isVariableDeclarator","extractExpression","imports","isLiteral","ValueType","CONST","loc","_p$parentPath2","isFunction","isFunctionExpression","isArrowFunctionExpression","expUid","evaluated","id","evaluatedId","mutate","replaceWith","valueToLiteral","FUNCTION","LAZY","expId","createId","expression","importedFrom","findImportSourceOfIdentifier","_idPath$scope$getBind","_imports$find","exBindingIdentifier","exImport","find","i","local","push","source","traverse","Identifier","callee","arguments","debug","logger","extend","collectTemplateDependencies","quasi","get","quasis","expressions","length","expressionValues","map","bind","getSource","isExpression","extracted"],"sources":["../../src/utils/collectTemplateDependencies.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-use-before-define: [\"error\", { \"functions\": false }] */\n\n/**\n * This file is a visitor that checks TaggedTemplateExpressions and look for WYW template literals.\n * For each template it makes a list of dependencies, try to evaluate expressions, and if it is not possible, mark them as lazy dependencies.\n */\n\nimport { statement } from '@babel/template';\nimport type { NodePath } from '@babel/traverse';\nimport type {\n Expression,\n Identifier,\n JSXIdentifier,\n Statement,\n TaggedTemplateExpression,\n TemplateElement,\n TSType,\n VariableDeclaration,\n VariableDeclarator,\n} from '@babel/types';\nimport { cloneNode } from '@babel/types';\n\nimport type {\n ConstValue,\n ExpressionValue,\n FunctionValue,\n LazyValue,\n} from '@wyw-in-js/shared';\nimport { hasEvalMeta, ValueType, logger } from '@wyw-in-js/shared';\n\nimport type { IImport } from './collectExportsAndImports';\nimport { createId } from './createId';\nimport { findIdentifiers } from './findIdentifiers';\nimport { getSource } from './getSource';\nimport { mutate, referenceAll } from './scopeHelpers';\nimport { valueToLiteral } from './valueToLiteral';\n\nfunction staticEval(\n ex: NodePath<Expression>,\n evaluate = false\n): [unknown] | undefined {\n if (!evaluate) return undefined;\n\n const result = ex.evaluate();\n if (result.confident && !hasEvalMeta(result.value)) {\n return [result.value];\n }\n\n return undefined;\n}\n\nconst expressionDeclarationTpl = statement(\n 'const %%expId%% = () => %%expression%%',\n {\n preserveComments: true,\n }\n);\n\nconst unsupported = (ex: NodePath, reason?: string): Error =>\n ex.buildCodeFrameError(\n `This ${\n ex.isIdentifier() ? 'identifier' : 'expression'\n } cannot be used in the template${reason ? `, because it ${reason}` : ''}.`\n );\n\nfunction getUidInRootScope(path: NodePath<Identifier | JSXIdentifier>): string {\n const { name } = path.node;\n const rootScope = path.scope.getProgramParent();\n if (rootScope.hasBinding(name)) {\n return rootScope.generateUid(name);\n }\n\n return name;\n}\n\nfunction hoistVariableDeclarator(ex: NodePath<VariableDeclarator>) {\n if (!ex.scope.parent) {\n // It is already in the root scope\n return;\n }\n\n const referencedIdentifiers = findIdentifiers([ex], 'reference');\n referencedIdentifiers.forEach((identifier) => {\n if (identifier.isIdentifier()) {\n hoistIdentifier(identifier);\n }\n });\n\n const bindingIdentifiers = findIdentifiers([ex], 'declaration');\n\n bindingIdentifiers.forEach((path) => {\n const newName = getUidInRootScope(path);\n if (newName !== path.node.name) {\n path.scope.rename(path.node.name, newName);\n }\n });\n\n const rootScope = ex.scope.getProgramParent();\n\n const statementInRoot = ex.findParent(\n (p) => p.parentPath?.isProgram() === true\n ) as NodePath<Statement>;\n\n const declaration: VariableDeclaration = {\n type: 'VariableDeclaration',\n kind: 'let',\n declarations: [cloneNode(ex.node)],\n };\n\n const [inserted] = statementInRoot.insertBefore(declaration);\n referenceAll(inserted);\n rootScope.registerDeclaration(inserted);\n}\n\nfunction hoistIdentifier(idPath: NodePath<Identifier>): void {\n if (!idPath.isReferenced()) {\n throw unsupported(idPath);\n }\n\n const binding = idPath.scope.getBinding(idPath.node.name);\n if (!binding) {\n // It's something strange\n throw unsupported(idPath, 'is undefined');\n }\n\n if (binding.kind === 'module') {\n // Modules are global by default\n return;\n }\n\n if (!['var', 'let', 'const', 'hoisted'].includes(binding.kind)) {\n // This is not a variable, we can't hoist it\n throw unsupported(binding.path, 'is a function parameter');\n }\n\n const { scope, path: bindingPath } = binding;\n // parent here can be null or undefined in different versions of babel\n if (!scope.parent) {\n // The variable is already in the root scope\n return;\n }\n\n if (bindingPath.isVariableDeclarator()) {\n hoistVariableDeclarator(bindingPath);\n\n return;\n }\n\n throw unsupported(idPath);\n}\n\n/**\n * Only an expression that can be evaluated in the root scope can be\n * used in a WYW template. This function tries to hoist the expression.\n * @param ex The expression to hoist.\n * @param evaluate If true, we try to statically evaluate the expression.\n * @param imports All the imports of the file.\n */\nexport function extractExpression(\n ex: NodePath<Expression>,\n evaluate = false,\n imports: IImport[] = []\n): Omit<ExpressionValue, 'buildCodeFrameError' | 'source'> {\n if (\n ex.isLiteral() &&\n ('value' in ex.node || ex.node.type === 'NullLiteral')\n ) {\n return {\n ex: ex.node,\n kind: ValueType.CONST,\n value: ex.node.type === 'NullLiteral' ? null : ex.node.value,\n } as Omit<ConstValue, 'buildCodeFrameError' | 'source'>;\n }\n\n const { loc } = ex.node;\n\n const rootScope = ex.scope.getProgramParent();\n const statementInRoot = ex.findParent(\n (p) => p.parentPath?.isProgram() === true\n ) as NodePath<Statement>;\n\n const isFunction =\n ex.isFunctionExpression() || ex.isArrowFunctionExpression();\n\n // Generate next _expN name\n const expUid = rootScope.generateUid('exp');\n\n const evaluated = staticEval(ex, evaluate);\n\n if (!evaluated) {\n // If expression is not statically evaluable,\n // we need to hoist all its referenced identifiers\n\n // Collect all referenced identifiers\n findIdentifiers([ex], 'reference').forEach((id) => {\n if (!id.isIdentifier()) return;\n\n // Try to evaluate and inline them…\n const evaluatedId = staticEval(id, evaluate);\n if (evaluatedId) {\n mutate(id, (p) => {\n p.replaceWith(valueToLiteral(evaluatedId[0], ex));\n });\n } else {\n // … or hoist them to the root scope\n hoistIdentifier(id);\n }\n });\n }\n\n const kind = isFunction ? ValueType.FUNCTION : ValueType.LAZY;\n\n // Declare _expN const with the lazy expression\n const declaration = expressionDeclarationTpl({\n expId: createId(expUid),\n expression: evaluated\n ? valueToLiteral(evaluated[0], ex)\n : cloneNode(ex.node),\n }) as VariableDeclaration;\n\n // Insert the declaration as close as possible to the original expression\n const [inserted] = statementInRoot.insertBefore(declaration);\n referenceAll(inserted);\n rootScope.registerDeclaration(inserted);\n\n const importedFrom: string[] = [];\n function findImportSourceOfIdentifier(idPath: NodePath<Identifier>) {\n const exBindingIdentifier = idPath.scope.getBinding(idPath.node.name)\n ?.identifier;\n const exImport =\n imports.find((i) => i.local.node === exBindingIdentifier) ?? null;\n if (exImport) {\n importedFrom.push(exImport.source);\n }\n }\n\n if (ex.isIdentifier()) {\n findImportSourceOfIdentifier(ex);\n } else {\n ex.traverse({\n Identifier: findImportSourceOfIdentifier,\n });\n }\n\n // Replace the expression with the _expN() call\n mutate(ex, (p) => {\n p.replaceWith({\n type: 'CallExpression',\n callee: createId(expUid),\n arguments: [],\n });\n });\n\n // eslint-disable-next-line no-param-reassign\n ex.node.loc = loc;\n\n // noinspection UnnecessaryLocalVariableJS\n const result: Omit<\n LazyValue | FunctionValue,\n 'buildCodeFrameError' | 'source'\n > = {\n kind,\n ex: createId(expUid, loc),\n importedFrom,\n };\n\n return result;\n}\n\nconst debug = logger.extend('template-parse:identify-expressions');\n\n/**\n * Collects, hoists, and makes lazy all expressions in the given template\n * If evaluate is true, it will try to evaluate the expressions\n */\nexport function collectTemplateDependencies(\n path: NodePath<TaggedTemplateExpression>,\n evaluate = false\n): [quasis: TemplateElement[], expressionValues: ExpressionValue[]] {\n const quasi = path.get('quasi');\n const quasis = quasi.get('quasis');\n const expressions = quasi.get('expressions');\n\n debug('Found: %s', expressions.length);\n\n const expressionValues: ExpressionValue[] = expressions.map(\n (ex: NodePath<Expression | TSType>): ExpressionValue => {\n const buildCodeFrameError = ex.buildCodeFrameError.bind(ex);\n const source = getSource(ex);\n\n if (!ex.isExpression()) {\n throw buildCodeFrameError(\n `The expression '${source}' is not supported.`\n );\n }\n\n const extracted = extractExpression(ex, evaluate);\n\n return {\n ...extracted,\n source,\n buildCodeFrameError,\n } as ExpressionValue;\n }\n );\n\n return [quasis.map((p) => p.node), expressionValues];\n}\n"],"mappings":";;;;;;;AAOA,IAAAA,SAAA,GAAAC,OAAA;AAaA,IAAAC,MAAA,GAAAD,OAAA;AAQA,IAAAE,OAAA,GAAAF,OAAA;AAGA,IAAAG,SAAA,GAAAH,OAAA;AACA,IAAAI,gBAAA,GAAAJ,OAAA;AACA,IAAAK,UAAA,GAAAL,OAAA;AACA,IAAAM,aAAA,GAAAN,OAAA;AACA,IAAAO,eAAA,GAAAP,OAAA;AAnCA;;AAEA;AACA;AACA;AACA;;AAgCA,SAASQ,UAAUA,CACjBC,EAAwB,EACxBC,QAAQ,GAAG,KAAK,EACO;EACvB,IAAI,CAACA,QAAQ,EAAE,OAAOC,SAAS;EAE/B,MAAMC,MAAM,GAAGH,EAAE,CAACC,QAAQ,CAAC,CAAC;EAC5B,IAAIE,MAAM,CAACC,SAAS,IAAI,CAAC,IAAAC,mBAAW,EAACF,MAAM,CAACG,KAAK,CAAC,EAAE;IAClD,OAAO,CAACH,MAAM,CAACG,KAAK,CAAC;EACvB;EAEA,OAAOJ,SAAS;AAClB;AAEA,MAAMK,wBAAwB,GAAG,IAAAC,mBAAS,EACxC,wCAAwC,EACxC;EACEC,gBAAgB,EAAE;AACpB,CACF,CAAC;AAED,MAAMC,WAAW,GAAGA,CAACV,EAAY,EAAEW,MAAe,KAChDX,EAAE,CAACY,mBAAmB,CACpB,QACEZ,EAAE,CAACa,YAAY,CAAC,CAAC,GAAG,YAAY,GAAG,YAAY,kCACfF,MAAM,GAAG,gBAAgBA,MAAM,EAAE,GAAG,EAAE,GAC1E,CAAC;AAEH,SAASG,iBAAiBA,CAACC,IAA0C,EAAU;EAC7E,MAAM;IAAEC;EAAK,CAAC,GAAGD,IAAI,CAACE,IAAI;EAC1B,MAAMC,SAAS,GAAGH,IAAI,CAACI,KAAK,CAACC,gBAAgB,CAAC,CAAC;EAC/C,IAAIF,SAAS,CAACG,UAAU,CAACL,IAAI,CAAC,EAAE;IAC9B,OAAOE,SAAS,CAACI,WAAW,CAACN,IAAI,CAAC;EACpC;EAEA,OAAOA,IAAI;AACb;AAEA,SAASO,uBAAuBA,CAACvB,EAAgC,EAAE;EACjE,IAAI,CAACA,EAAE,CAACmB,KAAK,CAACK,MAAM,EAAE;IACpB;IACA;EACF;EAEA,MAAMC,qBAAqB,GAAG,IAAAC,gCAAe,EAAC,CAAC1B,EAAE,CAAC,EAAE,WAAW,CAAC;EAChEyB,qBAAqB,CAACE,OAAO,CAAEC,UAAU,IAAK;IAC5C,IAAIA,UAAU,CAACf,YAAY,CAAC,CAAC,EAAE;MAC7BgB,eAAe,CAACD,UAAU,CAAC;IAC7B;EACF,CAAC,CAAC;EAEF,MAAME,kBAAkB,GAAG,IAAAJ,gCAAe,EAAC,CAAC1B,EAAE,CAAC,EAAE,aAAa,CAAC;EAE/D8B,kBAAkB,CAACH,OAAO,CAAEZ,IAAI,IAAK;IACnC,MAAMgB,OAAO,GAAGjB,iBAAiB,CAACC,IAAI,CAAC;IACvC,IAAIgB,OAAO,KAAKhB,IAAI,CAACE,IAAI,CAACD,IAAI,EAAE;MAC9BD,IAAI,CAACI,KAAK,CAACa,MAAM,CAACjB,IAAI,CAACE,IAAI,CAACD,IAAI,EAAEe,OAAO,CAAC;IAC5C;EACF,CAAC,CAAC;EAEF,MAAMb,SAAS,GAAGlB,EAAE,CAACmB,KAAK,CAACC,gBAAgB,CAAC,CAAC;EAE7C,MAAMa,eAAe,GAAGjC,EAAE,CAACkC,UAAU,CAClCC,CAAC;IAAA,IAAAC,aAAA;IAAA,OAAK,EAAAA,aAAA,GAAAD,CAAC,CAACE,UAAU,cAAAD,aAAA,uBAAZA,aAAA,CAAcE,SAAS,CAAC,CAAC,MAAK,IAAI;EAAA,CAC3C,CAAwB;EAExB,MAAMC,WAAgC,GAAG;IACvCC,IAAI,EAAE,qBAAqB;IAC3BC,IAAI,EAAE,KAAK;IACXC,YAAY,EAAE,CAAC,IAAAC,gBAAS,EAAC3C,EAAE,CAACiB,IAAI,CAAC;EACnC,CAAC;EAED,MAAM,CAAC2B,QAAQ,CAAC,GAAGX,eAAe,CAACY,YAAY,CAACN,WAAW,CAAC;EAC5D,IAAAO,0BAAY,EAACF,QAAQ,CAAC;EACtB1B,SAAS,CAAC6B,mBAAmB,CAACH,QAAQ,CAAC;AACzC;AAEA,SAASf,eAAeA,CAACmB,MAA4B,EAAQ;EAC3D,IAAI,CAACA,MAAM,CAACC,YAAY,CAAC,CAAC,EAAE;IAC1B,MAAMvC,WAAW,CAACsC,MAAM,CAAC;EAC3B;EAEA,MAAME,OAAO,GAAGF,MAAM,CAAC7B,KAAK,CAACgC,UAAU,CAACH,MAAM,CAAC/B,IAAI,CAACD,IAAI,CAAC;EACzD,IAAI,CAACkC,OAAO,EAAE;IACZ;IACA,MAAMxC,WAAW,CAACsC,MAAM,EAAE,cAAc,CAAC;EAC3C;EAEA,IAAIE,OAAO,CAACT,IAAI,KAAK,QAAQ,EAAE;IAC7B;IACA;EACF;EAEA,IAAI,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,CAAC,CAACW,QAAQ,CAACF,OAAO,CAACT,IAAI,CAAC,EAAE;IAC9D;IACA,MAAM/B,WAAW,CAACwC,OAAO,CAACnC,IAAI,EAAE,yBAAyB,CAAC;EAC5D;EAEA,MAAM;IAAEI,KAAK;IAAEJ,IAAI,EAAEsC;EAAY,CAAC,GAAGH,OAAO;EAC5C;EACA,IAAI,CAAC/B,KAAK,CAACK,MAAM,EAAE;IACjB;IACA;EACF;EAEA,IAAI6B,WAAW,CAACC,oBAAoB,CAAC,CAAC,EAAE;IACtC/B,uBAAuB,CAAC8B,WAAW,CAAC;IAEpC;EACF;EAEA,MAAM3C,WAAW,CAACsC,MAAM,CAAC;AAC3B;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAASO,iBAAiBA,CAC/BvD,EAAwB,EACxBC,QAAQ,GAAG,KAAK,EAChBuD,OAAkB,GAAG,EAAE,EACkC;EACzD,IACExD,EAAE,CAACyD,SAAS,CAAC,CAAC,KACb,OAAO,IAAIzD,EAAE,CAACiB,IAAI,IAAIjB,EAAE,CAACiB,IAAI,CAACuB,IAAI,KAAK,aAAa,CAAC,EACtD;IACA,OAAO;MACLxC,EAAE,EAAEA,EAAE,CAACiB,IAAI;MACXwB,IAAI,EAAEiB,iBAAS,CAACC,KAAK;MACrBrD,KAAK,EAAEN,EAAE,CAACiB,IAAI,CAACuB,IAAI,KAAK,aAAa,GAAG,IAAI,GAAGxC,EAAE,CAACiB,IAAI,CAACX;IACzD,CAAC;EACH;EAEA,MAAM;IAAEsD;EAAI,CAAC,GAAG5D,EAAE,CAACiB,IAAI;EAEvB,MAAMC,SAAS,GAAGlB,EAAE,CAACmB,KAAK,CAACC,gBAAgB,CAAC,CAAC;EAC7C,MAAMa,eAAe,GAAGjC,EAAE,CAACkC,UAAU,CAClCC,CAAC;IAAA,IAAA0B,cAAA;IAAA,OAAK,EAAAA,cAAA,GAAA1B,CAAC,CAACE,UAAU,cAAAwB,cAAA,uBAAZA,cAAA,CAAcvB,SAAS,CAAC,CAAC,MAAK,IAAI;EAAA,CAC3C,CAAwB;EAExB,MAAMwB,UAAU,GACd9D,EAAE,CAAC+D,oBAAoB,CAAC,CAAC,IAAI/D,EAAE,CAACgE,yBAAyB,CAAC,CAAC;;EAE7D;EACA,MAAMC,MAAM,GAAG/C,SAAS,CAACI,WAAW,CAAC,KAAK,CAAC;EAE3C,MAAM4C,SAAS,GAAGnE,UAAU,CAACC,EAAE,EAAEC,QAAQ,CAAC;EAE1C,IAAI,CAACiE,SAAS,EAAE;IACd;IACA;;IAEA;IACA,IAAAxC,gCAAe,EAAC,CAAC1B,EAAE,CAAC,EAAE,WAAW,CAAC,CAAC2B,OAAO,CAAEwC,EAAE,IAAK;MACjD,IAAI,CAACA,EAAE,CAACtD,YAAY,CAAC,CAAC,EAAE;;MAExB;MACA,MAAMuD,WAAW,GAAGrE,UAAU,CAACoE,EAAE,EAAElE,QAAQ,CAAC;MAC5C,IAAImE,WAAW,EAAE;QACf,IAAAC,oBAAM,EAACF,EAAE,EAAGhC,CAAC,IAAK;UAChBA,CAAC,CAACmC,WAAW,CAAC,IAAAC,8BAAc,EAACH,WAAW,CAAC,CAAC,CAAC,EAAEpE,EAAE,CAAC,CAAC;QACnD,CAAC,CAAC;MACJ,CAAC,MAAM;QACL;QACA6B,eAAe,CAACsC,EAAE,CAAC;MACrB;IACF,CAAC,CAAC;EACJ;EAEA,MAAM1B,IAAI,GAAGqB,UAAU,GAAGJ,iBAAS,CAACc,QAAQ,GAAGd,iBAAS,CAACe,IAAI;;EAE7D;EACA,MAAMlC,WAAW,GAAGhC,wBAAwB,CAAC;IAC3CmE,KAAK,EAAE,IAAAC,kBAAQ,EAACV,MAAM,CAAC;IACvBW,UAAU,EAAEV,SAAS,GACjB,IAAAK,8BAAc,EAACL,SAAS,CAAC,CAAC,CAAC,EAAElE,EAAE,CAAC,GAChC,IAAA2C,gBAAS,EAAC3C,EAAE,CAACiB,IAAI;EACvB,CAAC,CAAwB;;EAEzB;EACA,MAAM,CAAC2B,QAAQ,CAAC,GAAGX,eAAe,CAACY,YAAY,CAACN,WAAW,CAAC;EAC5D,IAAAO,0BAAY,EAACF,QAAQ,CAAC;EACtB1B,SAAS,CAAC6B,mBAAmB,CAACH,QAAQ,CAAC;EAEvC,MAAMiC,YAAsB,GAAG,EAAE;EACjC,SAASC,4BAA4BA,CAAC9B,MAA4B,EAAE;IAAA,IAAA+B,qBAAA,EAAAC,aAAA;IAClE,MAAMC,mBAAmB,IAAAF,qBAAA,GAAG/B,MAAM,CAAC7B,KAAK,CAACgC,UAAU,CAACH,MAAM,CAAC/B,IAAI,CAACD,IAAI,CAAC,cAAA+D,qBAAA,uBAAzCA,qBAAA,CACxBnD,UAAU;IACd,MAAMsD,QAAQ,IAAAF,aAAA,GACZxB,OAAO,CAAC2B,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAACC,KAAK,CAACpE,IAAI,KAAKgE,mBAAmB,CAAC,cAAAD,aAAA,cAAAA,aAAA,GAAI,IAAI;IACnE,IAAIE,QAAQ,EAAE;MACZL,YAAY,CAACS,IAAI,CAACJ,QAAQ,CAACK,MAAM,CAAC;IACpC;EACF;EAEA,IAAIvF,EAAE,CAACa,YAAY,CAAC,CAAC,EAAE;IACrBiE,4BAA4B,CAAC9E,EAAE,CAAC;EAClC,CAAC,MAAM;IACLA,EAAE,CAACwF,QAAQ,CAAC;MACVC,UAAU,EAAEX;IACd,CAAC,CAAC;EACJ;;EAEA;EACA,IAAAT,oBAAM,EAACrE,EAAE,EAAGmC,CAAC,IAAK;IAChBA,CAAC,CAACmC,WAAW,CAAC;MACZ9B,IAAI,EAAE,gBAAgB;MACtBkD,MAAM,EAAE,IAAAf,kBAAQ,EAACV,MAAM,CAAC;MACxB0B,SAAS,EAAE;IACb,CAAC,CAAC;EACJ,CAAC,CAAC;;EAEF;EACA3F,EAAE,CAACiB,IAAI,CAAC2C,GAAG,GAAGA,GAAG;;EAEjB;EACA,MAAMzD,MAGL,GAAG;IACFsC,IAAI;IACJzC,EAAE,EAAE,IAAA2E,kBAAQ,EAACV,MAAM,EAAEL,GAAG,CAAC;IACzBiB;EACF,CAAC;EAED,OAAO1E,MAAM;AACf;AAEA,MAAMyF,KAAK,GAAGC,cAAM,CAACC,MAAM,CAAC,qCAAqC,CAAC;;AAElE;AACA;AACA;AACA;AACO,SAASC,2BAA2BA,CACzChF,IAAwC,EACxCd,QAAQ,GAAG,KAAK,EACkD;EAClE,MAAM+F,KAAK,GAAGjF,IAAI,CAACkF,GAAG,CAAC,OAAO,CAAC;EAC/B,MAAMC,MAAM,GAAGF,KAAK,CAACC,GAAG,CAAC,QAAQ,CAAC;EAClC,MAAME,WAAW,GAAGH,KAAK,CAACC,GAAG,CAAC,aAAa,CAAC;EAE5CL,KAAK,CAAC,WAAW,EAAEO,WAAW,CAACC,MAAM,CAAC;EAEtC,MAAMC,gBAAmC,GAAGF,WAAW,CAACG,GAAG,CACxDtG,EAAiC,IAAsB;IACtD,MAAMY,mBAAmB,GAAGZ,EAAE,CAACY,mBAAmB,CAAC2F,IAAI,CAACvG,EAAE,CAAC;IAC3D,MAAMuF,MAAM,GAAG,IAAAiB,oBAAS,EAACxG,EAAE,CAAC;IAE5B,IAAI,CAACA,EAAE,CAACyG,YAAY,CAAC,CAAC,EAAE;MACtB,MAAM7F,mBAAmB,CACvB,mBAAmB2E,MAAM,qBAC3B,CAAC;IACH;IAEA,MAAMmB,SAAS,GAAGnD,iBAAiB,CAACvD,EAAE,EAAEC,QAAQ,CAAC;IAEjD,OAAO;MACL,GAAGyG,SAAS;MACZnB,MAAM;MACN3E;IACF,CAAC;EACH,CACF,CAAC;EAED,OAAO,CAACsF,MAAM,CAACI,GAAG,CAAEnE,CAAC,IAAKA,CAAC,CAAClB,IAAI,CAAC,EAAEoF,gBAAgB,CAAC;AACtD","ignoreList":[]}
1
+ {"version":3,"file":"collectTemplateDependencies.js","names":["_template","require","_types","_shared","_createId","_findIdentifiers","_getSource","_scopeHelpers","_valueToLiteral","staticEval","ex","evaluate","undefined","isIdentifier","binding","scope","getBinding","node","name","path","isVariableDeclarator","get","result","confident","hasEvalMeta","value","expressionDeclarationTpl","statement","preserveComments","unsupported","reason","buildCodeFrameError","getUidInRootScope","rootScope","getProgramParent","hasBinding","generateUid","hoistVariableDeclarator","parent","referencedIdentifiers","findIdentifiers","forEach","identifier","hoistIdentifier","bindingIdentifiers","newName","rename","statementInRoot","findParent","p","_p$parentPath","parentPath","isProgram","declaration","type","kind","declarations","cloneNode","inserted","insertBefore","referenceAll","registerDeclaration","idPath","isReferenced","includes","bindingPath","extractExpression","imports","isLiteral","ValueType","CONST","loc","_p$parentPath2","isFunction","isFunctionExpression","isArrowFunctionExpression","expUid","evaluated","id","evaluatedId","mutate","replaceWith","valueToLiteral","FUNCTION","LAZY","expId","createId","expression","importedFrom","findImportSourceOfIdentifier","_idPath$scope$getBind","_imports$find","exBindingIdentifier","exImport","find","i","local","push","source","traverse","Identifier","callee","arguments","debug","logger","extend","collectTemplateDependencies","quasi","quasis","expressions","length","expressionValues","map","bind","getSource","isExpression","extracted"],"sources":["../../src/utils/collectTemplateDependencies.ts"],"sourcesContent":["/* eslint @typescript-eslint/no-use-before-define: [\"error\", { \"functions\": false }] */\n\n/**\n * This file is a visitor that checks TaggedTemplateExpressions and look for WYW template literals.\n * For each template it makes a list of dependencies, try to evaluate expressions, and if it is not possible, mark them as lazy dependencies.\n */\n\nimport { statement } from '@babel/template';\nimport type { NodePath } from '@babel/traverse';\nimport type {\n Expression,\n Identifier,\n JSXIdentifier,\n Statement,\n TaggedTemplateExpression,\n TemplateElement,\n TSType,\n VariableDeclaration,\n VariableDeclarator,\n} from '@babel/types';\nimport { cloneNode } from '@babel/types';\n\nimport type {\n ConstValue,\n ExpressionValue,\n FunctionValue,\n LazyValue,\n} from '@wyw-in-js/shared';\nimport { hasEvalMeta, ValueType, logger } from '@wyw-in-js/shared';\n\nimport type { IImport } from './collectExportsAndImports';\nimport { createId } from './createId';\nimport { findIdentifiers } from './findIdentifiers';\nimport { getSource } from './getSource';\nimport { mutate, referenceAll } from './scopeHelpers';\nimport { valueToLiteral } from './valueToLiteral';\n\nfunction staticEval(\n ex: NodePath<Expression>,\n evaluate = false\n): [unknown] | undefined {\n if (!evaluate) return undefined;\n\n if (ex.isIdentifier()) {\n const binding = ex.scope.getBinding(ex.node.name);\n\n // Babel may \"evaluate\" a destructured binding to its source container\n // object/array instead of the bound value, which changes template semantics.\n if (\n binding?.path.isVariableDeclarator() &&\n !binding.path.get('id').isIdentifier()\n ) {\n return undefined;\n }\n }\n\n const result = ex.evaluate();\n if (result.confident && !hasEvalMeta(result.value)) {\n return [result.value];\n }\n\n return undefined;\n}\n\nconst expressionDeclarationTpl = statement(\n 'const %%expId%% = () => %%expression%%',\n {\n preserveComments: true,\n }\n);\n\nconst unsupported = (ex: NodePath, reason?: string): Error =>\n ex.buildCodeFrameError(\n `This ${\n ex.isIdentifier() ? 'identifier' : 'expression'\n } cannot be used in the template${reason ? `, because it ${reason}` : ''}.`\n );\n\nfunction getUidInRootScope(path: NodePath<Identifier | JSXIdentifier>): string {\n const { name } = path.node;\n const rootScope = path.scope.getProgramParent();\n if (rootScope.hasBinding(name)) {\n return rootScope.generateUid(name);\n }\n\n return name;\n}\n\nfunction hoistVariableDeclarator(ex: NodePath<VariableDeclarator>) {\n if (!ex.scope.parent) {\n // It is already in the root scope\n return;\n }\n\n const referencedIdentifiers = findIdentifiers([ex], 'reference');\n referencedIdentifiers.forEach((identifier) => {\n if (identifier.isIdentifier()) {\n hoistIdentifier(identifier);\n }\n });\n\n const bindingIdentifiers = findIdentifiers([ex], 'declaration');\n\n bindingIdentifiers.forEach((path) => {\n const newName = getUidInRootScope(path);\n if (newName !== path.node.name) {\n path.scope.rename(path.node.name, newName);\n }\n });\n\n const rootScope = ex.scope.getProgramParent();\n\n const statementInRoot = ex.findParent(\n (p) => p.parentPath?.isProgram() === true\n ) as NodePath<Statement>;\n\n const declaration: VariableDeclaration = {\n type: 'VariableDeclaration',\n kind: 'let',\n declarations: [cloneNode(ex.node)],\n };\n\n const [inserted] = statementInRoot.insertBefore(declaration);\n referenceAll(inserted);\n rootScope.registerDeclaration(inserted);\n}\n\nfunction hoistIdentifier(idPath: NodePath<Identifier>): void {\n if (!idPath.isReferenced()) {\n throw unsupported(idPath);\n }\n\n const binding = idPath.scope.getBinding(idPath.node.name);\n if (!binding) {\n // It's something strange\n throw unsupported(idPath, 'is undefined');\n }\n\n if (binding.kind === 'module') {\n // Modules are global by default\n return;\n }\n\n if (!['var', 'let', 'const', 'hoisted'].includes(binding.kind)) {\n // This is not a variable, we can't hoist it\n throw unsupported(binding.path, 'is a function parameter');\n }\n\n const { scope, path: bindingPath } = binding;\n // parent here can be null or undefined in different versions of babel\n if (!scope.parent) {\n // The variable is already in the root scope\n return;\n }\n\n if (bindingPath.isVariableDeclarator()) {\n hoistVariableDeclarator(bindingPath);\n\n return;\n }\n\n throw unsupported(idPath);\n}\n\n/**\n * Only an expression that can be evaluated in the root scope can be\n * used in a WYW template. This function tries to hoist the expression.\n * @param ex The expression to hoist.\n * @param evaluate If true, we try to statically evaluate the expression.\n * @param imports All the imports of the file.\n */\nexport function extractExpression(\n ex: NodePath<Expression>,\n evaluate = false,\n imports: IImport[] = []\n): Omit<ExpressionValue, 'buildCodeFrameError' | 'source'> {\n if (\n ex.isLiteral() &&\n ('value' in ex.node || ex.node.type === 'NullLiteral')\n ) {\n return {\n ex: ex.node,\n kind: ValueType.CONST,\n value: ex.node.type === 'NullLiteral' ? null : ex.node.value,\n } as Omit<ConstValue, 'buildCodeFrameError' | 'source'>;\n }\n\n const { loc } = ex.node;\n\n const rootScope = ex.scope.getProgramParent();\n const statementInRoot = ex.findParent(\n (p) => p.parentPath?.isProgram() === true\n ) as NodePath<Statement>;\n\n const isFunction =\n ex.isFunctionExpression() || ex.isArrowFunctionExpression();\n\n // Generate next _expN name\n const expUid = rootScope.generateUid('exp');\n\n const evaluated = staticEval(ex, evaluate);\n\n if (!evaluated) {\n // If expression is not statically evaluable,\n // we need to hoist all its referenced identifiers\n\n // Collect all referenced identifiers\n findIdentifiers([ex], 'reference').forEach((id) => {\n if (!id.isIdentifier()) return;\n\n // Try to evaluate and inline them…\n const evaluatedId = staticEval(id, evaluate);\n if (evaluatedId) {\n mutate(id, (p) => {\n p.replaceWith(valueToLiteral(evaluatedId[0], ex));\n });\n } else {\n // … or hoist them to the root scope\n hoistIdentifier(id);\n }\n });\n }\n\n const kind = isFunction ? ValueType.FUNCTION : ValueType.LAZY;\n\n // Declare _expN const with the lazy expression\n const declaration = expressionDeclarationTpl({\n expId: createId(expUid),\n expression: evaluated\n ? valueToLiteral(evaluated[0], ex)\n : cloneNode(ex.node),\n }) as VariableDeclaration;\n\n // Insert the declaration as close as possible to the original expression\n const [inserted] = statementInRoot.insertBefore(declaration);\n referenceAll(inserted);\n rootScope.registerDeclaration(inserted);\n\n const importedFrom: string[] = [];\n function findImportSourceOfIdentifier(idPath: NodePath<Identifier>) {\n const exBindingIdentifier = idPath.scope.getBinding(idPath.node.name)\n ?.identifier;\n const exImport =\n imports.find((i) => i.local.node === exBindingIdentifier) ?? null;\n if (exImport) {\n importedFrom.push(exImport.source);\n }\n }\n\n if (ex.isIdentifier()) {\n findImportSourceOfIdentifier(ex);\n } else {\n ex.traverse({\n Identifier: findImportSourceOfIdentifier,\n });\n }\n\n // Replace the expression with the _expN() call\n mutate(ex, (p) => {\n p.replaceWith({\n type: 'CallExpression',\n callee: createId(expUid),\n arguments: [],\n });\n });\n\n // eslint-disable-next-line no-param-reassign\n ex.node.loc = loc;\n\n // noinspection UnnecessaryLocalVariableJS\n const result: Omit<\n LazyValue | FunctionValue,\n 'buildCodeFrameError' | 'source'\n > = {\n kind,\n ex: createId(expUid, loc),\n importedFrom,\n };\n\n return result;\n}\n\nconst debug = logger.extend('template-parse:identify-expressions');\n\n/**\n * Collects, hoists, and makes lazy all expressions in the given template\n * If evaluate is true, it will try to evaluate the expressions\n */\nexport function collectTemplateDependencies(\n path: NodePath<TaggedTemplateExpression>,\n evaluate = false\n): [quasis: TemplateElement[], expressionValues: ExpressionValue[]] {\n const quasi = path.get('quasi');\n const quasis = quasi.get('quasis');\n const expressions = quasi.get('expressions');\n\n debug('Found: %s', expressions.length);\n\n const expressionValues: ExpressionValue[] = expressions.map(\n (ex: NodePath<Expression | TSType>): ExpressionValue => {\n const buildCodeFrameError = ex.buildCodeFrameError.bind(ex);\n const source = getSource(ex);\n\n if (!ex.isExpression()) {\n throw buildCodeFrameError(\n `The expression '${source}' is not supported.`\n );\n }\n\n const extracted = extractExpression(ex, evaluate);\n\n return {\n ...extracted,\n source,\n buildCodeFrameError,\n } as ExpressionValue;\n }\n );\n\n return [quasis.map((p) => p.node), expressionValues];\n}\n"],"mappings":"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","ignoreList":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wyw-in-js/transform",
3
- "version": "1.0.6",
3
+ "version": "1.0.8",
4
4
  "dependencies": {
5
5
  "@babel/core": "^7.23.5",
6
6
  "@babel/generator": "^7.23.5",
@@ -9,8 +9,8 @@
9
9
  "@babel/template": "^7.22.15",
10
10
  "@babel/traverse": "^7.23.5",
11
11
  "@babel/types": "^7.23.5",
12
- "@wyw-in-js/processor-utils": "1.0.4",
13
- "@wyw-in-js/shared": "1.0.4",
12
+ "@wyw-in-js/processor-utils": "1.0.5",
13
+ "@wyw-in-js/shared": "1.0.5",
14
14
  "cosmiconfig": "^8.0.0",
15
15
  "happy-dom": "^20.1.0",
16
16
  "minimatch": "^9.0.5",
@@ -62,5 +62,9 @@
62
62
  "lint": "eslint --ext .js,.ts .",
63
63
  "test": "bun test src"
64
64
  },
65
- "types": "types/index.d.ts"
65
+ "types": "types/index.d.ts",
66
+ "repository": {
67
+ "type": "git",
68
+ "url": "https://github.com/Anber/wyw-in-js"
69
+ }
66
70
  }
package/types/cache.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { BarrelManifestCacheEntry } from './transform/barrelManifest';
1
2
  import type { Entrypoint } from './transform/Entrypoint';
2
3
  import type { IEvaluatedEntrypoint } from './transform/EvaluatedEntrypoint';
3
4
  interface IBaseCachedEntrypoint {
@@ -5,18 +6,27 @@ interface IBaseCachedEntrypoint {
5
6
  resolved: string | null;
6
7
  }>;
7
8
  initialCode?: string;
9
+ invalidateOnDependencyChange?: Set<string>;
10
+ invalidationDependencies?: Map<string, {
11
+ resolved: string | null;
12
+ }>;
8
13
  }
9
14
  interface ICaches<TEntrypoint extends IBaseCachedEntrypoint> {
15
+ barrelManifests: Map<string, BarrelManifestCacheEntry>;
10
16
  entrypoints: Map<string, TEntrypoint>;
11
17
  exports: Map<string, string[]>;
12
18
  }
13
19
  type MapValue<T> = T extends Map<string, infer V> ? V : never;
14
- declare const cacheNames: readonly ["entrypoints", "exports"];
20
+ declare const cacheNames: readonly ["barrelManifests", "entrypoints", "exports"];
15
21
  type CacheNames = (typeof cacheNames)[number];
16
22
  export declare class TransformCacheCollection<TEntrypoint extends IBaseCachedEntrypoint = Entrypoint | IEvaluatedEntrypoint> {
23
+ readonly barrelManifests: Map<string, BarrelManifestCacheEntry>;
17
24
  readonly entrypoints: Map<string, TEntrypoint>;
18
25
  readonly exports: Map<string, string[]>;
26
+ private readonly barrelManifestDependencies;
19
27
  private contentHashes;
28
+ private fileMtimes;
29
+ private readonly exportDependencies;
20
30
  constructor(caches?: Partial<ICaches<TEntrypoint>>);
21
31
  add<TCache extends CacheNames, TValue extends MapValue<ICaches<TEntrypoint>[TCache]>>(cacheName: TCache, key: string, value: TValue): void;
22
32
  clear(cacheName: CacheNames | 'all'): void;
@@ -25,7 +35,18 @@ export declare class TransformCacheCollection<TEntrypoint extends IBaseCachedEnt
25
35
  has(cacheName: CacheNames, key: string): boolean;
26
36
  invalidate(cacheName: CacheNames, key: string): void;
27
37
  invalidateForFile(filename: string): void;
28
- invalidateIfChanged(filename: string, content: string, previousVisitedFiles?: Set<string>, source?: 'fs' | 'loaded'): boolean;
38
+ invalidateIfChanged(filename: string, content: string, previousVisitedFiles?: Set<string>, source?: 'fs' | 'loaded', changedFiles?: Set<string>): boolean;
39
+ setCacheDependencies(cacheName: 'barrelManifests' | 'exports', key: string, dependencies: Iterable<string>): void;
40
+ private clearCacheDependencies;
41
+ private getCachedDependencies;
42
+ private getDependencyCache;
43
+ private hasCachedDependencies;
44
+ /**
45
+ * Fast check if a file changed on disk since last seen.
46
+ * Uses mtime as a fast path — only reads the file if mtime differs.
47
+ * Returns true if the file changed (cache was invalidated).
48
+ */
49
+ checkFreshness(filename: string, strippedFilename: string): boolean;
29
50
  private setContentHash;
30
51
  }
31
52
  export {};
package/types/cache.js CHANGED
@@ -12,17 +12,29 @@ const parseRequest_1 = require("./utils/parseRequest");
12
12
  function hashContent(content) {
13
13
  return (0, crypto_1.createHash)('sha256').update(content).digest('hex');
14
14
  }
15
+ function isMissingFileError(error) {
16
+ if (!error || typeof error !== 'object') {
17
+ return false;
18
+ }
19
+ const { code } = error;
20
+ return code === 'ENOENT' || code === 'ENOTDIR';
21
+ }
15
22
  const cacheLogger = shared_1.logger.extend('cache');
16
- const cacheNames = ['entrypoints', 'exports'];
23
+ const cacheNames = ['barrelManifests', 'entrypoints', 'exports'];
17
24
  const loggers = cacheNames.reduce((acc, key) => ({
18
25
  ...acc,
19
26
  [key]: cacheLogger.extend(key),
20
27
  }), {});
21
28
  class TransformCacheCollection {
29
+ barrelManifests;
22
30
  entrypoints;
23
31
  exports;
32
+ barrelManifestDependencies = new Map();
24
33
  contentHashes = new Map();
34
+ fileMtimes = new Map();
35
+ exportDependencies = new Map();
25
36
  constructor(caches = {}) {
37
+ this.barrelManifests = caches.barrelManifests || new Map();
26
38
  this.entrypoints = caches.entrypoints || new Map();
27
39
  this.exports = caches.exports || new Map();
28
40
  }
@@ -40,8 +52,10 @@ class TransformCacheCollection {
40
52
  if (value === undefined) {
41
53
  cache.delete(key);
42
54
  this.contentHashes.delete(key);
55
+ this.clearCacheDependencies(cacheName, key);
43
56
  return;
44
57
  }
58
+ this.clearCacheDependencies(cacheName, key);
45
59
  cache.set(key, value);
46
60
  if ('initialCode' in value) {
47
61
  const maybeOriginalCode = value
@@ -66,6 +80,16 @@ class TransformCacheCollection {
66
80
  catch {
67
81
  this.setContentHash(key, source, hashContent(''));
68
82
  }
83
+ return;
84
+ }
85
+ if (cacheName === 'barrelManifests') {
86
+ try {
87
+ const fileContent = node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(key), 'utf8');
88
+ this.setContentHash(key, 'fs', hashContent(fileContent));
89
+ }
90
+ catch {
91
+ this.setContentHash(key, 'fs', hashContent(''));
92
+ }
69
93
  }
70
94
  }
71
95
  clear(cacheName) {
@@ -78,6 +102,7 @@ class TransformCacheCollection {
78
102
  loggers[cacheName]('clear');
79
103
  const cache = this[cacheName];
80
104
  cache.clear();
105
+ this.clearCacheDependencies(cacheName);
81
106
  }
82
107
  delete(cacheName, key) {
83
108
  this.invalidate(cacheName, key);
@@ -101,24 +126,69 @@ class TransformCacheCollection {
101
126
  }
102
127
  loggers[cacheName]('invalidate', key);
103
128
  cache.delete(key);
129
+ this.clearCacheDependencies(cacheName, key);
104
130
  }
105
131
  invalidateForFile(filename) {
106
132
  cacheNames.forEach((cacheName) => {
107
133
  this.invalidate(cacheName, filename);
108
134
  });
109
135
  }
110
- invalidateIfChanged(filename, content, previousVisitedFiles, source = 'loaded') {
136
+ invalidateIfChanged(filename, content, previousVisitedFiles, source = 'loaded', changedFiles = new Set()) {
137
+ if (changedFiles.has(filename)) {
138
+ return true;
139
+ }
111
140
  const visitedFiles = new Set(previousVisitedFiles);
112
141
  const fileEntrypoint = this.get('entrypoints', filename);
142
+ let anyDepChanged = false;
113
143
  // We need to check all dependencies of the file
114
144
  // because they might have changed as well.
115
- if (fileEntrypoint && !visitedFiles.has(filename)) {
145
+ if (!visitedFiles.has(filename) &&
146
+ (fileEntrypoint || this.hasCachedDependencies(filename))) {
116
147
  visitedFiles.add(filename);
117
- for (const [, dependency] of fileEntrypoint.dependencies) {
148
+ const invalidateOnDependencyChange = fileEntrypoint?.invalidateOnDependencyChange;
149
+ const dependenciesToCheck = new Map();
150
+ for (const [key, dependency] of fileEntrypoint?.dependencies ?? []) {
151
+ dependenciesToCheck.set(key, dependency);
152
+ }
153
+ for (const [key, dependency,] of fileEntrypoint?.invalidationDependencies ?? []) {
154
+ if (!dependenciesToCheck.has(key)) {
155
+ dependenciesToCheck.set(key, dependency);
156
+ }
157
+ }
158
+ for (const dependencyFilename of this.getCachedDependencies(filename)) {
159
+ if (![...dependenciesToCheck.values()].some((dependency) => dependency.resolved === dependencyFilename)) {
160
+ dependenciesToCheck.set(dependencyFilename, {
161
+ resolved: dependencyFilename,
162
+ });
163
+ }
164
+ }
165
+ for (const [, dependency] of dependenciesToCheck) {
118
166
  const dependencyFilename = dependency.resolved;
119
167
  if (dependencyFilename) {
120
- const dependencyContent = node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(dependencyFilename), 'utf8');
121
- this.invalidateIfChanged(dependencyFilename, dependencyContent, visitedFiles, 'fs');
168
+ let dependencyContent;
169
+ try {
170
+ dependencyContent = node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(dependencyFilename), 'utf8');
171
+ }
172
+ catch (error) {
173
+ if (!isMissingFileError(error)) {
174
+ throw error;
175
+ }
176
+ this.invalidateForFile(dependencyFilename);
177
+ anyDepChanged = true;
178
+ // eslint-disable-next-line no-continue
179
+ continue;
180
+ }
181
+ const dependencyChanged = this.invalidateIfChanged(dependencyFilename, dependencyContent, visitedFiles, 'fs', changedFiles);
182
+ if (dependencyChanged &&
183
+ invalidateOnDependencyChange?.has(dependencyFilename)) {
184
+ cacheLogger('dependency affecting output has changed, invalidate all for %s', filename);
185
+ this.invalidateForFile(filename);
186
+ changedFiles.add(filename);
187
+ return true;
188
+ }
189
+ if (dependencyChanged) {
190
+ anyDepChanged = true;
191
+ }
122
192
  }
123
193
  }
124
194
  }
@@ -128,30 +198,120 @@ class TransformCacheCollection {
128
198
  if (previousHash === undefined) {
129
199
  const otherSource = source === 'fs' ? 'loaded' : 'fs';
130
200
  const otherHash = existing?.[otherSource];
131
- if (otherHash !== undefined && otherHash !== newHash) {
201
+ if ((otherHash !== undefined && otherHash !== newHash) || anyDepChanged) {
132
202
  cacheLogger('content has changed, invalidate all for %s', filename);
133
203
  this.setContentHash(filename, source, newHash);
134
204
  this.invalidateForFile(filename);
205
+ changedFiles.add(filename);
135
206
  return true;
136
207
  }
137
208
  this.setContentHash(filename, source, newHash);
209
+ if (anyDepChanged) {
210
+ this.invalidateForFile(filename);
211
+ changedFiles.add(filename);
212
+ return true;
213
+ }
138
214
  return false;
139
215
  }
140
- if (previousHash !== newHash) {
216
+ if (previousHash !== newHash || anyDepChanged) {
141
217
  cacheLogger('content has changed, invalidate all for %s', filename);
142
218
  this.setContentHash(filename, source, newHash);
143
219
  this.invalidateForFile(filename);
220
+ changedFiles.add(filename);
144
221
  return true;
145
222
  }
146
223
  return false;
147
224
  }
225
+ setCacheDependencies(cacheName, key, dependencies) {
226
+ const cache = this.getDependencyCache(cacheName);
227
+ const nextDependencies = new Set([...dependencies].filter((dependency) => dependency.length > 0));
228
+ if (nextDependencies.size === 0) {
229
+ cache.delete(key);
230
+ return;
231
+ }
232
+ cache.set(key, nextDependencies);
233
+ }
234
+ clearCacheDependencies(cacheName, key) {
235
+ if (cacheName === 'all') {
236
+ this.barrelManifestDependencies.clear();
237
+ this.exportDependencies.clear();
238
+ return;
239
+ }
240
+ if (cacheName === 'barrelManifests') {
241
+ if (key === undefined) {
242
+ this.barrelManifestDependencies.clear();
243
+ }
244
+ else {
245
+ this.barrelManifestDependencies.delete(key);
246
+ }
247
+ return;
248
+ }
249
+ if (cacheName === 'exports') {
250
+ if (key === undefined) {
251
+ this.exportDependencies.clear();
252
+ }
253
+ else {
254
+ this.exportDependencies.delete(key);
255
+ }
256
+ }
257
+ }
258
+ getCachedDependencies(filename) {
259
+ return new Set([
260
+ ...(this.barrelManifestDependencies.get(filename) ?? []),
261
+ ...(this.exportDependencies.get(filename) ?? []),
262
+ ]);
263
+ }
264
+ getDependencyCache(cacheName) {
265
+ return cacheName === 'barrelManifests'
266
+ ? this.barrelManifestDependencies
267
+ : this.exportDependencies;
268
+ }
269
+ hasCachedDependencies(filename) {
270
+ return this.getCachedDependencies(filename).size > 0;
271
+ }
272
+ /**
273
+ * Fast check if a file changed on disk since last seen.
274
+ * Uses mtime as a fast path — only reads the file if mtime differs.
275
+ * Returns true if the file changed (cache was invalidated).
276
+ */
277
+ checkFreshness(filename, strippedFilename) {
278
+ try {
279
+ const currentMtime = node_fs_1.default.statSync(strippedFilename).mtimeMs;
280
+ const cachedMtime = this.fileMtimes.get(filename);
281
+ if (cachedMtime !== undefined && currentMtime === cachedMtime) {
282
+ return false;
283
+ }
284
+ const content = node_fs_1.default.readFileSync(strippedFilename, 'utf-8');
285
+ this.fileMtimes.set(filename, currentMtime);
286
+ if (this.invalidateIfChanged(filename, content, undefined, 'fs')) {
287
+ return true;
288
+ }
289
+ return false;
290
+ }
291
+ catch (error) {
292
+ if (!isMissingFileError(error)) {
293
+ throw error;
294
+ }
295
+ this.invalidateForFile(filename);
296
+ return true;
297
+ }
298
+ }
148
299
  setContentHash(filename, source, hash) {
149
300
  const current = this.contentHashes.get(filename);
150
301
  if (current) {
151
302
  current[source] = hash;
152
- return;
153
303
  }
154
- this.contentHashes.set(filename, { [source]: hash });
304
+ else {
305
+ this.contentHashes.set(filename, { [source]: hash });
306
+ }
307
+ if (source === 'fs') {
308
+ try {
309
+ this.fileMtimes.set(filename, node_fs_1.default.statSync((0, parseRequest_1.stripQueryAndHash)(filename)).mtimeMs);
310
+ }
311
+ catch {
312
+ // ignore
313
+ }
314
+ }
155
315
  }
156
316
  }
157
317
  exports.TransformCacheCollection = TransformCacheCollection;
@@ -11,6 +11,7 @@ export interface IProcessedEvent {
11
11
  what: string[];
12
12
  }[];
13
13
  only: string[];
14
+ phase?: 'initial' | 'rewritten';
14
15
  type: 'dependency';
15
16
  }
16
17
  export interface IQueueActionEvent {
package/types/module.d.ts CHANGED
@@ -23,6 +23,8 @@ type HiddenModuleMembers = {
23
23
  filename: string;
24
24
  id: string;
25
25
  paths: string[];
26
+ }, isMain?: boolean, resolveOptions?: {
27
+ conditions?: Set<string>;
26
28
  }) => string;
27
29
  _nodeModulePaths(filename: string): string[];
28
30
  };
@@ -54,6 +56,7 @@ export declare class Module {
54
56
  protected get entrypoint(): Entrypoint;
55
57
  evaluate(): void;
56
58
  getEntrypoint(filename: string, only: string[], log: Debugger): Entrypoint | IEvaluatedEntrypoint | null;
59
+ private resolveWithConditions;
57
60
  resolveDependency: (id: string) => IEntrypointDependency;
58
61
  protected createChild(entrypoint: Entrypoint): Module;
59
62
  private loadByImportLoaders;
package/types/module.js CHANGED
@@ -29,6 +29,29 @@ const UnprocessedEntrypointError_1 = require("./transform/actions/UnprocessedEnt
29
29
  const importOverrides_1 = require("./utils/importOverrides");
30
30
  const parseRequest_1 = require("./utils/parseRequest");
31
31
  const createVmContext_1 = require("./vm/createVmContext");
32
+ const CJS_DEFAULT_CONDITIONS = ['require', 'node', 'default'];
33
+ function expandConditions(conditionNames) {
34
+ const result = new Set();
35
+ for (const name of conditionNames) {
36
+ if (name === '...') {
37
+ for (const d of CJS_DEFAULT_CONDITIONS)
38
+ result.add(d);
39
+ }
40
+ else {
41
+ result.add(name);
42
+ }
43
+ }
44
+ return result;
45
+ }
46
+ function isBarePackageSubpath(id) {
47
+ if (id.startsWith('.') || path_1.default.isAbsolute(id)) {
48
+ return false;
49
+ }
50
+ if (id.startsWith('@')) {
51
+ return id.split('/').length > 2;
52
+ }
53
+ return id.includes('/');
54
+ }
32
55
  exports.DefaultModuleImplementation = module_1.default;
33
56
  // Supported node builtins based on the modules polyfilled by webpack
34
57
  // `true` means module is polyfilled, `false` means module is empty
@@ -303,10 +326,15 @@ class Module {
303
326
  if (extension !== '.json' && !this.extensions.includes(extension)) {
304
327
  return null;
305
328
  }
306
- const entrypoint = this.cache.get('entrypoints', filename);
329
+ let entrypoint = this.cache.get('entrypoints', filename);
307
330
  if (entrypoint && (0, Entrypoint_helpers_1.isSuperSet)(entrypoint.evaluatedOnly ?? [], only)) {
308
- log('✅ file has been already evaluated');
309
- return entrypoint;
331
+ if (this.cache.checkFreshness(filename, strippedFilename)) {
332
+ entrypoint = undefined;
333
+ }
334
+ if (entrypoint) {
335
+ log('✅ file has been already evaluated');
336
+ return entrypoint;
337
+ }
310
338
  }
311
339
  if (entrypoint?.ignored) {
312
340
  log('✅ file has been ignored during prepare stage. Original code will be used');
@@ -355,6 +383,33 @@ class Module {
355
383
  }
356
384
  return newEntrypoint;
357
385
  }
386
+ resolveWithConditions(id, parent, conditions) {
387
+ const resolveOptions = conditions ? { conditions } : undefined;
388
+ const shouldRetryWithExtensions = conditions &&
389
+ path_1.default.extname(id) === '' &&
390
+ (id.startsWith('.') || path_1.default.isAbsolute(id) || isBarePackageSubpath(id));
391
+ try {
392
+ return this.moduleImpl._resolveFilename(id, parent, false, resolveOptions);
393
+ }
394
+ catch (e) {
395
+ if (shouldRetryWithExtensions &&
396
+ e instanceof Error &&
397
+ e.code === 'MODULE_NOT_FOUND') {
398
+ // Extensionless subpath requests (e.g. "pkg/src/*" or "./src/*") may
399
+ // resolve to extensionless targets via conditional exports. Retry with
400
+ // each known extension, but never rewrite already explicit specifiers.
401
+ for (const ext of this.extensions) {
402
+ try {
403
+ return this.moduleImpl._resolveFilename(id + ext, parent, false, resolveOptions);
404
+ }
405
+ catch {
406
+ // try next extension
407
+ }
408
+ }
409
+ }
410
+ throw e;
411
+ }
412
+ }
358
413
  resolveDependency = (id) => {
359
414
  const cached = this.entrypoint.getDependency(id);
360
415
  (0, ts_invariant_1.invariant)(!(cached instanceof Promise), 'Dependency is not resolved yet');
@@ -380,11 +435,16 @@ class Module {
380
435
  });
381
436
  const { filename } = this;
382
437
  const strippedId = (0, parseRequest_1.stripQueryAndHash)(id);
383
- let resolved = this.moduleImpl._resolveFilename(strippedId, {
438
+ const parent = {
384
439
  id: filename,
385
440
  filename,
386
441
  paths: this.moduleImpl._nodeModulePaths(path_1.default.dirname(filename)),
387
- });
442
+ };
443
+ const { conditionNames } = this.services.options.pluginOptions;
444
+ const conditions = conditionNames?.length
445
+ ? expandConditions(conditionNames)
446
+ : undefined;
447
+ let resolved = this.resolveWithConditions(strippedId, parent, conditions);
388
448
  const isFileSpecifier = strippedId.startsWith('.') || path_1.default.isAbsolute(strippedId);
389
449
  if (isFileSpecifier &&
390
450
  path_1.default.extname(strippedId) === '' &&