mirror of
https://github.com/javascript-obfuscator/javascript-obfuscator
synced 2026-08-09 12:42:29 +00:00
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
This commit is contained in:
@@ -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
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
Vendored
+1
-1
File diff suppressed because one or more lines are too long
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "javascript-obfuscator",
|
||||
"version": "2.10.1",
|
||||
"version": "2.10.2",
|
||||
"description": "JavaScript obfuscator",
|
||||
"keywords": [
|
||||
"obfuscator",
|
||||
|
||||
@@ -14,6 +14,7 @@ export enum NodeType {
|
||||
ClassDeclaration = 'ClassDeclaration',
|
||||
ConditionalExpression = 'ConditionalExpression',
|
||||
ContinueStatement = 'ContinueStatement',
|
||||
DoWhileStatement = 'DoWhileStatement',
|
||||
ExportAllDeclaration = 'ExportAllDeclaration',
|
||||
ExportNamedDeclaration = 'ExportNamedDeclaration',
|
||||
ExportSpecifier = 'ExportSpecifier',
|
||||
@@ -54,6 +55,7 @@ export enum NodeType {
|
||||
UpdateExpression = 'UpdateExpression',
|
||||
VariableDeclaration = 'VariableDeclaration',
|
||||
VariableDeclarator = 'VariableDeclarator',
|
||||
WithStatement = 'WithStatement',
|
||||
WhileStatement = 'WhileStatement',
|
||||
YieldExpression = 'YieldExpression'
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
@@ -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
|
||||
|
||||
@@ -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}
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
/* eslint-disable max-lines */
|
||||
import * as ESTree from 'estree';
|
||||
|
||||
import { TNodeWithLexicalScope } from '../types/node/TNodeWithLexicalScope';
|
||||
@@ -5,6 +6,7 @@ import { TNodeWithLexicalScopeStatements } from '../types/node/TNodeWithLexicalS
|
||||
import { TNodeWithStatements } from '../types/node/TNodeWithStatements';
|
||||
|
||||
import { NodeType } from '../enums/node/NodeType';
|
||||
import { TNodeWithSingleStatementBody } from '../types/node/TNodeWithSingleStatementBody';
|
||||
|
||||
export class NodeGuards {
|
||||
/**
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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}
|
||||
@@ -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
|
||||
@@ -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}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
);
|
||||
+178
-3
@@ -781,7 +781,182 @@ describe('IfStatementSimplifyTransformer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: `FunctionDeclaration` as prohibited single statement', () => {
|
||||
describe('Variant #2: Nodes with single statement `body` property', () => {
|
||||
describe('Variant #1: Single line `ForStatement` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'for *\\( *' +
|
||||
'let _0x([a-f0-9]){4,6} *= *0x0; *' +
|
||||
'_0x([a-f0-9]){4,6} *< *0x1; *' +
|
||||
'_0x([a-f0-9]){4,6}\\+\\+ *' +
|
||||
'\\) *' +
|
||||
'console\\[\'log\']\\(_0x([a-f0-9]){4,6}\\); *' +
|
||||
'} *else *' +
|
||||
'var _0x([a-f0-9]){4,6} *= *hawk\\(\\);'
|
||||
);
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/single-line-for-statement-as-prohibited-single-statement.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should not simplify if statement', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: Single line `ForOfStatement` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'for *\\(const _0x([a-f0-9]){4,6} of *\\[\\]\\) *' +
|
||||
'console\\[\'log\']\\(_0x([a-f0-9]){4,6}\\); *' +
|
||||
'} *else *' +
|
||||
'var _0x([a-f0-9]){4,6} *= *hawk\\(\\);'
|
||||
);
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/single-line-for-of-statement-as-prohibited-single-statement.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should not simplify if statement', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: Single line `ForInStatement` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'for *\\(const _0x([a-f0-9]){4,6} in *\\{\\}\\) *' +
|
||||
'console\\[\'log\']\\(_0x([a-f0-9]){4,6}\\); *' +
|
||||
'} *else *' +
|
||||
'var _0x([a-f0-9]){4,6} *= *hawk\\(\\);'
|
||||
);
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/single-line-for-in-statement-as-prohibited-single-statement.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should not simplify if statement', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: Single line `WhileStatement` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'while *\\(!!\\[]\\) *' +
|
||||
'console\\[\'log\']\\(0x1\\); *' +
|
||||
'} *else *' +
|
||||
'var _0x([a-f0-9]){4,6} *= *hawk\\(\\);'
|
||||
);
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/single-line-while-statement-as-prohibited-single-statement.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should not simplify if statement', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #5: Single line `DoWhileStatement` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'do *' +
|
||||
'console\\[\'log\']\\(0x1\\); *' +
|
||||
'while *\\(!!\\[]\\); *' +
|
||||
'} *else *' +
|
||||
'var _0x([a-f0-9]){4,6} *= *hawk\\(\\);'
|
||||
);
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/single-line-do-while-statement-as-prohibited-single-statement.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should not simplify if statement', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #6: Single line `LabeledStatement` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'_0x([a-f0-9]){4,6}: *' +
|
||||
'console\\[\'log\']\\(0x1\\); *' +
|
||||
'} *else *' +
|
||||
'var _0x([a-f0-9]){4,6} *= *hawk\\(\\);'
|
||||
);
|
||||
|
||||
let obfuscatedCode: string;
|
||||
|
||||
before(() => {
|
||||
const code: string = readFileAsString(__dirname + '/fixtures/single-line-labeled-statement-as-prohibited-single-statement.js');
|
||||
|
||||
obfuscatedCode = JavaScriptObfuscator.obfuscate(
|
||||
code,
|
||||
{
|
||||
...NO_ADDITIONAL_NODES_PRESET,
|
||||
simplify: true
|
||||
}
|
||||
).getObfuscatedCode();
|
||||
});
|
||||
|
||||
it('should not simplify if statement', () => {
|
||||
assert.match(obfuscatedCode, regExp);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: `FunctionDeclaration` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'function _0x([a-f0-9]){4,6} *\\(\\) *{} *' +
|
||||
@@ -810,7 +985,7 @@ describe('IfStatementSimplifyTransformer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: `let` `VariableDeclaration` as prohibited single statement', () => {
|
||||
describe('Variant #4: `let` `VariableDeclaration` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'let foo *= *0x1; *' +
|
||||
@@ -837,7 +1012,7 @@ describe('IfStatementSimplifyTransformer', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: `const` `VariableDeclaration` as prohibited single statement', () => {
|
||||
describe('Variant #5: `const` `VariableDeclaration` as prohibited single statement', () => {
|
||||
const regExp: RegExp = new RegExp(
|
||||
'if *\\(!!\\[]\\) *{ *' +
|
||||
'const foo *= *0x1; *' +
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
function foo() {
|
||||
if (true) {
|
||||
do
|
||||
console.log(1);
|
||||
while (true);
|
||||
} else {
|
||||
var bark = hawk();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
function foo() {
|
||||
if (true) {
|
||||
for (const key in {})
|
||||
console.log(key);
|
||||
} else {
|
||||
var bark = hawk();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
function foo() {
|
||||
if (true) {
|
||||
for (const item of [])
|
||||
console.log(item);
|
||||
} else {
|
||||
var bark = hawk();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
function foo() {
|
||||
if (true) {
|
||||
for (let i= 0; i < 1; i++)
|
||||
console.log(i);
|
||||
} else {
|
||||
var bark = hawk();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
function foo() {
|
||||
if (true) {
|
||||
label:
|
||||
console.log(1);
|
||||
} else {
|
||||
var bark = hawk();
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
function foo() {
|
||||
if (true) {
|
||||
while (true)
|
||||
console.log(1);
|
||||
} else {
|
||||
var bark = hawk();
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,107 @@ import { NodeFactory } from '../../../../src/node/NodeFactory';
|
||||
import { NodeUtils } from '../../../../src/node/NodeUtils';
|
||||
|
||||
describe('NodeGuards', () => {
|
||||
describe('isIfStatementNodeWithSingleStatementBody', () => {
|
||||
describe('truthful checks', () => {
|
||||
describe('Variant #1: single statement `consequent`', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isIfStatementNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has single statement `consequent`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: single statement `alternate`', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
]),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isIfStatementNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has single statement `alternate`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: single statement `consequent` and `alternate`', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isIfStatementNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has single statement `consequent` and `alternate`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('false checks', () => {
|
||||
describe('Variant #1: multiple statements `consequent` and `alternate`', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
]),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isIfStatementNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has multiple statements `consequent` and `alternate`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNodeWithLexicalScopeStatements', () => {
|
||||
describe('truthful checks', () => {
|
||||
describe('Variant #1: block statement of function declaration', () => {
|
||||
@@ -138,6 +239,425 @@ describe('NodeGuards', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNodeWithSingleStatementBody', () => {
|
||||
describe('truthful checks', () => {
|
||||
describe('Variant #1: `IfStatement` node', () => {
|
||||
describe('Variant #1: single statement `consequent`', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has single statement `consequent`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: single statement `alternate`', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
]),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has single statement `alternate`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: single statement `consequent` and `alternate`', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has single statement `consequent` and `alternate`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: `ForStatement` node', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.ForStatement = NodeFactory.forStatementNode(
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('i'),
|
||||
NodeFactory.literalNode(0)
|
||||
)
|
||||
]),
|
||||
NodeFactory.binaryExpressionNode(
|
||||
'<',
|
||||
NodeFactory.identifierNode('i'),
|
||||
NodeFactory.literalNode(10)
|
||||
),
|
||||
NodeFactory.updateExpressionNode(
|
||||
'++',
|
||||
NodeFactory.identifierNode('i')
|
||||
),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `ForStatement` node has single statement `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: `ForInStatement` node', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.ForInStatement = NodeFactory.forInStatementNode(
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('key'),
|
||||
null
|
||||
)
|
||||
]),
|
||||
NodeFactory.objectExpressionNode(
|
||||
[]
|
||||
),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `ForInStatement` node has single statement `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: `ForOfStatement` node', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.ForOfStatement = NodeFactory.forOfStatementNode(
|
||||
false,
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('key'),
|
||||
null
|
||||
)
|
||||
]),
|
||||
NodeFactory.objectExpressionNode(
|
||||
[]
|
||||
),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `ForOfStatement` node has single statement `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #5: `WhileStatement` node', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.WhileStatement = NodeFactory.whileStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `WhileStatement` node has single statement `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #6: `DoWhileStatement` node', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.DoWhileStatement = NodeFactory.doWhileStatementNode(
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
),
|
||||
NodeFactory.literalNode(true)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `DoWhileStatement` node has single statement `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #7: `LabeledStatement` node', () => {
|
||||
const expectedResult: boolean = true;
|
||||
const node: ESTree.LabeledStatement = NodeFactory.labeledStatementNode(
|
||||
NodeFactory.identifierNode('label'),
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `LabeledStatement` node has single statement `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('false checks', () => {
|
||||
describe('Variant #1: `IfStatement` node', () => {
|
||||
describe('Variant #1: multiple statements `consequent` and `alternate`', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.IfStatement = NodeFactory.ifStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
]),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `IfStatement` node has multiple statements `consequent` and `alternate`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #2: `ForStatement` node', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.ForStatement = NodeFactory.forStatementNode(
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('i'),
|
||||
NodeFactory.literalNode(0)
|
||||
)
|
||||
]),
|
||||
NodeFactory.binaryExpressionNode(
|
||||
'<',
|
||||
NodeFactory.identifierNode('i'),
|
||||
NodeFactory.literalNode(10)
|
||||
),
|
||||
NodeFactory.updateExpressionNode(
|
||||
'++',
|
||||
NodeFactory.identifierNode('i')
|
||||
),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `ForStatement` node has multiple statements `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #3: `ForInStatement` node', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.ForInStatement = NodeFactory.forInStatementNode(
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('key'),
|
||||
null
|
||||
)
|
||||
]),
|
||||
NodeFactory.objectExpressionNode(
|
||||
[]
|
||||
),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `ForInStatement` node has multiple statements `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #4: `ForOfStatement` node', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.ForOfStatement = NodeFactory.forOfStatementNode(
|
||||
false,
|
||||
NodeFactory.variableDeclarationNode([
|
||||
NodeFactory.variableDeclaratorNode(
|
||||
NodeFactory.identifierNode('key'),
|
||||
null
|
||||
)
|
||||
]),
|
||||
NodeFactory.objectExpressionNode(
|
||||
[]
|
||||
),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `ForOfStatement` node has multiple statements `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #5: `WhileStatement` node', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.WhileStatement = NodeFactory.whileStatementNode(
|
||||
NodeFactory.literalNode(true),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `WhileStatement` node has multiple statements `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #6: `DoWhileStatement` node', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.DoWhileStatement = NodeFactory.doWhileStatementNode(
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
]),
|
||||
NodeFactory.literalNode(true)
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `DoWhileStatement` node has multiple statements `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Variant #7: `LabeledStatement` node', () => {
|
||||
const expectedResult: boolean = false;
|
||||
const node: ESTree.LabeledStatement = NodeFactory.labeledStatementNode(
|
||||
NodeFactory.identifierNode('label'),
|
||||
NodeFactory.blockStatementNode([
|
||||
NodeFactory.expressionStatementNode(
|
||||
NodeFactory.literalNode(true)
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
let result: boolean;
|
||||
|
||||
before(() => {
|
||||
result = NodeGuards.isNodeWithSingleStatementBody(node);
|
||||
});
|
||||
|
||||
it('should check if `LabeledStatement` node has multiple statements `body`', () => {
|
||||
assert.equal(result, expectedResult);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('isNodeWithStatements', () => {
|
||||
describe('truthful checks', () => {
|
||||
describe('Variant #1: program node', () => {
|
||||
|
||||
Reference in New Issue
Block a user