ObjectExpressionToVariableDeclarationExtractor.ts 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. import { inject, injectable } from 'inversify';
  2. import { ServiceIdentifiers } from '../../../container/ServiceIdentifiers';
  3. import * as ESTree from 'estree';
  4. import { TNodeWithStatements } from '../../../types/node/TNodeWithStatements';
  5. import { TObjectExpressionKeysTransformerCustomNodeFactory } from '../../../types/container/custom-nodes/TObjectExpressionKeysTransformerCustomNodeFactory';
  6. import { TPropertiesExtractorResult } from '../../../types/node-transformers/TPropertiesExtractorResult';
  7. import { TStatement } from '../../../types/node/TStatement';
  8. import { ICustomNode } from '../../../interfaces/custom-nodes/ICustomNode';
  9. import { TInitialData } from '../../../types/TInitialData';
  10. import { IPropertiesExtractor } from '../../../interfaces/node-transformers/converting-transformers/properties-extractors/IPropertiesExtractor';
  11. import { ObjectExpressionKeysTransformerCustomNode } from '../../../enums/custom-nodes/ObjectExpressionKeysTransformerCustomNode';
  12. import { BasePropertiesExtractorObjectExpressionHostNode } from '../../../custom-nodes/object-expression-keys-transformer-nodes/BasePropertiesExtractorObjectExpressionHostNode';
  13. import { NodeAppender } from '../../../node/NodeAppender';
  14. import { NodeGuards } from '../../../node/NodeGuards';
  15. import { NodeStatementUtils } from '../../../node/NodeStatementUtils';
  16. import { NodeUtils } from '../../../node/NodeUtils';
  17. @injectable()
  18. export class ObjectExpressionToVariableDeclarationExtractor implements IPropertiesExtractor {
  19. /**
  20. * @type {TObjectExpressionKeysTransformerCustomNodeFactory}
  21. */
  22. private readonly objectExpressionKeysTransformerCustomNodeFactory: TObjectExpressionKeysTransformerCustomNodeFactory;
  23. /**
  24. * @param {TObjectExpressionKeysTransformerCustomNodeFactory} objectExpressionKeysTransformerCustomNodeFactory
  25. */
  26. constructor (
  27. @inject(ServiceIdentifiers.Factory__IObjectExpressionKeysTransformerCustomNode)
  28. objectExpressionKeysTransformerCustomNodeFactory: TObjectExpressionKeysTransformerCustomNodeFactory,
  29. ) {
  30. this.objectExpressionKeysTransformerCustomNodeFactory = objectExpressionKeysTransformerCustomNodeFactory;
  31. }
  32. /**
  33. * extracts object expression:
  34. * var object = {
  35. * foo: 1,
  36. * bar: 2
  37. * };
  38. *
  39. * to:
  40. * var _0xabc123 = {
  41. * foo: 1,
  42. * bar: 2
  43. * };
  44. * var object = _0xabc123;
  45. *
  46. * @param {ObjectExpression} objectExpressionNode
  47. * @param {Statement} hostStatement
  48. * @returns {TPropertiesExtractorResult}
  49. */
  50. public extract (
  51. objectExpressionNode: ESTree.ObjectExpression,
  52. hostStatement: ESTree.Statement
  53. ): TPropertiesExtractorResult {
  54. return this.transformObjectExpressionToVariableDeclaration(
  55. objectExpressionNode,
  56. hostStatement
  57. );
  58. }
  59. /**
  60. * @param {ObjectExpression} objectExpressionNode
  61. * @param {Statement} hostStatement
  62. * @returns {Node}
  63. */
  64. private transformObjectExpressionToVariableDeclaration (
  65. objectExpressionNode: ESTree.ObjectExpression,
  66. hostStatement: ESTree.Statement
  67. ): TPropertiesExtractorResult {
  68. const properties: ESTree.Property[] = objectExpressionNode.properties;
  69. const newObjectExpressionHostStatement: ESTree.VariableDeclaration = this.getObjectExpressionHostNode(properties);
  70. const newObjectExpressionIdentifier: ESTree.Identifier = this.getObjectExpressionIdentifierNode(newObjectExpressionHostStatement);
  71. const newObjectExpressionNode: ESTree.ObjectExpression = this.getObjectExpressionNode(newObjectExpressionHostStatement);
  72. const statementsToInsert: TStatement[] = [newObjectExpressionHostStatement];
  73. const hostNodeWithStatements: TNodeWithStatements = NodeStatementUtils.getScopeOfNode(hostStatement);
  74. NodeAppender.insertBefore(hostNodeWithStatements, statementsToInsert, hostStatement);
  75. NodeUtils.parentizeAst(newObjectExpressionHostStatement);
  76. NodeUtils.parentizeNode(newObjectExpressionHostStatement, hostNodeWithStatements);
  77. return {
  78. nodeToReplace: newObjectExpressionIdentifier,
  79. objectExpressionHostStatement: newObjectExpressionHostStatement,
  80. objectExpressionNode: newObjectExpressionNode
  81. };
  82. }
  83. /**
  84. * @param {Property[]} properties
  85. * @returns {VariableDeclaration}
  86. */
  87. private getObjectExpressionHostNode (properties: ESTree.Property[]): ESTree.VariableDeclaration {
  88. const objectExpressionHostCustomNode: ICustomNode<TInitialData<BasePropertiesExtractorObjectExpressionHostNode>> =
  89. this.objectExpressionKeysTransformerCustomNodeFactory(
  90. ObjectExpressionKeysTransformerCustomNode.BasePropertiesExtractorObjectExpressionHostNode
  91. );
  92. objectExpressionHostCustomNode.initialize(properties);
  93. const statementNode: TStatement = objectExpressionHostCustomNode.getNode()[0];
  94. if (
  95. !statementNode
  96. || !NodeGuards.isVariableDeclarationNode(statementNode)
  97. ) {
  98. throw new Error(`\`objectExpressionHostCustomNode.getNode()[0]\` should returns array with \`VariableDeclaration\` node`);
  99. }
  100. return statementNode;
  101. }
  102. /**
  103. * @param {VariableDeclaration} objectExpressionHostNode
  104. * @returns {Identifier}
  105. */
  106. private getObjectExpressionIdentifierNode (objectExpressionHostNode: ESTree.VariableDeclaration): ESTree.Identifier {
  107. const newObjectExpressionIdentifierNode: ESTree.Pattern = objectExpressionHostNode.declarations[0].id;
  108. if (!NodeGuards.isIdentifierNode(newObjectExpressionIdentifierNode)) {
  109. throw new Error(`\`objectExpressionHostNode\` should contain \`VariableDeclarator\` node with \`Identifier\` id property`);
  110. }
  111. return newObjectExpressionIdentifierNode;
  112. }
  113. /**
  114. * @param {VariableDeclaration} objectExpressionHostNode
  115. * @returns {Identifier}
  116. */
  117. private getObjectExpressionNode (objectExpressionHostNode: ESTree.VariableDeclaration): ESTree.ObjectExpression {
  118. const newObjectExpressionNode: ESTree.Expression | null = objectExpressionHostNode.declarations[0].init ?? null;
  119. if (!newObjectExpressionNode || !NodeGuards.isObjectExpressionNode(newObjectExpressionNode)) {
  120. throw new Error(`\`objectExpressionHostNode\` should contain \`VariableDeclarator\` node with \`ObjectExpression\` init property`);
  121. }
  122. return newObjectExpressionNode;
  123. }
  124. }