Added TaggedTemplateExpression converting to the es5 code

This commit is contained in:
sanex
2020-08-21 11:42:25 +03:00
parent 398da36257
commit 7ccd906c32
13 changed files with 34371 additions and 28 deletions
+17332 -1
View File
File diff suppressed because one or more lines are too long
+16558 -1
View File
File diff suppressed because one or more lines are too long
+1
View File
@@ -85,6 +85,7 @@ export class JavaScriptObfuscator implements IJavaScriptObfuscator {
NodeTransformer.ParentificationTransformer,
NodeTransformer.ScopeIdentifiersTransformer,
NodeTransformer.SplitStringTransformer,
NodeTransformer.TaggedTemplateExpressionTransformer,
NodeTransformer.TemplateLiteralTransformer,
NodeTransformer.VariableDeclarationsMergeTransformer,
NodeTransformer.VariablePreserveTransformer
@@ -28,6 +28,8 @@ import { SelfDefendingUnicodeCodeHelper } from '../../../custom-code-helpers/sel
import { StringArrayCallsWrapperCodeHelper } from '../../../custom-code-helpers/string-array/StringArrayCallsWrapperCodeHelper';
import { StringArrayCodeHelper } from '../../../custom-code-helpers/string-array/StringArrayCodeHelper';
import { StringArrayRotateFunctionCodeHelper } from '../../../custom-code-helpers/string-array/StringArrayRotateFunctionCodeHelper';
import { TaggedTemplateLiteralCodeHelper } from '../../../custom-code-helpers/tagged-template-expression/TaggedTemplateLiteralCodeHelper';
import { TemplateObjectCodeHelper } from '../../../custom-code-helpers/tagged-template-expression/TemplateObjectCodeHelper';
export const customCodeHelpersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
// custom code helpers
@@ -71,6 +73,14 @@ export const customCodeHelpersModule: interfaces.ContainerModule = new Container
.to(StringArrayRotateFunctionCodeHelper)
.whenTargetNamed(CustomCodeHelper.StringArrayRotateFunction);
bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
.to(TaggedTemplateLiteralCodeHelper)
.whenTargetNamed(CustomCodeHelper.TaggedTemplateLiteralCodeHelper);
bind<ICustomCodeHelper>(ServiceIdentifiers.ICustomCodeHelper)
.to(TemplateObjectCodeHelper)
.whenTargetNamed(CustomCodeHelper.TemplateObjectCodeHelper);
// code helper groups
bind<ICustomCodeHelperGroup>(ServiceIdentifiers.ICustomCodeHelperGroup)
.to(ConsoleOutputCodeHelperGroup)
@@ -17,6 +17,7 @@ import { ObjectExpressionKeysTransformer } from '../../../node-transformers/conv
import { ObjectExpressionTransformer } from '../../../node-transformers/converting-transformers/ObjectExpressionTransformer';
import { ObjectPatternPropertiesTransformer } from '../../../node-transformers/converting-transformers/ObjectPatternPropertiesTransformer';
import { SplitStringTransformer } from '../../../node-transformers/converting-transformers/SplitStringTransformer';
import { TaggedTemplateExpressionTransformer } from '../../../node-transformers/converting-transformers/TaggedTemplateExpressionTransformer';
import { TemplateLiteralTransformer } from '../../../node-transformers/converting-transformers/TemplateLiteralTransformer';
export const convertingTransformersModule: interfaces.ContainerModule = new ContainerModule((bind: interfaces.Bind) => {
@@ -50,6 +51,10 @@ export const convertingTransformersModule: interfaces.ContainerModule = new Cont
.to(SplitStringTransformer)
.whenTargetNamed(NodeTransformer.SplitStringTransformer);
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(TaggedTemplateExpressionTransformer)
.whenTargetNamed(NodeTransformer.TaggedTemplateExpressionTransformer);
bind<INodeTransformer>(ServiceIdentifiers.INodeTransformer)
.to(TemplateLiteralTransformer)
.whenTargetNamed(NodeTransformer.TemplateLiteralTransformer);
@@ -0,0 +1,76 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { TStatement } from '../../types/node/TStatement';
import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { initializable } from '../../decorators/Initializable';
import { TaggedTemplateLiteralTemplate } from './templates/tagged-template-literal/TaggedTemplateLiteralTemplate';
import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
import { NodeUtils } from '../../node/NodeUtils';
@injectable()
export class TaggedTemplateLiteralCodeHelper extends AbstractCustomCodeHelper {
/**
* @type {string}
*/
@initializable()
private taggedTemplateLiteralHelperName!: string;
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
* @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
public constructor (
@inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
@inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
@inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(
identifierNamesGeneratorFactory,
customCodeHelperFormatter,
customCodeHelperObfuscator,
randomGenerator,
options
);
}
/**
* @param {string} taggedTemplateLiteralHelperName
*/
public initialize (
taggedTemplateLiteralHelperName: string
): void {
this.taggedTemplateLiteralHelperName = taggedTemplateLiteralHelperName;
}
/**
* @param {string} codeHelperTemplate
* @returns {TStatement[]}
*/
protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
return NodeUtils.convertCodeToStructure(codeHelperTemplate);
}
/**
* @returns {string}
*/
protected getCodeHelperTemplate (): string {
return this.customCodeHelperFormatter.formatTemplate(TaggedTemplateLiteralTemplate(), {
taggedTemplateLiteralHelperName: this.taggedTemplateLiteralHelperName
});
}
}
@@ -0,0 +1,132 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { TStatement } from '../../types/node/TStatement';
import { ICustomCodeHelperFormatter } from '../../interfaces/custom-code-helpers/ICustomCodeHelperFormatter';
import { ICustomCodeHelperObfuscator } from '../../interfaces/custom-code-helpers/ICustomCodeHelperObfuscator';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { initializable } from '../../decorators/Initializable';
import { TemplateObjectTemplate } from './templates/template-object/TemplateObjectTemplate';
import { AbstractCustomCodeHelper } from '../AbstractCustomCodeHelper';
import { NodeUtils } from '../../node/NodeUtils';
import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
@injectable()
export class TemplateObjectCodeHelper extends AbstractCustomCodeHelper {
/**
* @type {string}
*/
@initializable()
private taggedTemplateLiteralHelperName!: string;
/**
* @type {string}
*/
@initializable()
private templateObjectHelperName!: string;
/**
* @type {string[]}
*/
@initializable()
private templateObjectValues!: string[];
/**
* @type {string[] | null}
*/
@initializable()
private templateObjectRawValues!: string[] | null;
/**
* @type {IEscapeSequenceEncoder}
*/
private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
/**
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {ICustomCodeHelperFormatter} customCodeHelperFormatter
* @param {ICustomCodeHelperObfuscator} customCodeHelperObfuscator
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
*/
public constructor (
@inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
@inject(ServiceIdentifiers.ICustomCodeHelperFormatter) customCodeHelperFormatter: ICustomCodeHelperFormatter,
@inject(ServiceIdentifiers.ICustomCodeHelperObfuscator) customCodeHelperObfuscator: ICustomCodeHelperObfuscator,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
) {
super(
identifierNamesGeneratorFactory,
customCodeHelperFormatter,
customCodeHelperObfuscator,
randomGenerator,
options
);
this.escapeSequenceEncoder = escapeSequenceEncoder;
}
/**
* @param {string} templateObjectHelperName
* @param {string} taggedTemplateLiteralHelperName
* @param {string[]} templateObjectValues
* @param {string[] | null} templateObjectRawValues
*/
public initialize (
templateObjectHelperName: string,
taggedTemplateLiteralHelperName: string,
templateObjectValues: string[],
templateObjectRawValues: string[] | null,
): void {
this.templateObjectHelperName = templateObjectHelperName;
this.taggedTemplateLiteralHelperName = taggedTemplateLiteralHelperName;
this.templateObjectValues = templateObjectValues;
this.templateObjectRawValues = templateObjectRawValues;
}
/**
* @param {string} codeHelperTemplate
* @returns {TStatement[]}
*/
protected getNodeStructure (codeHelperTemplate: string): TStatement[] {
return NodeUtils.convertCodeToStructure(codeHelperTemplate);
}
/**
* @returns {string}
*/
protected getCodeHelperTemplate (): string {
return this.customCodeHelperFormatter.formatTemplate(TemplateObjectTemplate(), {
taggedTemplateLiteralHelperName: this.taggedTemplateLiteralHelperName,
templateObjectHelperName: this.templateObjectHelperName,
templateObjectValues: this.formatTemplateObjectValuesToString(this.templateObjectValues),
templateObjectRawValues: this.templateObjectRawValues
? this.formatTemplateObjectValuesToString(this.templateObjectRawValues)
: undefined
});
}
/**
* @param {string[]} values
* @returns {string}
*/
private formatTemplateObjectValuesToString (values: string[]): string {
return values
.map((value: string) => `'${this.escapeSequenceEncoder.encode(
value,
this.options.unicodeEscapeSequence
)}'`)
.toString();
}
}
@@ -0,0 +1,18 @@
/**
* @returns {string}
*/
export function TaggedTemplateLiteralTemplate (): string {
return `
function {taggedTemplateLiteralHelperName} (strings, raw) {
if (!raw || !raw.length) {
raw = strings.slice(0);
}
return Object.freeze(Object.defineProperties(strings, {
raw: {
value: Object.freeze(raw)
}
}));
}
`;
}
@@ -0,0 +1,16 @@
/**
* @returns {string}
*/
export function TemplateObjectTemplate (): string {
return `
function {templateObjectHelperName} () {
const data = {taggedTemplateLiteralHelperName}([{templateObjectValues}], [{templateObjectRawValues}]);
{templateObjectHelperName} = function() {
return data;
};
return data;
}
`;
}
@@ -8,5 +8,7 @@ export enum CustomCodeHelper {
SelfDefendingUnicode = 'SelfDefendingUnicode',
StringArrayCallsWrapper = 'StringArrayCallsWrapper',
StringArray = 'StringArray',
StringArrayRotateFunction = 'StringArrayRotateFunction'
StringArrayRotateFunction = 'StringArrayRotateFunction',
TaggedTemplateLiteralCodeHelper = 'TaggedTemplateLiteralCodeHelper',
TemplateObjectCodeHelper = 'TemplateObjectCodeHelper'
}
@@ -23,6 +23,7 @@ export enum NodeTransformer {
ScopeIdentifiersTransformer = 'ScopeIdentifiersTransformer',
ScopeThroughIdentifiersTransformer = 'ScopeThroughIdentifiersTransformer',
SplitStringTransformer = 'SplitStringTransformer',
TaggedTemplateExpressionTransformer = 'TaggedTemplateExpressionTransformer',
TemplateLiteralTransformer = 'TemplateLiteralTransformer',
VariableDeclarationsMergeTransformer = 'VariableDeclarationsMergeTransformer',
VariablePreserveTransformer = 'VariablePreserveTransformer'
@@ -0,0 +1,200 @@
import { inject, injectable, } from 'inversify';
import { ServiceIdentifiers } from '../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { TCustomCodeHelperFactory } from '../../types/container/custom-code-helpers/TCustomCodeHelperFactory';
import { TIdentifierNamesGeneratorFactory } from '../../types/container/generators/TIdentifierNamesGeneratorFactory';
import { TInitialData } from '../../types/TInitialData';
import { TNodeWithStatements } from '../../types/node/TNodeWithStatements';
import { ICustomCodeHelper } from '../../interfaces/custom-code-helpers/ICustomCodeHelper';
import { IIdentifierNamesGenerator } from '../../interfaces/generators/identifier-names-generators/IIdentifierNamesGenerator';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IVisitor } from '../../interfaces/node-transformers/IVisitor';
import { NodeTransformationStage } from '../../enums/node-transformers/NodeTransformationStage';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { CustomCodeHelper } from '../../enums/custom-code-helpers/CustomCodeHelper';
import { NodeAppender } from '../../node/NodeAppender';
import { NodeFactory } from '../../node/NodeFactory';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeStatementUtils } from '../../node/NodeStatementUtils';
import { NodeUtils } from '../../node/NodeUtils';
import { TaggedTemplateLiteralCodeHelper } from '../../custom-code-helpers/tagged-template-expression/TaggedTemplateLiteralCodeHelper';
import { TemplateObjectCodeHelper } from '../../custom-code-helpers/tagged-template-expression/TemplateObjectCodeHelper';
/**
* Transform ES2015 tagged template expressions to ES5
* Thanks to Babel for algorithm
*/
@injectable()
export class TaggedTemplateExpressionTransformer extends AbstractNodeTransformer {
/**
* @type {TCustomCodeHelperFactory}
*/
private readonly customCodeHelperFactory: TCustomCodeHelperFactory;
/**
* @type {IIdentifierNamesGenerator}
*/
private readonly identifierNamesGenerator: IIdentifierNamesGenerator;
/**
* @type {boolean}
*/
private isTaggedTemplateLiteralHelperAppended: boolean = false;
/**
* @type {string | null}
*/
private readonly taggedTemplateLiteralHelperName: string | null = null;
/**
* @param {TCustomCodeHelperFactory} customCodeHelperFactory
* @param {TIdentifierNamesGeneratorFactory} identifierNamesGeneratorFactory
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
public constructor (
@inject(ServiceIdentifiers.Factory__ICustomCodeHelper)
customCodeHelperFactory: TCustomCodeHelperFactory,
@inject(ServiceIdentifiers.Factory__IIdentifierNamesGenerator)
identifierNamesGeneratorFactory: TIdentifierNamesGeneratorFactory,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(randomGenerator, options);
this.customCodeHelperFactory = customCodeHelperFactory;
this.identifierNamesGenerator = identifierNamesGeneratorFactory(options);
if (!this.taggedTemplateLiteralHelperName) {
this.taggedTemplateLiteralHelperName = this.identifierNamesGenerator.generateForGlobalScope();
}
}
/**
* @param {NodeTransformationStage} nodeTransformationStage
* @returns {IVisitor | null}
*/
public getVisitor (nodeTransformationStage: NodeTransformationStage): IVisitor | null {
switch (nodeTransformationStage) {
case NodeTransformationStage.Converting:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): ESTree.Node | undefined => {
if (parentNode && NodeGuards.isTaggedTemplateExpressionNode(node)) {
return this.transformNode(node, parentNode);
}
}
};
default:
return null;
}
}
/**
* @param {TaggedTemplateExpression} taggedTemplateExpression
* @param {Node} parentNode
* @returns {Node}
*/
public transformNode (taggedTemplateExpression: ESTree.TaggedTemplateExpression, parentNode: ESTree.Node): ESTree.Node {
if (!this.taggedTemplateLiteralHelperName) {
throw new Error('`TaggedTemplateLiteral` code helper name is not set');
}
const parentNodesWithStatements: TNodeWithStatements[] = NodeStatementUtils.getParentNodesWithStatements(parentNode);
const rootNodeWithStatements: TNodeWithStatements | null =
parentNodesWithStatements[parentNodesWithStatements.length - 1] ?? null;
if (!rootNodeWithStatements || !NodeGuards.isProgramNode(rootNodeWithStatements)) {
return taggedTemplateExpression;
}
const templateObjectHelperName: string = this.identifierNamesGenerator.generateForGlobalScope();
this.appendTemplateLiteralCustomCodeHelper(rootNodeWithStatements);
this.appendTemplateObjectCustomCodeHelper(
rootNodeWithStatements,
templateObjectHelperName,
taggedTemplateExpression.quasi.quasis
);
const templateObjectCallExpressionNode: ESTree.CallExpression = NodeFactory.callExpressionNode(
taggedTemplateExpression.tag,
[
NodeFactory.callExpressionNode(NodeFactory.identifierNode(templateObjectHelperName), []),
...taggedTemplateExpression.quasi.expressions
]
);
NodeUtils.parentizeAst(templateObjectCallExpressionNode);
NodeUtils.parentizeNode(templateObjectCallExpressionNode, parentNode);
return templateObjectCallExpressionNode;
}
/**
* @param {Program} programNode
*/
private appendTemplateLiteralCustomCodeHelper (programNode: ESTree.Program): void {
if (this.isTaggedTemplateLiteralHelperAppended || !this.taggedTemplateLiteralHelperName) {
return;
}
const taggedTemplateLiteralCodeHelper: ICustomCodeHelper<TInitialData<TaggedTemplateLiteralCodeHelper>> =
this.customCodeHelperFactory(CustomCodeHelper.TaggedTemplateLiteralCodeHelper);
taggedTemplateLiteralCodeHelper.initialize(this.taggedTemplateLiteralHelperName);
NodeAppender.prepend(programNode, taggedTemplateLiteralCodeHelper.getNode());
this.isTaggedTemplateLiteralHelperAppended = true;
}
/**
* @param {Program} programNode
* @param {string} templateObjectHelperName
* @param {TemplateElement[]} quasisElements
*/
private appendTemplateObjectCustomCodeHelper (
programNode: ESTree.Program,
templateObjectHelperName: string,
quasisElements: ESTree.TemplateElement[]
): void {
if (!this.taggedTemplateLiteralHelperName) {
return;
}
const values: string[] = [];
const rawValues: string[] = [];
// Flag variable to check if contents of strings and raw are equal
let isStringsRawEqual: boolean = true;
for (const elem of quasisElements) {
const {raw, cooked} = elem.value;
values.push(cooked);
rawValues.push(raw);
if (raw !== cooked) {
// false even if one of raw and cooked are not equal
isStringsRawEqual = false;
}
}
const templateObjectCodeHelper: ICustomCodeHelper<TInitialData<TemplateObjectCodeHelper>> =
this.customCodeHelperFactory(CustomCodeHelper.TemplateObjectCodeHelper);
templateObjectCodeHelper.initialize(
templateObjectHelperName,
this.taggedTemplateLiteralHelperName,
values,
!isStringsRawEqual ? rawValues : null
);
NodeAppender.prepend(programNode, templateObjectCodeHelper.getNode());
}
}
+19 -25
View File
@@ -7,38 +7,32 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
function foo () {
function bar () {
const a = [];
const b = [];
while (true) {
for (const a of b) {}
}
return a;
function azaza() {
var pre = 1;
var tag = function (strings, ...args) {
return [strings.raw, args]
}
function baz () {
const a = 1;
}
function bark () {
const a = 1;
if (true) {
console.log(a);
}
}
function hawk () {
const a = 1;
var tag1 = function (strings, ...args) {
return [strings.raw]
}
var foo = 1;
console.log(tag\`\${'first'}m\\iddle\${'second'}end\`);
console.log(tag1\`\${'first'}middle\${'second'}end\`);
var bar = 2;
}
azaza();
`,
{
...NO_ADDITIONAL_NODES_PRESET,
compact: false,
deadCodeInjection: true,
deadCodeInjectionThreshold: 1
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();