• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2020 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5/**
6 * @fileoverview Variables mutator.
7 */
8
9'use strict';
10
11const babelTypes = require('@babel/types');
12
13const common = require('./common.js');
14const random = require('../random.js');
15const mutator = require('./mutator.js');
16
17function _isInFunctionParam(path) {
18  const child = path.find(p => p.parent && babelTypes.isFunction(p.parent));
19  return child && child.parentKey === 'params';
20}
21
22class VariableMutator extends mutator.Mutator {
23  constructor(settings) {
24    super();
25    this.settings = settings;
26  }
27
28  get visitor() {
29    const thisMutator = this;
30
31    return {
32      Identifier(path) {
33        if (!random.choose(thisMutator.settings.MUTATE_VARIABLES)) {
34          return;
35        }
36
37        if (!common.isVariableIdentifier(path.node.name)) {
38          return;
39        }
40
41        // Don't mutate variables that are being declared.
42        if (babelTypes.isVariableDeclarator(path.parent)) {
43          return;
44        }
45
46        // Don't mutate function params.
47        if (_isInFunctionParam(path)) {
48          return;
49        }
50
51        if (common.isInForLoopCondition(path) ||
52            common.isInWhileLoop(path)) {
53          return;
54        }
55
56        const randVar = common.randomVariable(path);
57        if (!randVar) {
58          return;
59        }
60
61        const newName = randVar.name;
62        thisMutator.annotate(
63            path.node,
64            `Replaced ${path.node.name} with ${newName}`);
65        path.node.name = newName;
66      }
67    };
68  }
69}
70
71module.exports = {
72  VariableMutator: VariableMutator,
73};
74