• 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 Expression mutator.
7 */
8
9'use strict';
10
11const babelTypes = require('@babel/types');
12
13const random = require('../random.js');
14const mutator = require('./mutator.js');
15
16class ExpressionMutator extends mutator.Mutator {
17  constructor(settings) {
18    super();
19    this.settings = settings;
20  }
21
22  get visitor() {
23    const thisMutator = this;
24
25    return {
26      ExpressionStatement(path) {
27        if (!random.choose(thisMutator.settings.MUTATE_EXPRESSIONS)) {
28          return;
29        }
30
31        const probability = random.random();
32
33        if (probability < 0.7) {
34          const repeated = babelTypes.cloneDeep(path.node);
35          thisMutator.annotate(repeated, 'Repeated');
36          thisMutator.insertBeforeSkip(path, repeated);
37        } else if (path.key > 0) {
38          // Get a random previous sibling.
39          const prev = path.getSibling(random.randInt(0, path.key - 1));
40          if (!prev || !prev.node) {
41            return;
42          }
43          // Either select a previous or the current node to clone.
44          const [selected, destination] = random.shuffle([prev, path]);
45          if (selected.isDeclaration()) {
46            return;
47          }
48          const cloned = babelTypes.cloneDeep(selected.node);
49          thisMutator.annotate(cloned, 'Cloned sibling');
50          if (random.choose(0.5)) {
51            thisMutator.insertBeforeSkip(destination, cloned);
52          } else {
53            thisMutator.insertAfterSkip(destination, cloned);
54          }
55        }
56      },
57    };
58  }
59}
60
61module.exports = {
62  ExpressionMutator: ExpressionMutator,
63};
64