// Copyright 2017 the V8 project authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // Flags: --allow-natives-syntax --no-always-opt --block-coverage // Flags: --no-stress-fullcodegen --harmony-async-iteration // Files: test/mjsunit/code-coverage-utils.js %DebugToggleBlockCoverage(true); TestCoverage( "call an IIFE", ` (function f() {})(); `, [{"start":0,"end":20,"count":1},{"start":1,"end":16,"count":1}] ); TestCoverage( "call locally allocated function", `let f = () => 1; f();`, [{"start":0,"end":21,"count":1},{"start":8,"end":15,"count":1}] ); TestCoverage( "if statements", ` function g() {} // 0000 function f(x) { // 0050 if (x == 42) { // 0100 if (x == 43) g(); else g(); // 0150 } // 0200 if (x == 42) { g(); } else { g(); } // 0250 if (x == 42) g(); else g(); // 0300 if (false) g(); else g(); // 0350 if (false) g(); // 0400 if (true) g(); else g(); // 0450 if (true) g(); // 0500 } // 0550 f(42); // 0600 f(43); // 0650 `, [{"start":0,"end":699,"count":1}, {"start":0,"end":15,"count":11}, {"start":50,"end":551,"count":2}, {"start":115,"end":203,"count":1}, {"start":167,"end":171,"count":0}, {"start":265,"end":273,"count":1}, {"start":279,"end":287,"count":1}, {"start":315,"end":319,"count":1}, {"start":325,"end":329,"count":1}, {"start":363,"end":367,"count":0}, {"start":413,"end":417,"count":0}, {"start":472,"end":476,"count":0}] ); TestCoverage( "if statement (early return)", ` !function() { // 0000 if (true) { // 0050 nop(); // 0100 return; // 0150 nop(); // 0200 } // 0250 nop(); // 0300 }() // 0350 `, [{"start":0,"end":399,"count":1}, {"start":1,"end":351,"count":1}, {"start":161,"end":351,"count":0}] ); TestCoverage( "if statement (no semi-colon)", ` !function() { // 0000 if (true) nop() // 0050 if (true) nop(); else nop() // 0100 nop(); // 0150 }() // 0200 `, [{"start":0,"end":249,"count":1}, {"start":1,"end":201,"count":1}, {"start":124,"end":129,"count":0}] ); TestCoverage( "for statements", ` function g() {} // 0000 !function() { // 0050 for (var i = 0; i < 12; i++) g(); // 0100 for (var i = 0; i < 12; i++) { // 0150 g(); // 0200 } // 0250 for (var i = 0; false; i++) g(); // 0300 for (var i = 0; true; i++) break; // 0350 for (var i = 0; i < 12; i++) { // 0400 if (i % 3 == 0) g(); else g(); // 0450 } // 0500 }(); // 0550 `, [{"start":0,"end":599,"count":1}, {"start":0,"end":15,"count":36}, {"start":51,"end":551,"count":1}, {"start":131,"end":135,"count":12}, {"start":181,"end":253,"count":12}, {"start":330,"end":334,"count":0}, {"start":431,"end":503,"count":12}, {"start":470,"end":474,"count":4}, {"start":480,"end":484,"count":8}] ); TestCoverage( "for statements pt. 2", ` function g() {} // 0000 !function() { // 0050 let j = 0; // 0100 for (let i = 0; i < 12; i++) g(); // 0150 for (const i = 0; j < 12; j++) g(); // 0200 for (j = 0; j < 12; j++) g(); // 0250 for (;;) break; // 0300 }(); // 0350 `, [{"start":0,"end":399,"count":1}, {"start":0,"end":15,"count":36}, {"start":51,"end":351,"count":1}, {"start":181,"end":185,"count":12}, {"start":233,"end":237,"count":12}, {"start":277,"end":281,"count":12}] ); TestCoverage( "for statements (no semicolon)", ` function g() {} // 0000 !function() { // 0050 for (let i = 0; i < 12; i++) g() // 0100 for (let i = 0; i < 12; i++) break // 0150 for (let i = 0; i < 12; i++) break; g() // 0200 }(); // 0250 `, [{"start":0,"end":299,"count":1}, {"start":0,"end":15,"count":13}, {"start":51,"end":251,"count":1}, {"start":131,"end":134,"count":12}] ); TestCoverage( "for statement (early return)", ` !function() { // 0000 for (var i = 0; i < 10; i++) { // 0050 nop(); // 0100 continue; // 0150 nop(); // 0200 } // 0250 nop(); // 0300 for (;;) { // 0350 nop(); // 0400 break; // 0450 nop(); // 0500 } // 0550 nop(); // 0600 for (;;) { // 0650 nop(); // 0700 return; // 0750 nop(); // 0800 } // 0850 nop(); // 0900 }() // 0950 `, [{"start":0,"end":999,"count":1}, {"start":1,"end":951,"count":1}, {"start":81,"end":253,"count":10}, {"start":163,"end":253,"count":0}, {"start":460,"end":553,"count":0}, {"start":761,"end":951,"count":0}] ); TestCoverage( "for-of and for-in statements", ` !function() { // 0000 var i; // 0050 for (i of [0,1,2,3]) { nop(); } // 0100 for (let j of [0,1,2,3]) { nop(); } // 0150 for (i in [0,1,2,3]) { nop(); } // 0200 for (let j in [0,1,2,3]) { nop(); } // 0250 var xs = [{a:0, b:1}, {a:1,b:0}]; // 0300 for (var {a: x, b: y} of xs) { nop(); } // 0350 }(); // 0400 `, [{"start":0,"end":449,"count":1}, {"start":1,"end":401,"count":1}, {"start":123,"end":133,"count":4}, {"start":177,"end":187,"count":4}, {"start":223,"end":233,"count":4}, {"start":277,"end":287,"count":4}, {"start":381,"end":391,"count":2}] ); TestCoverage( "for-await-of statements", ` !async function() { // 0000 for await (var x of [0,1,2,3]) { // 0050 nop(); // 0100 } // 0150 }(); // 0200 %RunMicrotasks(); // 0250 `, [{"start":0,"end":299,"count":1}, {"start":1,"end":201,"count":6}, // TODO(jgruber): Invocation count is off. {"start":83,"end":153,"count":4}, {"start":153,"end":201,"count":1}] ); TestCoverage( "while and do-while statements", ` function g() {} // 0000 !function() { // 0050 var i; // 0100 i = 0; while (i < 12) i++; // 0150 i = 0; while (i < 12) { g(); i++; } // 0200 i = 0; while (false) g(); // 0250 i = 0; while (true) break; // 0300 // 0350 i = 0; do i++; while (i < 12); // 0400 i = 0; do { g(); i++; } // 0450 while (i < 12); // 0500 i = 0; do { g(); } while (false); // 0550 i = 0; do { break; } while (true); // 0600 }(); // 0650 `, [{"start":0,"end":699,"count":1}, {"start":0,"end":15,"count":25}, {"start":51,"end":651,"count":1}, {"start":174,"end":178,"count":12}, {"start":224,"end":237,"count":12}, {"start":273,"end":277,"count":0}, {"start":412,"end":416,"count":12}, {"start":462,"end":475,"count":12}, {"start":620,"end":622,"count":0}] ); TestCoverage( "while statement (early return)", ` !function() { // 0000 let i = 0; // 0050 while (i < 10) { // 0100 i++; // 0150 continue; // 0200 nop(); // 0250 } // 0300 nop(); // 0350 while (true) { // 0400 nop(); // 0450 break; // 0500 nop(); // 0550 } // 0600 nop(); // 0650 while (true) { // 0700 nop(); // 0750 return; // 0800 nop(); // 0850 } // 0900 nop(); // 0950 }() // 1000 `, [{"start":0,"end":1049,"count":1}, {"start":1,"end":1001,"count":1}, {"start":117,"end":303,"count":10}, {"start":213,"end":303,"count":0}, {"start":510,"end":603,"count":0}, {"start":811,"end":1001,"count":0}] ); TestCoverage( "do-while statement (early return)", ` !function() { // 0000 let i = 0; // 0050 do { // 0100 i++; // 0150 continue; // 0200 nop(); // 0250 } while (i < 10); // 0300 nop(); // 0350 do { // 0400 nop(); // 0450 break; // 0500 nop(); // 0550 } while (true); // 0600 nop(); // 0650 do { // 0700 nop(); // 0750 return; // 0800 nop(); // 0850 } while (true); // 0900 nop(); // 0950 }() // 1000 `, [{"start":0,"end":1049,"count":1}, {"start":1,"end":1001,"count":1}, {"start":105,"end":303,"count":10}, {"start":213,"end":303,"count":0}, {"start":510,"end":603,"count":0}, {"start":811,"end":1001,"count":0}] ); TestCoverage( "return statements", ` !function() { nop(); return; nop(); }(); // 0000 !function() { nop(); return 42; // 0050 nop(); }(); // 0100 `, [{"start":0,"end":149,"count":1}, {"start":1,"end":37,"count":1}, {"start":28,"end":37,"count":0}, {"start":51,"end":122,"count":1}, {"start":81,"end":122,"count":0}] ); TestCoverage( "try/catch/finally statements", ` !function() { // 0000 try { nop(); } catch (e) { nop(); } // 0050 try { nop(); } finally { nop(); } // 0100 try { // 0150 try { throw 42; } catch (e) { nop(); }// 0200 } catch (e) { nop(); } // 0250 try { // 0300 try { throw 42; } finally { nop(); } // 0350 } catch (e) { nop(); } // 0400 try { // 0450 throw 42; // 0500 } catch (e) { // 0550 nop(); // 0600 } finally { // 0650 nop(); // 0700 } // 0750 }(); // 0800 `, [{"start":0,"end":849,"count":1}, {"start":1,"end":801,"count":1}, {"start":77,"end":87,"count":0}, {"start":219,"end":232,"count":0}, {"start":264,"end":274,"count":0}, {"start":369,"end":380,"count":0}, {"start":403,"end":414,"count":0}, // TODO(jgruber): Include `catch` in range. {"start":513,"end":564,"count":0}] ); TestCoverage( "early return in blocks", ` !function() { // 0000 try { throw 42; } catch (e) { return; } // 0050 nop(); // 0100 }(); // 0150 !function() { // 0200 try { nop(); } finally { return; } // 0250 nop(); // 0300 }(); // 0350 !function() { // 0400 { // 0450 let x = 42; // 0500 return () => x; // 0550 } // 0600 nop(); // 0650 }(); // 0700 !function() { // 0750 try { throw 42; } catch (e) { // 0800 return; // 0850 nop(); // 0900 } // 0950 nop(); // 1000 }(); // 1050 `, [{"start":0,"end":1099,"count":1}, {"start":1,"end":151,"count":1}, {"start":67,"end":80,"count":0}, {"start":89,"end":151,"count":0}, {"start":201,"end":351,"count":1}, {"start":284,"end":351,"count":0}, {"start":401,"end":701,"count":1}, {"start":569,"end":701,"count":0}, {"start":561,"end":568,"count":0}, // TODO(jgruber): Sorting. {"start":751,"end":1051,"count":1}, {"start":817,"end":830,"count":0}, {"start":861,"end":1051,"count":0}] ); TestCoverage( "switch statements", ` !function() { // 0000 var x = 42; // 0050 switch (x) { // 0100 case 41: nop(); break; // 0150 case 42: nop(); break; // 0200 default: nop(); break; // 0250 } // 0300 }(); // 0350 `, [{"start":0,"end":399,"count":1}, {"start":1,"end":351,"count":1}, {"start":154,"end":204,"count":0}, {"start":226,"end":303,"count":0}] ); TestCoverage( "labeled break statements", ` !function() { // 0000 var x = 42; // 0050 l0: switch (x) { // 0100 case 41: return; // 0150 case 42: // 0200 switch (x) { case 42: break l0; } // 0250 break; // 0300 } // 0350 l1: for (;;) { // 0400 for (;;) break l1; // 0450 } // 0500 l2: while (true) { // 0550 while (true) break l2; // 0600 } // 0650 l3: do { // 0700 do { break l3; } while (true); // 0750 } while (true); // 0800 l4: { break l4; } // 0850 l5: for (;;) for (;;) break l5; // 0900 }(); // 0950 `, [{"start":0,"end":999,"count":1}, {"start":1,"end":951,"count":1}, {"start":152,"end":202,"count":0}, {"start":285,"end":353,"count":0}, {"start":472,"end":503,"count":0}, {"start":626,"end":653,"count":0}, {"start":768,"end":803,"count":0}, {"start":867,"end":869,"count":0}] ); TestCoverage( "labeled continue statements", ` !function() { // 0000 l0: for (var i0 = 0; i0 < 2; i0++) { // 0050 for (;;) continue l0; // 0100 } // 0150 var i1 = 0; // 0200 l1: while (i1 < 2) { // 0250 i1++; // 0300 while (true) continue l1; // 0350 } // 0400 var i2 = 0; // 0450 l2: do { // 0500 i2++; // 0550 do { continue l2; } while (true); // 0600 } while (i2 < 2); // 0650 }(); // 0700 `, [{"start":0,"end":749,"count":1}, {"start":1,"end":701,"count":1}, {"start":87,"end":153,"count":2}, {"start":125,"end":153,"count":0}, {"start":271,"end":403,"count":2}, {"start":379,"end":403,"count":0}, {"start":509,"end":653,"count":2}, {"start":621,"end":653,"count":0}] ); TestCoverage( "conditional expressions", ` var TRUE = true; // 0000 var FALSE = false; // 0050 !function() { // 0100 TRUE ? nop() : nop(); // 0150 true ? nop() : nop(); // 0200 false ? nop() : nop(); // 0250 FALSE ? TRUE ? nop() // 0300 : nop() // 0350 : nop(); // 0400 TRUE ? FALSE ? nop() // 0450 : nop() // 0500 : nop(); // 0550 TRUE ? nop() : FALSE ? nop() // 0600 : nop(); // 0650 FALSE ? nop() : TRUE ? nop() // 0700 : nop(); // 0750 }(); // 0800 `, [{"start":0,"end":849,"count":1}, {"start":101,"end":801,"count":1}, {"start":167,"end":172,"count":0}, {"start":217,"end":222,"count":0}, {"start":260,"end":265,"count":0}, {"start":310,"end":372,"count":0}, {"start":467,"end":472,"count":0}, {"start":559,"end":564,"count":0}, {"start":617,"end":680,"count":0}, {"start":710,"end":715,"count":0}, {"start":775,"end":780,"count":0}] ); TestCoverage( "yield expressions", ` const it = function*() { // 0000 yield nop(); // 0050 yield nop() ? nop() : nop() // 0100 return nop(); // 0150 }(); // 0200 it.next(); it.next(); // 0250 `, [{"start":0,"end":299,"count":1}, {"start":11,"end":201,"count":3}, {"start":64,"end":116,"count":1}, {"start":116,"end":121,"count":0}, {"start":124,"end":129,"count":1}, {"start":129,"end":201,"count":0}] ); TestCoverage( "yield expressions (.return and .throw)", ` const it0 = function*() { // 0000 yield 1; yield 2; yield 3; // 0050 }(); // 0100 it0.next(); it0.return(); // 0150 try { // 0200 const it1 = function*() { // 0250 yield 1; yield 2; yield 3; // 0300 }(); // 0350 it1.next(); it1.throw(); // 0400 } catch (e) {} // 0450 `, [{"start":0,"end":499,"count":1}, {"start":12,"end":101,"count":3}, {"start":60,"end":101,"count":0}, {"start":264,"end":353,"count":3}, {"start":312,"end":353,"count":0}] ); TestCoverage("yield expressions (.return and try/catch/finally)", ` const it = function*() { // 0000 try { // 0050 yield 1; yield 2; yield 3; // 0100 } catch (e) { // 0150 nop(); // 0200 } finally { nop(); } // 0250 yield 4; // 0300 }(); // 0350 it.next(); it.return(); // 0450 `, [{"start":0,"end":449,"count":1}, {"start":11,"end":351,"count":3}, {"start":112,"end":253,"count":0}, {"start":262,"end":272,"count":1}, {"start":310,"end":351,"count":0}] // TODO(jgruber): Missing continuation. ); TestCoverage("yield expressions (.throw and try/catch/finally)", ` const it = function*() { // 0000 try { // 0050 yield 1; yield 2; yield 3; // 0100 } catch (e) { // 0150 nop(); // 0200 } finally { nop(); } // 0250 yield 4; // 0300 }(); // 0350 it.next(); it.throw(42); // 0550 `, [{"start":0,"end":449,"count":1}, {"start":11,"end":351,"count":3}, {"start":112,"end":164,"count":0}, {"start":164,"end":253,"count":1}, {"start":262,"end":272,"count":1}, {"start":310,"end":351,"count":0}] // TODO(jgruber): Missing continuation. ); TestCoverage( "yield* expressions", ` const it = function*() { // 0000 yield* gen(); // 0050 yield* nop() ? gen() : gen() // 0100 return gen(); // 0150 }(); // 0200 it.next(); it.next(); it.next(); // 0250 it.next(); it.next(); it.next(); // 0300 `, [{"start":0,"end":349,"count":1}, {"start":11,"end":201,"count":7}, {"start":65,"end":117,"count":1}, {"start":117,"end":122,"count":0}, {"start":125,"end":130,"count":1}, {"start":130,"end":201,"count":0}] ); TestCoverage( "yield* expressions (.return and .throw)", ` const it0 = function*() { // 0000 yield* gen(); yield* gen(); yield 3; // 0050 }(); // 0100 it0.next(); it0.return(); // 0150 try { // 0200 const it1 = function*() { // 0250 yield* gen(); yield* gen(); yield 3; // 0300 }(); // 0350 it1.next(); it1.throw(); // 0400 } catch (e) {} // 0450 `, [{"start":0,"end":499,"count":1}, {"start":12,"end":101,"count":3}, {"start":65,"end":101,"count":0}, {"start":264,"end":353,"count":3}, {"start":317,"end":353,"count":0}] ); TestCoverage( "await expressions", ` async function f() { // 0000 await 42; // 0050 await 42; // 0100 }; // 0150 f(); // 0200 %RunMicrotasks(); // 0250 `, [{"start":0,"end":299,"count":1}, {"start":0,"end":151,"count":3}, {"start":61,"end":151,"count":1}] ); %DebugToggleBlockCoverage(false);