Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
Change Log

v2.10.2
---
* Fixed behaviour of `simplify` options when node with a single-statement `body` is inside simplified `IfStatement` node. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/860

v2.10.1
---
* Removed padding characters from all base64 encoded strings. Removed RegExp that trims padding characters from `base64` encoded strings from `atob` code helper to prevent mutation of `RegExp.$1` value during calls to the `stringArray`. Fixed https://github.com/javascript-obfuscator/javascript-obfuscator/issues/829
Expand Down
2 changes: 1 addition & 1 deletion dist/index.browser.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.cli.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/index.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "javascript-obfuscator",
"version": "2.10.1",
"version": "2.10.2",
"description": "JavaScript obfuscator",
"keywords": [
"obfuscator",
Expand Down
2 changes: 2 additions & 0 deletions src/enums/node/NodeType.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export enum NodeType {
ClassDeclaration = 'ClassDeclaration',
ConditionalExpression = 'ConditionalExpression',
ContinueStatement = 'ContinueStatement',
DoWhileStatement = 'DoWhileStatement',
ExportAllDeclaration = 'ExportAllDeclaration',
ExportNamedDeclaration = 'ExportNamedDeclaration',
ExportSpecifier = 'ExportSpecifier',
Expand Down Expand Up @@ -54,6 +55,7 @@ export enum NodeType {
UpdateExpression = 'UpdateExpression',
VariableDeclaration = 'VariableDeclaration',
VariableDeclarator = 'VariableDeclarator',
WithStatement = 'WithStatement',
WhileStatement = 'WhileStatement',
YieldExpression = 'YieldExpression'
}
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ export class IfStatementSimplifyTransformer extends AbstractStatementSimplifyTra
*/
return NodeGuards.isFunctionDeclarationNode(statement)
/**
* Ignore any nodes with a single statement as a `body`
* Without ignore it can break following code:
* Input:
* if (condition1) {
Expand All @@ -302,8 +303,10 @@ export class IfStatementSimplifyTransformer extends AbstractStatementSimplifyTra
* var foo = bar();
* else
* var baz = bark();
*
* See issue: https://github.com/javascript-obfuscator/javascript-obfuscator/issues/860
*/
|| NodeGuards.isIfStatementNode(statement)
|| NodeGuards.isNodeWithSingleStatementBody(statement)

/**
* `let` and `const` variable declarations are not allowed outside of `IfStatement` block statement
Expand Down
97 changes: 97 additions & 0 deletions src/node/NodeFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,20 @@ export class NodeFactory {
};
}

/**
* @param {Statement} body
* @param {Expression} test
* @returns {DoWhileStatement}
*/
public static doWhileStatementNode (body: ESTree.Statement, test: ESTree.Expression): ESTree.DoWhileStatement {
return {
type: NodeType.DoWhileStatement,
body,
test,
metadata: { ignoredNode: false }
};
}

/**
* @param {Literal} source
* @returns {ExportAllDeclaration}
Expand Down Expand Up @@ -210,6 +224,72 @@ export class NodeFactory {
};
}

/**
* @param {VariableDeclaration | Expression | null} init
* @param {Expression | null} test
* @param {Expression | null} update
* @param {Statement} body
* @returns {ForStatement}
*/
public static forStatementNode (
init: ESTree.VariableDeclaration | ESTree.Expression | null,
test: ESTree.Expression | null,
update: ESTree.Expression | null,
body: ESTree.Statement
): ESTree.ForStatement {
return {
type: NodeType.ForStatement,
init,
test,
update,
body,
metadata: { ignoredNode: false }
};
}

/**
* @param {VariableDeclaration | Pattern} left
* @param {Expression} right
* @param {Statement} body
* @returns {ForInStatement}
*/
public static forInStatementNode (
left: ESTree.VariableDeclaration | ESTree.Pattern,
right: ESTree.Expression,
body: ESTree.Statement
): ESTree.ForInStatement {
return {
type: NodeType.ForInStatement,
left,
right,
body,
metadata: { ignoredNode: false }
};
}

/**
* @param {boolean} await
* @param {VariableDeclaration | Pattern} left
* @param {Expression} right
* @param {Statement} body
* @returns {ForOfStatement}
*/
public static forOfStatementNode (
await: boolean,
left: ESTree.VariableDeclaration | ESTree.Pattern,
right: ESTree.Expression,
body: ESTree.Statement
): ESTree.ForOfStatement {
return {
type: NodeType.ForOfStatement,
await,
left,
right,
body,
metadata: { ignoredNode: false }
};
}

/**
* @param {string} functionName
* @param {Identifier[]} params
Expand Down Expand Up @@ -298,6 +378,23 @@ export class NodeFactory {
};
}

/**
* @param {Identifier} label
* @param {Statement} body
* @returns {LabeledStatement}
*/
public static labeledStatementNode (
label: ESTree.Identifier,
body: ESTree.Statement
): ESTree.LabeledStatement {
return {
type: NodeType.LabeledStatement,
label,
body,
metadata: { ignoredNode: false }
};
}

/**
* @param {boolean | number | string} value
* @param {string} raw
Expand Down
76 changes: 76 additions & 0 deletions src/node/NodeGuards.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
/* eslint-disable max-lines */
import * as ESTree from 'estree';

import { TNodeWithLexicalScope } from '../types/node/TNodeWithLexicalScope';
import { TNodeWithLexicalScopeStatements } from '../types/node/TNodeWithLexicalScopeStatements';
import { TNodeWithStatements } from '../types/node/TNodeWithStatements';

import { NodeType } from '../enums/node/NodeType';
import { TNodeWithSingleStatementBody } from '../types/node/TNodeWithSingleStatementBody';

export class NodeGuards {
/**
Expand Down Expand Up @@ -116,6 +118,14 @@ export class NodeGuards {
&& 'directive' in node;
}

/**
* @param {Node} node
* @returns {boolean}
*/
public static isDoWhileStatementNode (node: ESTree.Node): node is ESTree.DoWhileStatement {
return node.type === NodeType.DoWhileStatement;
}

/**
* @param {Node} node
* @returns {boolean}
Expand Down Expand Up @@ -149,6 +159,22 @@ export class NodeGuards {
&& !('directive' in node);
}

/**
* @param {Node} node
* @returns {boolean}
*/
public static isForStatementNode (node: ESTree.Node): node is ESTree.ForStatement {
return node.type === NodeType.ForStatement;
}

/**
* @param {Node} node
* @returns {boolean}
*/
public static isForInStatementNode (node: ESTree.Node): node is ESTree.ForInStatement {
return node.type === NodeType.ForInStatement;
}

/**
* @param {Node} node
* @returns {boolean}
Expand Down Expand Up @@ -201,6 +227,19 @@ export class NodeGuards {
return node.type === NodeType.IfStatement;
}

/**
* @param {Node} node
* @returns {boolean}
*/
public static isIfStatementNodeWithSingleStatementBody (node: ESTree.Node): node is ESTree.IfStatement {
if (!NodeGuards.isIfStatementNode(node)) {
return false;
}

return !NodeGuards.isBlockStatementNode(node.consequent)
|| (!!node.alternate && !NodeGuards.isBlockStatementNode(node.alternate));
}

/**
* @param {Node} node
* @returns {boolean}
Expand Down Expand Up @@ -287,6 +326,35 @@ export class NodeGuards {
return NodeGuards.isNodeWithLexicalScope(node) || NodeGuards.isBlockStatementNode(node);
}

/**
* Checks if a node is the node with single statement body, like:
* while (true)
* console.log(1);
*
* or:
*
*
* @param {Node} node
* @returns {boolean}
*/
public static isNodeWithSingleStatementBody (node: ESTree.Node): node is TNodeWithSingleStatementBody {
// Different approach for `IfStatement` node because this node hasn't `body` property
if (NodeGuards.isIfStatementNode(node)) {
return NodeGuards.isIfStatementNodeWithSingleStatementBody(node);
}

// All other nodes with `Statement` node as `body` property
return (
NodeGuards.isForStatementNode(node)
|| NodeGuards.isForOfStatementNode(node)
|| NodeGuards.isForInStatementNode(node)
|| NodeGuards.isWhileStatementNode(node)
|| NodeGuards.isDoWhileStatementNode(node)
|| NodeGuards.isWithStatementNode(node)
|| NodeGuards.isLabeledStatementNode(node)
) && !NodeGuards.isBlockStatementNode(node.body);
}

/**
* @param {Node} node
* @param {Node} parentNode
Expand Down Expand Up @@ -438,6 +506,14 @@ export class NodeGuards {
return node.type === NodeType.VariableDeclarator;
}

/**
* @param {Node} node
* @returns {boolean}
*/
public static isWithStatementNode (node: ESTree.Node): node is ESTree.WithStatement {
return node.type === NodeType.WithStatement;
}

/**
* @param {Node} node
* @returns {boolean}
Expand Down
21 changes: 21 additions & 0 deletions src/types/node/TNodeWithSingleStatementBody.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as ESTree from 'estree';

export type TNodeWithSingleStatementBody = (
ESTree.LabeledStatement
| ESTree.WithStatement
| ESTree.WhileStatement
| ESTree.DoWhileStatement
| ESTree.ForStatement
| ESTree.ForInStatement
| ESTree.ForOfStatement
& {
body: Exclude<ESTree.Statement, ESTree.BlockStatement>;
}
)
| (
ESTree.IfStatement
& {
consequent: Exclude<ESTree.Statement, ESTree.BlockStatement>;
alternate?: Exclude<ESTree.Statement, ESTree.BlockStatement> | null;
}
);
Loading