codemod-peerconnection-addcleanup (2040B)
1 /* a codemod for ensuring RTCPeerConnection is cleaned up in tests. 2 * For each `new RTCPeerConnection` add a 3 * `test.add_cleanup(() => pc.close())` 4 * Only applies in promise_tests if there is no add_cleanup in the 5 * test function body. 6 */ 7 export default function transformer(file, api) { 8 const j = api.jscodeshift; 9 return j(file.source) 10 // find each RTCPeerConnection constructor 11 .find(j.NewExpression, {callee: {type: 'Identifier', name: 'RTCPeerConnection'}}) 12 13 // check it is inside a promise_test 14 .filter(path => { 15 // iterate parentPath until you find a CallExpression 16 let nextPath = path.parentPath; 17 while (nextPath && nextPath.value.type !== 'CallExpression') { 18 nextPath = nextPath.parentPath; 19 } 20 return nextPath && nextPath.value.callee.name === 'promise_test'; 21 }) 22 // check there is no add_cleanup in the function body 23 .filter(path => { 24 let nextPath = path.parentPath; 25 while (nextPath && nextPath.value.type !== 'CallExpression') { 26 nextPath = nextPath.parentPath; 27 } 28 const body = nextPath.value.arguments[0].body; 29 return j(body).find(j.Identifier, {name: 'add_cleanup'}).length === 0; 30 }) 31 .forEach(path => { 32 // iterate parentPath until you find a CallExpression 33 let nextPath = path.parentPath; 34 while (nextPath && nextPath.value.type !== 'CallExpression') { 35 nextPath = nextPath.parentPath; 36 } 37 const declaration = path.parentPath.parentPath.parentPath; 38 const pc = path.parentPath.value.id; 39 40 declaration.insertAfter( 41 j.expressionStatement( 42 j.callExpression( 43 j.memberExpression( 44 nextPath.node.arguments[0].params[0], 45 j.identifier('add_cleanup') 46 ), 47 [j.arrowFunctionExpression([], 48 j.callExpression( 49 j.memberExpression(pc, j.identifier('close'), false), 50 [] 51 ) 52 )] 53 ) 54 ) 55 ); 56 }) 57 .toSource(); 58 };