@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.
- package/esm/cache.js +160 -12
- package/esm/cache.js.map +1 -1
- package/esm/debug/fileReporter.js.map +1 -1
- package/esm/module.js +59 -5
- package/esm/module.js.map +1 -1
- package/esm/plugins/shaker.js +152 -13
- package/esm/plugins/shaker.js.map +1 -1
- package/esm/shaker.js +51 -23
- package/esm/shaker.js.map +1 -1
- package/esm/transform/BaseEntrypoint.js +3 -1
- package/esm/transform/BaseEntrypoint.js.map +1 -1
- package/esm/transform/Entrypoint.js +68 -20
- package/esm/transform/Entrypoint.js.map +1 -1
- package/esm/transform/EvaluatedEntrypoint.js.map +1 -1
- package/esm/transform/actions/BaseAction.js +2 -1
- package/esm/transform/actions/BaseAction.js.map +1 -1
- package/esm/transform/actions/actionRunner.js +2 -2
- package/esm/transform/actions/actionRunner.js.map +1 -1
- package/esm/transform/barrelManifest.js +291 -0
- package/esm/transform/barrelManifest.js.map +1 -0
- package/esm/transform/generators/getExports.js +5 -0
- package/esm/transform/generators/getExports.js.map +1 -1
- package/esm/transform/generators/processEntrypoint.js +31 -1
- package/esm/transform/generators/processEntrypoint.js.map +1 -1
- package/esm/transform/generators/resolveImports.js +29 -5
- package/esm/transform/generators/resolveImports.js.map +1 -1
- package/esm/transform/generators/rewriteBarrelImports.js +733 -0
- package/esm/transform/generators/rewriteBarrelImports.js.map +1 -0
- package/esm/transform/generators/transform.js +154 -21
- package/esm/transform/generators/transform.js.map +1 -1
- package/esm/transform/types.js.map +1 -1
- package/esm/transform.js +45 -23
- package/esm/transform.js.map +1 -1
- package/esm/utils/collectTemplateDependencies.js +9 -0
- package/esm/utils/collectTemplateDependencies.js.map +1 -1
- package/lib/cache.js +163 -12
- package/lib/cache.js.map +1 -1
- package/lib/debug/fileReporter.js.map +1 -1
- package/lib/module.js +61 -7
- package/lib/module.js.map +1 -1
- package/lib/plugins/shaker.js +152 -13
- package/lib/plugins/shaker.js.map +1 -1
- package/lib/shaker.js +58 -26
- package/lib/shaker.js.map +1 -1
- package/lib/transform/BaseEntrypoint.js +3 -1
- package/lib/transform/BaseEntrypoint.js.map +1 -1
- package/lib/transform/Entrypoint.js +69 -20
- package/lib/transform/Entrypoint.js.map +1 -1
- package/lib/transform/EvaluatedEntrypoint.js.map +1 -1
- package/lib/transform/actions/BaseAction.js +2 -1
- package/lib/transform/actions/BaseAction.js.map +1 -1
- package/lib/transform/actions/actionRunner.js +2 -2
- package/lib/transform/actions/actionRunner.js.map +1 -1
- package/lib/transform/barrelManifest.js +300 -0
- package/lib/transform/barrelManifest.js.map +1 -0
- package/lib/transform/generators/getExports.js +5 -0
- package/lib/transform/generators/getExports.js.map +1 -1
- package/lib/transform/generators/processEntrypoint.js +31 -1
- package/lib/transform/generators/processEntrypoint.js.map +1 -1
- package/lib/transform/generators/resolveImports.js +29 -5
- package/lib/transform/generators/resolveImports.js.map +1 -1
- package/lib/transform/generators/rewriteBarrelImports.js +743 -0
- package/lib/transform/generators/rewriteBarrelImports.js.map +1 -0
- package/lib/transform/generators/transform.js +158 -22
- package/lib/transform/generators/transform.js.map +1 -1
- package/lib/transform/types.js.map +1 -1
- package/lib/transform.js +45 -23
- package/lib/transform.js.map +1 -1
- package/lib/utils/collectTemplateDependencies.js +9 -0
- package/lib/utils/collectTemplateDependencies.js.map +1 -1
- package/package.json +8 -4
- package/types/cache.d.ts +23 -2
- package/types/cache.js +170 -10
- package/types/debug/fileReporter.d.ts +1 -0
- package/types/module.d.ts +3 -0
- package/types/module.js +65 -5
- package/types/plugins/shaker.js +161 -16
- package/types/shaker.d.ts +10 -1
- package/types/shaker.js +56 -28
- package/types/transform/BaseEntrypoint.d.ts +3 -1
- package/types/transform/BaseEntrypoint.js +5 -1
- package/types/transform/Entrypoint.d.ts +10 -1
- package/types/transform/Entrypoint.js +81 -23
- package/types/transform/EvaluatedEntrypoint.d.ts +2 -0
- package/types/transform/actions/BaseAction.d.ts +2 -1
- package/types/transform/actions/BaseAction.js +3 -1
- package/types/transform/actions/actionRunner.js +2 -2
- package/types/transform/barrelManifest.d.ts +42 -0
- package/types/transform/barrelManifest.js +300 -0
- package/types/transform/generators/getExports.js +5 -0
- package/types/transform/generators/processEntrypoint.js +29 -1
- package/types/transform/generators/resolveImports.js +29 -5
- package/types/transform/generators/rewriteBarrelImports.d.ts +15 -0
- package/types/transform/generators/rewriteBarrelImports.js +815 -0
- package/types/transform/generators/transform.js +148 -19
- package/types/transform/types.d.ts +3 -0
- package/types/transform.js +47 -23
- package/types/utils/collectTemplateDependencies.js +9 -0
package/lib/transform.js.map
CHANGED
|
@@ -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":"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","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.
|
|
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.
|
|
13
|
-
"@wyw-in-js/shared": "1.0.
|
|
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 (
|
|
145
|
+
if (!visitedFiles.has(filename) &&
|
|
146
|
+
(fileEntrypoint || this.hasCachedDependencies(filename))) {
|
|
116
147
|
visitedFiles.add(filename);
|
|
117
|
-
|
|
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
|
-
|
|
121
|
-
|
|
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
|
-
|
|
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;
|
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
|
-
|
|
329
|
+
let entrypoint = this.cache.get('entrypoints', filename);
|
|
307
330
|
if (entrypoint && (0, Entrypoint_helpers_1.isSuperSet)(entrypoint.evaluatedOnly ?? [], only)) {
|
|
308
|
-
|
|
309
|
-
|
|
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
|
-
|
|
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) === '' &&
|