@wyw-in-js/transform 1.0.7 → 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 (47) hide show
  1. package/esm/cache.js +60 -5
  2. package/esm/cache.js.map +1 -1
  3. package/esm/module.js +8 -3
  4. package/esm/module.js.map +1 -1
  5. package/esm/transform/Entrypoint.js +8 -3
  6. package/esm/transform/Entrypoint.js.map +1 -1
  7. package/esm/transform/actions/BaseAction.js +2 -1
  8. package/esm/transform/actions/BaseAction.js.map +1 -1
  9. package/esm/transform/actions/actionRunner.js +2 -2
  10. package/esm/transform/actions/actionRunner.js.map +1 -1
  11. package/esm/transform/generators/processEntrypoint.js +5 -1
  12. package/esm/transform/generators/processEntrypoint.js.map +1 -1
  13. package/esm/transform/types.js.map +1 -1
  14. package/esm/transform.js +45 -23
  15. package/esm/transform.js.map +1 -1
  16. package/esm/utils/collectTemplateDependencies.js +9 -0
  17. package/esm/utils/collectTemplateDependencies.js.map +1 -1
  18. package/lib/cache.js +60 -5
  19. package/lib/cache.js.map +1 -1
  20. package/lib/module.js +10 -5
  21. package/lib/module.js.map +1 -1
  22. package/lib/transform/Entrypoint.js +8 -3
  23. package/lib/transform/Entrypoint.js.map +1 -1
  24. package/lib/transform/actions/BaseAction.js +2 -1
  25. package/lib/transform/actions/BaseAction.js.map +1 -1
  26. package/lib/transform/actions/actionRunner.js +2 -2
  27. package/lib/transform/actions/actionRunner.js.map +1 -1
  28. package/lib/transform/generators/processEntrypoint.js +5 -1
  29. package/lib/transform/generators/processEntrypoint.js.map +1 -1
  30. package/lib/transform/types.js.map +1 -1
  31. package/lib/transform.js +45 -23
  32. package/lib/transform.js.map +1 -1
  33. package/lib/utils/collectTemplateDependencies.js +9 -0
  34. package/lib/utils/collectTemplateDependencies.js.map +1 -1
  35. package/package.json +1 -1
  36. package/types/cache.d.ts +7 -0
  37. package/types/cache.js +59 -3
  38. package/types/module.js +8 -3
  39. package/types/transform/Entrypoint.d.ts +1 -1
  40. package/types/transform/Entrypoint.js +8 -3
  41. package/types/transform/actions/BaseAction.d.ts +2 -1
  42. package/types/transform/actions/BaseAction.js +3 -1
  43. package/types/transform/actions/actionRunner.js +2 -2
  44. package/types/transform/generators/processEntrypoint.js +4 -1
  45. package/types/transform/types.d.ts +1 -0
  46. package/types/transform.js +47 -23
  47. package/types/utils/collectTemplateDependencies.js +9 -0
@@ -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.7",
3
+ "version": "1.0.8",
4
4
  "dependencies": {
5
5
  "@babel/core": "^7.23.5",
6
6
  "@babel/generator": "^7.23.5",
package/types/cache.d.ts CHANGED
@@ -25,6 +25,7 @@ export declare class TransformCacheCollection<TEntrypoint extends IBaseCachedEnt
25
25
  readonly exports: Map<string, string[]>;
26
26
  private readonly barrelManifestDependencies;
27
27
  private contentHashes;
28
+ private fileMtimes;
28
29
  private readonly exportDependencies;
29
30
  constructor(caches?: Partial<ICaches<TEntrypoint>>);
30
31
  add<TCache extends CacheNames, TValue extends MapValue<ICaches<TEntrypoint>[TCache]>>(cacheName: TCache, key: string, value: TValue): void;
@@ -40,6 +41,12 @@ export declare class TransformCacheCollection<TEntrypoint extends IBaseCachedEnt
40
41
  private getCachedDependencies;
41
42
  private getDependencyCache;
42
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;
43
50
  private setContentHash;
44
51
  }
45
52
  export {};
