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