From 6b8ead0b2b81942062f640efd89f8bf2020d89a7 Mon Sep 17 00:00:00 2001 From: sanex Date: Sat, 29 Jan 2022 13:36:10 +0300 Subject: [PATCH] Support for class static blocks --- CHANGELOG.md | 4 +++ package.json | 4 +-- src/declarations/ESTree.d.ts | 5 +++ src/enums/node/NodeType.ts | 1 + src/node/NodeFactory.ts | 12 +++++++ src/node/NodeGuards.ts | 15 +++++++- test/dev/dev.ts | 16 +++++---- .../JavaScriptObfuscator.spec.ts | 36 +++++++++++++++++++ .../fixtures/class-static-block-support-1.js | 11 ++++++ .../node/node-guards/NodeGuards.spec.ts | 18 +++++++++- yarn.lock | 8 ++--- 11 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 test/functional-tests/javascript-obfuscator/fixtures/class-static-block-support-1.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 7ab57c28..cef368a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ Change Log +v3.1.0 +--- +* Added support of `es2022` features: class static block + v3.0.1 --- * Dependencies update diff --git a/package.json b/package.json index dbaecf90..f4e31e45 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "javascript-obfuscator", - "version": "3.0.1", + "version": "3.1.0", "description": "JavaScript obfuscator", "keywords": [ "obfuscator", @@ -21,7 +21,7 @@ }, "types": "typings/index.d.ts", "dependencies": { - "@javascript-obfuscator/escodegen": "2.2.2", + "@javascript-obfuscator/escodegen": "2.3.0", "@javascript-obfuscator/estraverse": "5.4.0", "@nuxtjs/opencollective": "0.3.2", "acorn": "8.7.0", diff --git a/src/declarations/ESTree.d.ts b/src/declarations/ESTree.d.ts index 252dfd76..81ba0023 100644 --- a/src/declarations/ESTree.d.ts +++ b/src/declarations/ESTree.d.ts @@ -3,6 +3,7 @@ import * as acorn from 'acorn'; import * as escodegen from '@javascript-obfuscator/escodegen'; import * as eslintScope from 'eslint-scope'; +import { BlockStatement } from 'estree'; declare module 'estree' { /** @@ -53,4 +54,8 @@ declare module 'estree' { metadata?: LiteralNodeMetadata; 'x-verbatim-property'?: escodegen.XVerbatimProperty; } + + interface StaticBlock extends Omit { + type: 'StaticBlock' + } } diff --git a/src/enums/node/NodeType.ts b/src/enums/node/NodeType.ts index a7812104..4723442d 100644 --- a/src/enums/node/NodeType.ts +++ b/src/enums/node/NodeType.ts @@ -47,6 +47,7 @@ export enum NodeType { ReturnStatement = 'ReturnStatement', SequenceExpression = 'SequenceExpression', SpreadElement = 'SpreadElement', + StaticBlock = 'StaticBlock', Super = 'Super', SwitchCase = 'SwitchCase', SwitchStatement = 'SwitchStatement', diff --git a/src/node/NodeFactory.ts b/src/node/NodeFactory.ts index a759ff46..cb9ff055 100644 --- a/src/node/NodeFactory.ts +++ b/src/node/NodeFactory.ts @@ -544,6 +544,18 @@ export class NodeFactory { }; } + /** + * @param {Statement[]} body + * @returns {StaticBlock} + */ + public static staticBlockNode (body: ESTree.Statement[] = []): ESTree.StaticBlock { + return { + type: NodeType.StaticBlock, + body, + metadata: { ignoredNode: false } + }; + } + /** * @param {Expression} discriminant * @param {SwitchCase[]} cases diff --git a/src/node/NodeGuards.ts b/src/node/NodeGuards.ts index 0db2585c..dd13f2b4 100644 --- a/src/node/NodeGuards.ts +++ b/src/node/NodeGuards.ts @@ -365,7 +365,9 @@ export class NodeGuards { * @returns {boolean} */ public static isNodeWithBlockLexicalScope (node: ESTree.Node): node is TNodeWithLexicalScope { - return NodeGuards.isNodeWithLexicalScope(node) || NodeGuards.isBlockStatementNode(node); + return NodeGuards.isNodeWithLexicalScope(node) + || NodeGuards.isBlockStatementNode(node) + || NodeGuards.isStaticBlockNode(node); } /** @@ -417,6 +419,7 @@ export class NodeGuards { public static isNodeWithStatements (node: ESTree.Node): node is TNodeWithStatements { return NodeGuards.isProgramNode(node) || NodeGuards.isBlockStatementNode(node) + || NodeGuards.isStaticBlockNode(node) || NodeGuards.isSwitchCaseNode(node); } @@ -500,6 +503,16 @@ export class NodeGuards { return node.type === NodeType.SpreadElement; } + /** + * @param {Node} node + * @returns {boolean} + */ + // TODO: add type guard after @types/estree update + public static isStaticBlockNode (node: ESTree.Node): boolean { + // TODO: Update @types/estree + return (node).type === NodeType.StaticBlock; + } + /** * @param {Node} node * @returns {boolean} diff --git a/test/dev/dev.ts b/test/dev/dev.ts index cdb55b46..9dce153b 100644 --- a/test/dev/dev.ts +++ b/test/dev/dev.ts @@ -1,18 +1,20 @@ 'use strict'; -import { readFileAsString } from '../helpers/readFileAsString'; - (function () { const JavaScriptObfuscator: any = require('../../index'); - const code: string = readFileAsString(__dirname + '/../functional-tests/javascript-obfuscator/fixtures/custom-nodes-identifier-names-collision.js'); + const code: string = ` + class Foo { + static { + let abc = 2; + abc = 3; + } + } + `; let obfuscationResult = JavaScriptObfuscator.obfuscate( code, { - identifierNamesGenerator: 'mangled', - compact: false, - stringArray: true, - seed: 429105580 + compact: false } ); diff --git a/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts b/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts index 99481fd5..95f3bd0e 100644 --- a/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts +++ b/test/functional-tests/javascript-obfuscator/JavaScriptObfuscator.spec.ts @@ -984,6 +984,42 @@ describe('JavaScriptObfuscator', () => { }); }); + describe('Class static block support', () => { + const regExp: RegExp = new RegExp( + 'let _0x(\\w){4,6} *= *0x1; *' + + 'class _0x(\\w){4,6} *{ *' + + 'static *\\[\'_0x(\\w){4,6}\']; *' + + 'static *{ *' + + 'let _0x(\\w){4,6} *= *0x2; *' + + '_0x(\\w){4,6}\\[\'_0x(\\w){4,6}\'] *= *0x3; *' + + '_0x(\\w){4,6} *= *0x4; *' + + '_0x(\\w){4,6} *= *0x5; *' + + '} *' + + '}' + ); + + let obfuscatedCode: string; + + beforeEach(() => { + const code: string = readFileAsString(__dirname + '/fixtures/class-static-block-support-1.js'); + + obfuscatedCode = JavaScriptObfuscator.obfuscate( + code, + { + ...NO_ADDITIONAL_NODES_PRESET, + renameGlobals: true, + renameProperties: true + } + ).getObfuscatedCode(); + + console.log(obfuscatedCode); + }); + + it('should support class static block await', () => { + assert.match(obfuscatedCode, regExp); + }); + }); + describe('Private identifiers support', () => { const regExp: RegExp = new RegExp( 'class Foo *{ *' + diff --git a/test/functional-tests/javascript-obfuscator/fixtures/class-static-block-support-1.js b/test/functional-tests/javascript-obfuscator/fixtures/class-static-block-support-1.js new file mode 100644 index 00000000..8efcd819 --- /dev/null +++ b/test/functional-tests/javascript-obfuscator/fixtures/class-static-block-support-1.js @@ -0,0 +1,11 @@ +let foo = 1; +class Foo { + static abc; + + static { + let bar = 2; + Foo.abc = 3; + foo = 4; + bar = 5; + } +} \ No newline at end of file diff --git a/test/unit-tests/node/node-guards/NodeGuards.spec.ts b/test/unit-tests/node/node-guards/NodeGuards.spec.ts index ed5bd375..df9f82e0 100644 --- a/test/unit-tests/node/node-guards/NodeGuards.spec.ts +++ b/test/unit-tests/node/node-guards/NodeGuards.spec.ts @@ -705,7 +705,23 @@ describe('NodeGuards', () => { }); }); - describe('Variant #3: switch case node', () => { + describe('Variant #3: static block node', () => { + const expectedResult: boolean = true; + // TODO: remove typecast after @types/estree update + const node: ESTree.Node = NodeFactory.staticBlockNode(); + + let result: boolean; + + before(() => { + result = NodeGuards.isNodeWithStatements(node); + }); + + it('should check if node has statements', () => { + assert.equal(result, expectedResult); + }); + }); + + describe('Variant #4: switch case node', () => { const expectedResult: boolean = true; const node: ESTree.Node = NodeFactory.switchCaseNode( NodeFactory.literalNode(1), diff --git a/yarn.lock b/yarn.lock index 5d0aa3d4..e22482f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -259,10 +259,10 @@ resolved "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz" integrity sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw== -"@javascript-obfuscator/escodegen@2.2.2": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@javascript-obfuscator/escodegen/-/escodegen-2.2.2.tgz#518aa621f6258fa369eb48b865e54dc58fc44cfa" - integrity sha512-0VoGJun/lpGEPv8J8R8fpwt1iAGyctUjHTQoYoCbKY2rcGc6d+NycrqSMo61vRXhZiTnHgud1UF8dOI7UAPdTw== +"@javascript-obfuscator/escodegen@2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@javascript-obfuscator/escodegen/-/escodegen-2.3.0.tgz#ff7eb7f8a7c004532e93b14ae8b2196dcf9a1a9e" + integrity sha512-QVXwMIKqYMl3KwtTirYIA6gOCiJ0ZDtptXqAv/8KWLG9uQU2fZqTVy7a/A5RvcoZhbDoFfveTxuGxJ5ibzQtkw== dependencies: "@javascript-obfuscator/estraverse" "^5.3.0" esprima "^4.0.1"