package/types/cache.js CHANGED
@@ -12,6 +12,13 @@ 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
23
  const cacheNames = ['barrelManifests', 'entrypoints', 'exports'];
17
24
  const loggers = cacheNames.reduce((acc, key) => ({
@@ -24,6 +31,7 @@ class TransformCacheCollection {
24
31
  exports;
25
32
  barrelManifestDependencies = new Map();
26
33
  contentHashes = new Map();
34
+ fileMtimes = new Map();
27
35
  exportDependencies = new Map();
28
36
  constructor(caches = {}) {
29
37
  this.barrelManifests = caches.barrelManifests || new Map();
@@ -157,7 +165,19 @@ class TransformCacheCollection {
157
165
  for (const [, dependency] of dependenciesToCheck) {
158
166
  const dependencyFilename = dependency.resolved;
159
167
  if (dependencyFilename) {
160
- const dependencyContent = node_fs_1.default.readFileSync((0, parseRequest_1.stripQueryAndHash)(dependencyFilename), 'utf8');
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
+ }
161
181
  const dependencyChanged = this.invalidateIfChanged(dependencyFilename, dependencyContent, visitedFiles, 'fs', changedFiles);
162
182
  if (dependencyChanged &&
163
183
  invalidateOnDependencyChange?.has(dependencyFilename)) {
@@ -249,13 +269,49 @@ class TransformCacheCollection {
249
269
  hasCachedDependencies(filename) {
250
270
  return this.getCachedDependencies(filename).size > 0;
251
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
+ }
252
299
  setContentHash(filename, source, hash) {
253
300
  const current = this.contentHashes.get(filename);
254
301
  if (current) {
255
302
  current[source] = hash;
256
- return;
257
303
  }
258
- 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
+ }
259
315
  }
260
316
  }
261
317
  exports.TransformCacheCollection = TransformCacheCollection;
package/types/module.js CHANGED
@@ -326,10 +326,15 @@ class Module {
326
326
  if (extension !== '.json' && !this.extensions.includes(extension)) {
327
327
  return null;
328
328
  }
329
- const entrypoint = this.cache.get('entrypoints', filename);
329
+ let entrypoint = this.cache.get('entrypoints', filename);
330
330
  if (entrypoint && (0, Entrypoint_helpers_1.isSuperSet)(entrypoint.evaluatedOnly ?? [], only)) {
331
- log('✅ file has been already evaluated');
332
- 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
+ }
333
338
  }
334
339
  if (entrypoint?.ignored) {
335
340
  log('✅ file has been ignored during prepare stage. Original code will be used');
@@ -43,7 +43,7 @@ export declare class Entrypoint extends BaseEntrypoint {
43
43
  assertNotSuperseded(): void;
44
44
  assertTransformed(): void;
45
45
  beginProcessing(): void;
46
- createAction<TType extends ActionTypes, TAction extends ActionByType<TType>>(actionType: TType, data: TAction['data'], abortSignal?: AbortSignal | null): BaseAction<TAction>;
46
+ createAction<TType extends ActionTypes, TAction extends ActionByType<TType>>(actionType: TType, data: TAction['data'], abortSignal?: AbortSignal | null, actionContext?: unknown): BaseAction<TAction>;
47
47
  createChild(name: string, only: string[], loadedCode?: string): Entrypoint | 'loop';
48
48
  createEvaluated(): EvaluatedEntrypoint;
49
49
  endProcessing(): void;
@@ -14,6 +14,7 @@ const BaseAction_1 = require("./actions/BaseAction");
14
14
  const UnprocessedEntrypointError_1 = require("./actions/UnprocessedEntrypointError");
15
15
  const parseRequest_1 = require("../utils/parseRequest");
16
16
  const EMPTY_FILE = '=== empty file ===';
17
+ const DEFAULT_ACTION_CONTEXT = Symbol('defaultActionContext');
17
18
  function hasLoop(name, parent, processed = []) {
18
19
  if (parent.name === name || processed.includes(parent.name)) {
19
20
  return true;
@@ -201,16 +202,20 @@ class Entrypoint extends BaseEntrypoint_1.BaseEntrypoint {
201
202
  beginProcessing() {
202
203
  this.#isProcessing = true;
203
204
  }
204
- createAction(actionType, data, abortSignal = null) {
205
+ createAction(actionType, data, abortSignal = null, actionContext = DEFAULT_ACTION_CONTEXT) {
205
206
  if (!this.actionsCache.has(actionType)) {
206
207
  this.actionsCache.set(actionType, new Map());
207
208
  }
208
- const cache = this.actionsCache.get(actionType);
209
+ const contexts = this.actionsCache.get(actionType);
210
+ if (!contexts.has(actionContext)) {
211
+ contexts.set(actionContext, new Map());
212
+ }
213
+ const cache = contexts.get(actionContext);
209
214
  const cached = cache.get(data);
210
215
  if (cached && !cached.abortSignal?.aborted) {
211
216
  return cached;
212
217
  }
213
- const newAction = new BaseAction_1.BaseAction(actionType, this.services, this, data, abortSignal);
218
+ const newAction = new BaseAction_1.BaseAction(actionType, this.services, this, data, abortSignal, actionContext);
214
219
  cache.set(data, newAction);
215
220
  this.services.eventEmitter.entrypointEvent(this.seqId, {
216
221
  type: 'actionCreated',
@@ -13,13 +13,14 @@ export declare class BaseAction<TAction extends ActionQueueItem> implements GetB
13
13
  readonly entrypoint: Entrypoint;
14
14
  readonly data: TAction['data'];
15
15
  readonly abortSignal: AbortSignal | null;
16
+ readonly actionContext: unknown;
16
17
  readonly idx: string;
17
18
  result: TypeOfResult<TAction> | typeof Pending;
18
19
  private activeScenario;
19
20
  private activeScenarioError?;
20
21
  private activeScenarioNextResults;
21
22
  private handler;
22
- constructor(type: TAction['type'], services: Services, entrypoint: Entrypoint, data: TAction['data'], abortSignal: AbortSignal | null);
23
+ constructor(type: TAction['type'], services: Services, entrypoint: Entrypoint, data: TAction['data'], abortSignal: AbortSignal | null, actionContext: unknown);
23
24
  get log(): Debugger;
24
25
  get ref(): string;
25
26
  createAbortSignal(): AbortSignal & Disposable;
@@ -11,18 +11,20 @@ class BaseAction {
11
11
  entrypoint;
12
12
  data;
13
13
  abortSignal;
14
+ actionContext;
14
15
  idx;
15
16
  result = types_1.Pending;
16
17
  activeScenario = null;
17
18
  activeScenarioError;
18
19
  activeScenarioNextResults = [];
19
20
  handler = null;
20
- constructor(type, services, entrypoint, data, abortSignal) {
21
+ constructor(type, services, entrypoint, data, abortSignal, actionContext) {
21
22
  this.type = type;
22
23
  this.services = services;
23
24
  this.entrypoint = entrypoint;
24
25
  this.data = data;
25
26
  this.abortSignal = abortSignal;
27
+ this.actionContext = actionContext;
26
28
  actionIdx += 1;
27
29
  this.idx = actionIdx.toString(16).padStart(6, '0');
28
30
  }
@@ -36,7 +36,7 @@ async function asyncActionRunner(action, actionHandlers, stack = [getActionRef(a
36
36
  return result.value;
37
37
  }
38
38
  const [type, entrypoint, data, abortSignal] = result.value;
39
- const nextAction = entrypoint.createAction(type, data, abortSignal);
39
+ const nextAction = entrypoint.createAction(type, data, abortSignal, action.actionContext);
40
40
  try {
41
41
  actionResult = await asyncActionRunner(nextAction, actionHandlers, [
42
42
  ...stack,
@@ -70,7 +70,7 @@ function syncActionRunner(action, actionHandlers, stack = [getActionRef(action.t
70
70
  return result.value;
71
71
  }
72
72
  const [type, entrypoint, data, abortSignal] = result.value;
73
- const nextAction = entrypoint.createAction(type, data, abortSignal);
73
+ const nextAction = entrypoint.createAction(type, data, abortSignal, action.actionContext);
74
74
  try {
75
75
  actionResult = syncActionRunner(nextAction, actionHandlers, [
76
76
  ...stack,
@@ -57,7 +57,10 @@ const shaker_1 = require("../../shaker");
57
57
  const AbortError_1 = require("../actions/AbortError");
58
58
  const barrelManifest_1 = require("../barrelManifest");
59
59
  const shouldSkipExplodeReexports = (action) => {
60
- const { loadedAndParsed } = action.entrypoint;
60
+ const { loadedAndParsed, only } = action.entrypoint;
61
+ if (only.length === 1 && only[0] === '__wywPreval') {
62
+ return true;
63
+ }
61
64
  if (loadedAndParsed.evaluator !== shaker_1.shaker || !loadedAndParsed.ast) {
62
65
  return false;
63
66
  }
@@ -34,6 +34,7 @@ export type AnyIteratorResult<TMode extends 'async' | 'sync', TResult> = {
34
34
  sync: IteratorResult<YieldArg, TResult>;
35
35
  }[TMode];
36
36
  export interface IBaseAction<TAction extends ActionQueueItem, TResult, TData> extends IBaseNode {
37
+ actionContext: unknown;
37
38
  abortSignal: AbortSignal | null;
38
39
  createAbortSignal: () => AbortSignal & Disposable;
39
40
  data: TData;
@@ -21,6 +21,24 @@ const resolveImports_1 = require("./transform/generators/resolveImports");
21
21
  const withDefaultServices_1 = require("./transform/helpers/withDefaultServices");
22
22
  const memoizedSyncResolve = new WeakMap();
23
23
  const memoizedAsyncResolve = new WeakMap();
24
+ const EMPTY_CUSTOM_HANDLERS = {};
25
+ const memoizedActionContexts = new WeakMap();
26
+ const getActionContext = (resolveImportsHandler, customHandlers) => {
27
+ const customHandlersKey = Object.keys(customHandlers).length === 0
28
+ ? EMPTY_CUSTOM_HANDLERS
29
+ : customHandlers;
30
+ let actionContextsByHandlers = memoizedActionContexts.get(resolveImportsHandler);
31
+ if (!actionContextsByHandlers) {
32
+ actionContextsByHandlers = new WeakMap();
33
+ memoizedActionContexts.set(resolveImportsHandler, actionContextsByHandlers);
34
+ }
35
+ let actionContext = actionContextsByHandlers.get(customHandlersKey);
36
+ if (!actionContext) {
37
+ actionContext = {};
38
+ actionContextsByHandlers.set(customHandlersKey, actionContext);
39
+ }
40
+ return actionContext;
41
+ };
24
42
  function transformSync(partialServices, originalCode, syncResolve, customHandlers = {}) {
25
43
  const { options } = partialServices;
26
44
  const pluginOptions = (0, loadWywOptions_1.loadWywOptions)(options.pluginOptions);
@@ -35,6 +53,18 @@ function transformSync(partialServices, originalCode, syncResolve, customHandler
35
53
  // If global cache is disabled, we need to create a new cache for each file
36
54
  services.cache = new cache_1.TransformCacheCollection();
37
55
  }
56
+ if (!memoizedSyncResolve.has(syncResolve)) {
57
+ memoizedSyncResolve.set(syncResolve, function resolveImports() {
58
+ return resolveImports_1.syncResolveImports.call(this, syncResolve);
59
+ });
60
+ }
61
+ const resolveImportsHandler = memoizedSyncResolve.get(syncResolve);
62
+ const actionHandlers = {
63
+ ...generators_1.baseHandlers,
64
+ ...customHandlers,
65
+ resolveImports: resolveImportsHandler,
66
+ };
67
+ const actionContext = getActionContext(resolveImportsHandler, customHandlers);
38
68
  const entrypoint = Entrypoint_1.Entrypoint.createRoot(services, options.filename, ['__wywPreval'], originalCode);
39
69
  if (entrypoint.ignored) {
40
70
  return {
@@ -42,18 +72,9 @@ function transformSync(partialServices, originalCode, syncResolve, customHandler
42
72
  sourceMap: options.inputSourceMap,
43
73
  };
44
74
  }
45
- const workflowAction = entrypoint.createAction('workflow', undefined);
46
- if (!memoizedSyncResolve.has(syncResolve)) {
47
- memoizedSyncResolve.set(syncResolve, function resolveImports() {
48
- return resolveImports_1.syncResolveImports.call(this, syncResolve);
49
- });
50
- }
75
+ const workflowAction = entrypoint.createAction('workflow', undefined, null, actionContext);
51
76
  try {
52
- const result = (0, actionRunner_1.syncActionRunner)(workflowAction, {
53
- ...generators_1.baseHandlers,
54
- ...customHandlers,
55
- resolveImports: memoizedSyncResolve.get(syncResolve),
56
- });
77
+ const result = (0, actionRunner_1.syncActionRunner)(workflowAction, actionHandlers);
57
78
  entrypoint.log('%s is ready', entrypoint.name);
58
79
  return result;
59
80
  }
@@ -92,6 +113,19 @@ async function transform(partialServices, originalCode, asyncResolve, customHand
92
113
  * but the "only" option has changed, the file will be re-processed using
93
114
  * the combined "only" option.
94
115
  */
116
+ if (!memoizedAsyncResolve.has(asyncResolve)) {
117
+ const resolveImports = function resolveImports() {
118
+ return resolveImports_1.asyncResolveImports.call(this, asyncResolve);
119
+ };
120
+ memoizedAsyncResolve.set(asyncResolve, resolveImports);
121
+ }
122
+ const resolveImportsHandler = memoizedAsyncResolve.get(asyncResolve);
123
+ const actionHandlers = {
124
+ ...generators_1.baseHandlers,
125
+ ...customHandlers,
126
+ resolveImports: resolveImportsHandler,
127
+ };
128
+ const actionContext = getActionContext(resolveImportsHandler, customHandlers);
95
129
  const entrypoint = Entrypoint_1.Entrypoint.createRoot(services, options.filename, ['__wywPreval'], originalCode);
96
130
  if (entrypoint.ignored) {
97
131
  return {
@@ -99,19 +133,9 @@ async function transform(partialServices, originalCode, asyncResolve, customHand
99
133
  sourceMap: options.inputSourceMap,
100
134
  };
101
135
  }
102
- const workflowAction = entrypoint.createAction('workflow', undefined);
103
- if (!memoizedAsyncResolve.has(asyncResolve)) {
104
- const resolveImports = function resolveImports() {
105
- return resolveImports_1.asyncResolveImports.call(this, asyncResolve);
106
- };
107
- memoizedAsyncResolve.set(asyncResolve, resolveImports);
108
- }
136
+ const workflowAction = entrypoint.createAction('workflow', undefined, null, actionContext);
109
137
  try {
110
- const result = await (0, actionRunner_1.asyncActionRunner)(workflowAction, {
111
- ...generators_1.baseHandlers,
112
- ...customHandlers,
113
- resolveImports: memoizedAsyncResolve.get(asyncResolve),
114
- });
138
+ const result = await (0, actionRunner_1.asyncActionRunner)(workflowAction, actionHandlers);
115
139
  entrypoint.log('%s is ready', entrypoint.name);
116
140
  return result;
117
141
  }
@@ -18,6 +18,15 @@ const valueToLiteral_1 = require("./valueToLiteral");
18
18
  function staticEval(ex, evaluate = false) {
19
19
  if (!evaluate)
20
20
  return undefined;
21
+ if (ex.isIdentifier()) {
22
+ const binding = ex.scope.getBinding(ex.node.name);
23
+ // Babel may "evaluate" a destructured binding to its source container
24
+ // object/array instead of the bound value, which changes template semantics.
25
+ if (binding?.path.isVariableDeclarator() &&
26
+ !binding.path.get('id').isIdentifier()) {
27
+ return undefined;
28
+ }
29
+ }
21
30
  const result = ex.evaluate();
22
31
  if (result.confident && !(0, shared_1.hasEvalMeta)(result.value)) {
23
32
  return [result.value];