BaseIdentifierObfuscatingReplacer.ts 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { inject, injectable, } from 'inversify';
  2. import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
  3. import * as ESTree from 'estree';
  4. import { TIdentifierNamesGeneratorFactory } from '../../../../types/container/generators/TIdentifierNamesGeneratorFactory';
  5. import { TNodeWithLexicalScope } from '../../../../types/node/TNodeWithLexicalScope';
  6. import { IIdentifierNamesGenerator } from '../../../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
  7. import { IIdentifierObfuscatingReplacer } from '../../../../interfaces/node-transformers/obfuscating-transformers/obfuscating-replacers/IIdentifierObfuscatingReplacer';
  8. import { IOptions } from '../../../../interfaces/options/IOptions';
  9. import { AbstractObfuscatingReplacer } from '../AbstractObfuscatingReplacer';
  10. import { NodeFactory } from '../../../../node/NodeFactory';
  11. @injectable()
  12. export class BaseIdentifierObfuscatingReplacer extends AbstractObfuscatingReplacer implements IIdentifierObfuscatingReplacer {
  13. /**
  14. * @type {IIdentifierNamesGenerator}
  15. */
  16. private readonly identifierNamesGenerator: IIdentifierNamesGenerator;
  17. /**
  18. * @type {Map<TNodeWithLexicalScope, Map<string, string>>}
  19. */
  20. private readonly blockScopesMap: Map<TNodeWithLexicalScope, Map<string, string>> = new Map();
  21. /**
  22. * @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
  23. * @param {IOptions} options
  24. */
  25. constructor (
  26. @inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
  27. identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
  28. @inject(ServiceIdentifiers.IOptions) options: IOptions
  29. ) {
  30. super(options);
  31. this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
  32. }
  33. /**
  34. * @param {Identifier} identifierNode
  35. * @param {TNodeWithLexicalScope} lexicalScopeNode
  36. * @returns {Identifier}
  37. */
  38. public replace (identifierNode: ESTree.Identifier, lexicalScopeNode: TNodeWithLexicalScope): ESTree.Identifier {
  39. let identifierName: string = identifierNode.name;
  40. if (this.blockScopesMap.has(lexicalScopeNode)) {
  41. const namesMap: Map<string, string> = <Map<string, string>>this.blockScopesMap.get(lexicalScopeNode);
  42. if (namesMap.has(identifierName)) {
  43. identifierName = <string>namesMap.get(identifierName);
  44. }
  45. }
  46. return NodeFactory.identifierNode(identifierName);
  47. }
  48. /**
  49. * Store `nodeName` of global identifiers as key in map with random name as value.
  50. * Reserved name will be ignored.
  51. *
  52. * @param {Node} identifierNode
  53. * @param {TNodeWithLexicalScope} lexicalScopeNode
  54. */
  55. public storeGlobalName (identifierNode: ESTree.Identifier, lexicalScopeNode: TNodeWithLexicalScope): void {
  56. const identifierName: string = identifierNode.name;
  57. if (this.isReservedName(identifierName)) {
  58. return;
  59. }
  60. const newIdentifierName: string = this.identifierNamesGenerator.generateWithPrefix();
  61. if (!this.blockScopesMap.has(lexicalScopeNode)) {
  62. this.blockScopesMap.set(lexicalScopeNode, new Map());
  63. }
  64. const namesMap: Map<string, string> = <Map<string, string>>this.blockScopesMap.get(lexicalScopeNode);
  65. namesMap.set(identifierName, newIdentifierName);
  66. }
  67. /**
  68. * Store `nodeName` of local identifier as key in map with random name as value.
  69. * Reserved name will be ignored.
  70. *
  71. * @param {Identifier} identifierNode
  72. * @param {TNodeWithLexicalScope} lexicalScopeNode
  73. */
  74. public storeLocalName (identifierNode: ESTree.Identifier, lexicalScopeNode: TNodeWithLexicalScope): void {
  75. const identifierName: string = identifierNode.name;
  76. if (this.isReservedName(identifierName)) {
  77. return;
  78. }
  79. const newIdentifierName: string = this.identifierNamesGenerator.generate();
  80. if (!this.blockScopesMap.has(lexicalScopeNode)) {
  81. this.blockScopesMap.set(lexicalScopeNode, new Map());
  82. }
  83. const namesMap: Map<string, string> = <Map<string, string>>this.blockScopesMap.get(lexicalScopeNode);
  84. namesMap.set(identifierName, newIdentifierName);
  85. }
  86. /**
  87. * Preserve `name` to protect it from further using.
  88. *
  89. * @param {string} name
  90. */
  91. public preserveName (name: string): void {
  92. this.identifierNamesGenerator.preserveName(name);
  93. }
  94. /**
  95. * @param {string} name
  96. * @returns {boolean}
  97. */
  98. private isReservedName (name: string): boolean {
  99. if (!this.options.reservedNames.length) {
  100. return false;
  101. }
  102. return this.options.reservedNames
  103. .some((reservedName: string) => {
  104. return new RegExp(reservedName, 'g').exec(name) !== null;
  105. });
  106. }
  107. }