More complex object keys transformation + some string literal transformations refactoring

This commit is contained in:
sanex3339
2020-01-25 13:50:00 +03:00
parent f333b9d425
commit fc2cf933d9
20 changed files with 390 additions and 101 deletions
+6 -6
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
File diff suppressed because one or more lines are too long
@@ -12,6 +12,7 @@ import { IStringArrayStorageItemData } from '../../interfaces/storages/string-ar
import { NodeGuards } from '../../node/NodeGuards';
import { NodeMetadata } from '../../node/NodeMetadata';
import { NodeLiteralUtils } from '../../node/NodeLiteralUtils';
/**
* Adds values of literal nodes to the string array storage
@@ -67,7 +68,11 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
}
estraverse.traverse(astTree, {
enter: (node: ESTree.Node): estraverse.VisitorOption | void => {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null): estraverse.VisitorOption | void => {
if (!parentNode) {
return;
}
if (NodeMetadata.isIgnoredNode(node)) {
return estraverse.VisitorOption.Skip;
}
@@ -76,7 +81,7 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
return;
}
this.analyzeLiteralNode(node);
this.analyzeLiteralNode(node, parentNode);
}
});
}
@@ -91,12 +96,17 @@ export class StringArrayStorageAnalyzer implements IStringArrayStorageAnalyzer {
/**
* @param {Literal} literalNode
* @param {Node} parentNode
*/
private analyzeLiteralNode (literalNode: ESTree.Literal): void {
private analyzeLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): void {
if (typeof literalNode.value !== 'string') {
return;
}
if (NodeLiteralUtils.isProhibitedLiteralNode(literalNode, parentNode)) {
return;
}
if (!this.shouldAddValueToStringArray(literalNode.value)) {
return;
}
@@ -165,7 +165,7 @@ export class ObjectExpressionKeysTransformer extends AbstractNodeTransformer {
switch (transformationStage) {
case TransformationStage.Converting:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
leave: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
if (
parentNode
&& NodeGuards.isObjectExpressionNode(node)
@@ -12,7 +12,6 @@ import { TransformationStage } from '../../enums/node-transformers/Transformatio
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeFactory } from '../../node/NodeFactory';
import { NodeGuards } from '../../node/NodeGuards';
import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
/**
* replaces:
@@ -24,23 +23,14 @@ import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEn
@injectable()
export class ObjectExpressionTransformer extends AbstractNodeTransformer {
/**
* @type {IEscapeSequenceEncoder}
*/
private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
/**
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(randomGenerator, options);
this.escapeSequenceEncoder = escapeSequenceEncoder;
}
/**
@@ -93,7 +83,7 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
return;
}
property.key = NodeFactory.literalNode(this.getPropertyKeyValue(property.key.value));
property.key = NodeFactory.literalNode(property.key.value);
}
/**
@@ -108,16 +98,6 @@ export class ObjectExpressionTransformer extends AbstractNodeTransformer {
return;
}
property.key = NodeFactory.literalNode(this.getPropertyKeyValue(property.key.name));
}
/**
* @param {string} inputValue
* @returns {string}
*/
private getPropertyKeyValue (inputValue: string): string {
return this.options.unicodeEscapeSequence
? this.escapeSequenceEncoder.encode(inputValue, true)
: inputValue;
property.key = NodeFactory.literalNode(property.key.name);
}
}
@@ -5,6 +5,7 @@ import * as ESTree from 'estree';
import { TLiteralObfuscatingReplacerFactory } from '../../types/container/node-transformers/TLiteralObfuscatingReplacerFactory';
import { IEscapeSequenceEncoder } from '../../interfaces/utils/IEscapeSequenceEncoder';
import { IOptions } from '../../interfaces/options/IOptions';
import { IRandomGenerator } from '../../interfaces/utils/IRandomGenerator';
import { IStringArrayStorageAnalyzer } from '../../interfaces/analyzers/string-array-storage-analyzer/IStringArrayStorageAnalyzer';
@@ -14,12 +15,19 @@ import { LiteralObfuscatingReplacer } from '../../enums/node-transformers/obfusc
import { TransformationStage } from '../../enums/node-transformers/TransformationStage';
import { AbstractNodeTransformer } from '../AbstractNodeTransformer';
import { NodeFactory } from '../../node/NodeFactory';
import { NodeGuards } from '../../node/NodeGuards';
import { NodeLiteralUtils } from '../../node/NodeLiteralUtils';
import { NodeMetadata } from '../../node/NodeMetadata';
import { NodeUtils } from '../../node/NodeUtils';
@injectable()
export class LiteralTransformer extends AbstractNodeTransformer {
/**
* @type {IEscapeSequenceEncoder}
*/
private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
/**
* @type {TLiteralObfuscatingReplacerFactory}
*/
@@ -35,18 +43,21 @@ export class LiteralTransformer extends AbstractNodeTransformer {
* @param {IRandomGenerator} randomGenerator
* @param {IOptions} options
* @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
*/
constructor (
@inject(ServiceIdentifiers.Factory__IObfuscatingReplacer)
literalObfuscatingReplacerFactory: TLiteralObfuscatingReplacerFactory,
@inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator,
@inject(ServiceIdentifiers.IOptions) options: IOptions,
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
@inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder
) {
super(randomGenerator, options);
this.literalObfuscatingReplacerFactory = literalObfuscatingReplacerFactory;
this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
this.escapeSequenceEncoder = escapeSequenceEncoder;
}
/**
@@ -68,6 +79,15 @@ export class LiteralTransformer extends AbstractNodeTransformer {
}
};
case TransformationStage.Finalizing:
return {
enter: (node: ESTree.Node, parentNode: ESTree.Node | null) => {
if (parentNode && NodeGuards.isLiteralNode(node)) {
return this.encodeLiteralNodeToEscapeSequence(node, parentNode);
}
}
};
default:
return null;
}
@@ -83,7 +103,7 @@ export class LiteralTransformer extends AbstractNodeTransformer {
* @returns {NodeGuards}
*/
public transformNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): ESTree.Node {
if (this.isProhibitedNode(literalNode, parentNode)) {
if (NodeLiteralUtils.isProhibitedLiteralNode(literalNode, parentNode)) {
return literalNode;
}
@@ -123,17 +143,18 @@ export class LiteralTransformer extends AbstractNodeTransformer {
/**
* @param {Literal} literalNode
* @param {Node} parentNode
* @returns {boolean}
* @returns {Literal}
*/
private isProhibitedNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): boolean {
if (NodeGuards.isPropertyNode(parentNode) && parentNode.key === literalNode) {
return true;
private encodeLiteralNodeToEscapeSequence (
literalNode: ESTree.Literal,
parentNode: ESTree.Node
): ESTree.Literal {
if (typeof literalNode.value !== 'string') {
return literalNode;
}
if (NodeGuards.isImportDeclarationNode(parentNode)) {
return true;
}
return false;
return NodeFactory.literalNode(
this.escapeSequenceEncoder.encode(literalNode.value, this.options.unicodeEscapeSequence)
);
}
}
@@ -3,7 +3,6 @@ import { ServiceIdentifiers } from '../../../../container/ServiceIdentifiers';
import * as ESTree from 'estree';
import { IEscapeSequenceEncoder } from '../../../../interfaces/utils/IEscapeSequenceEncoder';
import { IInitializable } from '../../../../interfaces/IInitializable';
import { IOptions } from '../../../../interfaces/options/IOptions';
import { IStringArrayStorage } from '../../../../interfaces/storages/string-array-storage/IStringArrayStorage';
@@ -22,11 +21,6 @@ import { Utils } from '../../../../utils/Utils';
@injectable()
export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplacer implements IInitializable {
/**
* @type {IEscapeSequenceEncoder}
*/
private readonly escapeSequenceEncoder: IEscapeSequenceEncoder;
/**
* @type {Map<string, ESTree.Node>}
*/
@@ -51,20 +45,17 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
/**
* @param {IStringArrayStorage} stringArrayStorage
* @param {IStringArrayStorageAnalyzer} stringArrayStorageAnalyzer
* @param {IEscapeSequenceEncoder} escapeSequenceEncoder
* @param {IOptions} options
*/
constructor (
@inject(ServiceIdentifiers.TStringArrayStorage) stringArrayStorage: IStringArrayStorage,
@inject(ServiceIdentifiers.IStringArrayStorageAnalyzer) stringArrayStorageAnalyzer: IStringArrayStorageAnalyzer,
@inject(ServiceIdentifiers.IEscapeSequenceEncoder) escapeSequenceEncoder: IEscapeSequenceEncoder,
@inject(ServiceIdentifiers.IOptions) options: IOptions
) {
super(options);
this.stringArrayStorage = stringArrayStorage;
this.stringArrayStorageAnalyzer = stringArrayStorageAnalyzer;
this.escapeSequenceEncoder = escapeSequenceEncoder;
}
/**
@@ -138,9 +129,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
* @returns {Node}
*/
private replaceWithLiteralNode (value: string): ESTree.Node {
return NodeFactory.literalNode(
this.escapeSequenceEncoder.encode(value, this.options.unicodeEscapeSequence)
);
return NodeFactory.literalNode(value);
}
/**
@@ -156,9 +145,7 @@ export class StringLiteralObfuscatingReplacer extends AbstractObfuscatingReplace
];
if (decodeKey) {
callExpressionArgs.push(StringLiteralObfuscatingReplacer.getRc4KeyLiteralNode(
this.escapeSequenceEncoder.encode(decodeKey, this.options.unicodeEscapeSequence)
));
callExpressionArgs.push(StringLiteralObfuscatingReplacer.getRc4KeyLiteralNode(decodeKey));
}
const stringArrayIdentifierNode: ESTree.Identifier = NodeFactory.identifierNode(this.stringArrayStorageCallsWrapperName);
+17
View File
@@ -228,6 +228,23 @@ export class NodeFactory {
};
}
/**
* @param {(ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier)[]} specifiers
* @param {Literal} source
* @returns {ImportDeclaration}
*/
public static importDeclarationNode (
specifiers: (ESTree.ImportSpecifier | ESTree.ImportDefaultSpecifier | ESTree.ImportNamespaceSpecifier)[],
source: ESTree.Literal
): ESTree.ImportDeclaration {
return {
type: NodeType.ImportDeclaration,
specifiers,
source,
metadata: { ignoredNode: false }
};
}
/**
* @param {boolean | number | string} value
* @param {string} raw
+22
View File
@@ -0,0 +1,22 @@
import * as ESTree from 'estree';
import { NodeGuards } from './NodeGuards';
export class NodeLiteralUtils {
/**
* @param {Literal} literalNode
* @param {Node} parentNode
* @returns {boolean}
*/
public static isProhibitedLiteralNode (literalNode: ESTree.Literal, parentNode: ESTree.Node): boolean {
if (NodeGuards.isPropertyNode(parentNode) && !parentNode.computed && parentNode.key === literalNode) {
return true;
}
if (NodeGuards.isImportDeclarationNode(parentNode)) {
return true;
}
return false;
}
}
@@ -218,6 +218,7 @@ export class StringArrayStorage extends MapStorage <string, IStringArrayStorageI
return Array
.from(this.storage.values())
.map((stringArrayStorageItemData: IStringArrayStorageItemData) => {
// we have to encode here, because of possible errors during `parse` of StringArrayCustomNode
return `'${this.escapeSequenceEncoder.encode(
stringArrayStorageItemData.encodedValue,
this.options.unicodeEscapeSequence
+5 -3
View File
@@ -7,12 +7,14 @@ import { NO_ADDITIONAL_NODES_PRESET } from '../../src/options/presets/NoCustomNo
let obfuscatedCode: string = JavaScriptObfuscator.obfuscate(
`
var foo = {foo: 1};
var foo = {['foo']: 1};
`,
{
...NO_ADDITIONAL_NODES_PRESET,
transformObjectKeys: true,
compact: false
compact: false,
unicodeEscapeSequence: true,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
@@ -152,11 +152,14 @@ describe('ObjectExpressionKeysTransformer', () => {
describe('Variant #6: nested objects #1', () => {
const match: string = `` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['baz'] *= *'bark';` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['inner1'] *= *${variableMatch};` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *'bar';` +
`${variableMatch}\\['inner'] *= *{};` +
`${variableMatch}\\['inner']\\['inner1'] *= *{};` +
`${variableMatch}\\['inner']\\['inner1']\\['baz'] *= *'bark';` +
`${variableMatch}\\['inner'] *= *${variableMatch};` +
`var object *= *${variableMatch};` +
``;
const regExp: RegExp = new RegExp(match);
@@ -181,14 +184,17 @@ describe('ObjectExpressionKeysTransformer', () => {
describe('Variant #7: nested objects #2', () => {
const match: string = `` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['hawk'] *= *'geek';` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['baz'] *= *'bark';` +
`${variableMatch}\\['inner1'] *= *${variableMatch};` +
`${variableMatch}\\['cow'] *= *'bear';` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *'bar';` +
`${variableMatch}\\['inner'] *= *{};` +
`${variableMatch}\\['inner'] *= *${variableMatch};` +
`${variableMatch}\\['ball'] *= *'door';` +
`${variableMatch}\\['inner']\\['baz'] *= *'bark';` +
`${variableMatch}\\['inner']\\['inner1'] *= *{};` +
`${variableMatch}\\['inner']\\['cow'] *= *'bear';` +
`${variableMatch}\\['inner']\\['inner1']\\['hawk'] *= *'geek';` +
`var *object *= *${variableMatch};` +
``;
const regExp: RegExp = new RegExp(match);
@@ -213,14 +219,16 @@ describe('ObjectExpressionKeysTransformer', () => {
describe('Variant #8: nested objects #3', () => {
const match: string = `` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['hawk'] *= *'geek';` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['baz'] *= *'bark';` +
`${variableMatch}\\['inner1'] *= *${variableMatch};` +
`${variableMatch}\\['cow'] *= *'bear';` +
`var *${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *'bar';` +
`${variableMatch}\\['inner'] *= *{};` +
`${variableMatch}\\['inner'] *= *${variableMatch};` +
`${variableMatch}\\['ball'] *= *'door';` +
`${variableMatch}\\['inner']\\['baz'] *= *'bark';` +
`${variableMatch}\\['inner']\\['inner1'] *= *{};` +
`${variableMatch}\\['inner']\\['cow'] *= *'bear';` +
`${variableMatch}\\['inner']\\['inner1']\\['hawk'] *= *'geek';` +
`return ${variableMatch};` +
``;
const regExp: RegExp = new RegExp(match);
@@ -1394,7 +1402,7 @@ describe('ObjectExpressionKeysTransformer', () => {
`var ${variableMatch} *= *{};` +
`${variableMatch}\\['foo'] *= *'test';` +
`var foo *= *${variableMatch};` +
`var ${variableMatch} *= *{\\[foo.foo] *: *'1'};` +
`var ${variableMatch} *= *{\\[foo\\['foo']] *: *'1'};` +
`${variableMatch}\\['bar'] *= *'2';` +
`var bar *= *${variableMatch};` +
``;
@@ -1,10 +1,8 @@
(function(){
var object = {
foo: 'bar',
inner: {
inner1: {
baz: 'bark'
}
var object = {
foo: 'bar',
inner: {
inner1: {
baz: 'bark'
}
};
})();
}
};
@@ -1,14 +1,12 @@
(function(){
var object = {
foo: 'bar',
inner: {
baz: 'bark',
inner1: {
hawk: 'geek'
},
cow: 'bear',
var object = {
foo: 'bar',
inner: {
baz: 'bark',
inner1: {
hawk: 'geek'
},
ball: 'door',
};
})();
cow: 'bear',
},
ball: 'door',
};
@@ -135,7 +135,7 @@ describe('LiteralTransformer', () => {
describe('Variant #6: `unicodeEscapeSequence` and `stringArray` options are enabled', () => {
const stringArrayRegExp: RegExp = /^var *_0x([a-f0-9]){4} *= *\['\\x74\\x65\\x73\\x74'\];/;
const stringArrayCallRegExp: RegExp = /var *test *= *_0x([a-f0-9]){4}\('0x0'\);/;
const stringArrayCallRegExp: RegExp = /var *test *= *_0x([a-f0-9]){4}\('\\x30\\x78\\x30'\);/;
let obfuscatedCode: string;
@@ -157,7 +157,7 @@ describe('LiteralTransformer', () => {
assert.match(obfuscatedCode, stringArrayRegExp);
});
it('match #1: should replace literal node value with unicode escape sequence from string array', () => {
it('match #2: should replace literal node value with unicode escape sequence from string array', () => {
assert.match(obfuscatedCode, stringArrayCallRegExp);
});
});
@@ -518,6 +518,64 @@ describe('LiteralTransformer', () => {
});
});
});
describe('Variant #13: object expression key literal', () => {
describe('Variant #1: base key literal', () => {
const stringArrayRegExp: RegExp = /^var _0x([a-f0-9]){4} *= *\['bar'];/;
const objectExpressionRegExp: RegExp = /var test *= *{'foo' *: *_0x([a-f0-9]){4}\('0x0'\)};/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/object-expression-key-literal.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
});
it('match #1: should not add object expression key literal to the string array', () => {
assert.match(obfuscatedCode, stringArrayRegExp);
});
it('match #2: should keep object expression key literal', () => {
assert.match(obfuscatedCode, objectExpressionRegExp);
});
});
describe('Variant #2: computed key literal', () => {
const stringArrayRegExp: RegExp = /^var _0x([a-f0-9]){4} *= *\['foo', *'bar'];/;
const objectExpressionRegExp: RegExp = /var test *= *{\[_0x([a-f0-9]){4}\('0x0'\)] *: *_0x([a-f0-9]){4}\('0x1'\)};/;
let obfuscatedCode: string;
before(() => {
const code: string = readFileAsString(__dirname + '/fixtures/object-expression-computed-key-literal.js');
obfuscatedCode = JavaScriptObfuscator.obfuscate(
code,
{
...NO_ADDITIONAL_NODES_PRESET,
stringArray: true,
stringArrayThreshold: 1
}
).getObfuscatedCode();
});
it('match #1: should add object expression computed key literal to the string array', () => {
assert.match(obfuscatedCode, stringArrayRegExp);
});
it('match #2: should replace object expression computed key literal on call to the string array', () => {
assert.match(obfuscatedCode, objectExpressionRegExp);
});
});
});
});
describe('transformation of literal node with boolean value', () => {
@@ -157,6 +157,55 @@ describe('StringArrayStorageAnalyzer', () => {
});
});
describe('Analyzes of the AST tree with prohibited string literal nodes', () => {
const literalNode1: ESTree.Literal = NodeFactory.literalNode('foo');
const literalNode2: ESTree.Literal = NodeFactory.literalNode('bar');
const expectedStringArrayStorageItemData1: IStringArrayStorageItemData = {
encodedValue: 'foo',
decodeKey: null,
index: 0,
value: 'foo'
};
const expectedStringArrayStorageItemData2: undefined = undefined;
let stringArrayStorageItemData1: IStringArrayStorageItemData | undefined;
let stringArrayStorageItemData2: IStringArrayStorageItemData | undefined;
before(() => {
stringArrayStorageAnalyzer = getStringArrayStorageAnalyzer({
stringArrayThreshold: 1
});
const astTree: ESTree.Program = NodeFactory.programNode([
NodeFactory.expressionStatementNode(literalNode1),
NodeFactory.variableDeclarationNode([
NodeFactory.variableDeclaratorNode(
NodeFactory.identifierNode('bar'),
NodeFactory.objectExpressionNode([
NodeFactory.propertyNode(
literalNode2,
NodeFactory.literalNode(1)
)
])
)
])
]);
stringArrayStorageAnalyzer.analyze(astTree);
stringArrayStorageItemData1 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode1);
stringArrayStorageItemData2 = stringArrayStorageAnalyzer.getItemDataForLiteralNode(literalNode2);
});
it('Variant #1: should return correct string array storage item data for literal node #1', () => {
assert.deepEqual(stringArrayStorageItemData1, expectedStringArrayStorageItemData1);
});
it('Variant #2: should return correct string array storage item data for literal node #1', () => {
assert.deepEqual(stringArrayStorageItemData2, expectedStringArrayStorageItemData2);
});
});
describe('Analyzes of the AST tree with ignored nodes', () => {
const literalNode1: ESTree.Literal = NodeFactory.literalNode('foo');
const literalNode2: ESTree.Literal = NodeFactory.literalNode('bar');
@@ -0,0 +1,136 @@
import * as ESTree from 'estree';
import { assert } from 'chai';
import { NodeFactory } from '../../../../src/node/NodeFactory';
import { NodeLiteralUtils } from '../../../../src/node/NodeLiteralUtils';
describe('NodeLiteralUtils', () => {
describe('isProhibitedLiteralNode', () => {
describe('String literal node', () => {
describe('Variant #1: base string literal node', () => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
let statementNode: ESTree.Statement;
before(() => {
statementNode = NodeFactory.expressionStatementNode(
literalNode
);
literalNode.parentNode = statementNode;
});
it('should return false for base string literal node', () => {
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, statementNode), false);
});
});
describe('Variant #2: property literal node', () => {
describe('Variant #1: property key literal node', () => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
let propertyNode: ESTree.Property;
before(() => {
propertyNode = NodeFactory.propertyNode(
literalNode,
NodeFactory.literalNode(1)
);
literalNode.parentNode = propertyNode;
});
it('should return false for property key literal node', () => {
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, propertyNode), true);
});
});
describe('Variant #2: computed property key literal node', () => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
let propertyNode: ESTree.Property;
before(() => {
propertyNode = NodeFactory.propertyNode(
literalNode,
NodeFactory.literalNode(1),
true
);
literalNode.parentNode = propertyNode;
});
it('should return false for computed property key literal node', () => {
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, propertyNode), false);
});
});
describe('Variant #3: property value literal node', () => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
let propertyNode: ESTree.Property;
before(() => {
propertyNode = NodeFactory.propertyNode(
NodeFactory.literalNode(1),
literalNode
);
literalNode.parentNode = propertyNode;
});
it('should return false for property value literal node', () => {
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, propertyNode), false);
});
});
});
describe('Variant #3: import declaration node', () => {
describe('Variant #1: base import declaration literal node', () => {
const literalNode: ESTree.Literal = NodeFactory.literalNode('foo');
let importDeclarationNode: ESTree.ImportDeclaration;
before(() => {
importDeclarationNode = NodeFactory.importDeclarationNode(
[],
literalNode
);
literalNode.parentNode = importDeclarationNode;
});
it('should return false for import declaration literal node', () => {
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, importDeclarationNode), true);
});
});
});
});
describe('Number literal node', () => {
describe('Variant #1: base number literal node', () => {
const literalNode: ESTree.Literal = NodeFactory.literalNode(1);
let statementNode: ESTree.Statement;
before(() => {
statementNode = NodeFactory.expressionStatementNode(
literalNode
);
const blockStatementNode: ESTree.BlockStatement = NodeFactory.blockStatementNode([
statementNode
]);
statementNode.parentNode = blockStatementNode;
literalNode.parentNode = statementNode;
});
it('should return false for base number literal node', () => {
assert.equal(NodeLiteralUtils.isProhibitedLiteralNode(literalNode, statementNode), false);
});
});
});
});
});