From 0eca5983951641b5d0884e6ce8fd162185d0cf05 Mon Sep 17 00:00:00 2001 From: tntim96 Date: Thu, 27 Oct 2022 15:33:53 +1100 Subject: [PATCH] Fix instruments in lit-html template (https://github.com/tntim96/JSCover/issues/311) Remove references to 'this' from header which breaks the example in #311 Remove redundant escape characters from regular expressions --- History.md | 1 + .../java/jscover/instrument/NodeProcessor.java | 14 ++++++++++++++ src/main/resources/header.js | 7 ++++--- src/main/resources/jscoverage-common.js | 2 +- src/main/resources/report.js | 2 +- .../resources/test-instrumented-file-system.js | 9 +++++---- .../resources/test-instrumented-server.js | 11 ++++++----- .../java/jscover/instrument/InstrumenterTest.java | 15 ++++++++++++--- 8 files changed, 44 insertions(+), 17 deletions(-) diff --git a/History.md b/History.md index 4936f1c9..249e40d0 100644 --- a/History.md +++ b/History.md @@ -1,5 +1,6 @@ 2.0.16 / 2022-??-?? ================== + * Fix instruments in lit-html template (https://github.com/tntim96/JSCover/issues/311) * Requires Java 11 * Upgrade closure-compiler v20220405 to v20221004, gson 2.9.0 to 2.10 * Internal: HtmlUnit 2.61.0 to 2.66.0, Mockito 4.5.1 to 4.8.1 diff --git a/src/main/java/jscover/instrument/NodeProcessor.java b/src/main/java/jscover/instrument/NodeProcessor.java index 81e94f9a..f8ab0f7c 100644 --- a/src/main/java/jscover/instrument/NodeProcessor.java +++ b/src/main/java/jscover/instrument/NodeProcessor.java @@ -371,10 +371,24 @@ public Node buildFunctionInstrumentationStatement(int functionNumber) { return statementBuilder.buildFunctionInstrumentationStatement(functionNumber, fileName); } + boolean isInTemplateLiteral(Node node) { + if (node.isTemplateLit()) { + return true; + } + Node parent = node.getParent(); + if (parent == null) { + return false; + } + return isInTemplateLiteral(parent); + } + boolean processNode(Node node) { if (statementBuilder.isInstrumentation(node)) { return false; } + if (isInTemplateLiteral(node)) { + return false; + } // Function Coverage (HA-CA), tntim96 if (includeFunctionCoverage && node.isFunction() && !node.isArrowFunction()) { Node block = node.getChildAtIndex(2); diff --git a/src/main/resources/header.js b/src/main/resources/header.js index 3668e479..2b1b7571 100644 --- a/src/main/resources/header.js +++ b/src/main/resources/header.js @@ -30,11 +30,12 @@ if (!jsCover_isolateBrowser) { try { if (typeof top === 'object' && top !== null && top._$jscoverage) { - this._$jscoverage = top._$jscoverage; + _$jscoverage = top._$jscoverage; } } catch (e) { } } -if (!this._$jscoverage) { - this._$jscoverage = {}; +var _$jscoverage; +if (!_$jscoverage) { + _$jscoverage = {}; } diff --git a/src/main/resources/jscoverage-common.js b/src/main/resources/jscoverage-common.js index bb114024..406b6d11 100644 --- a/src/main/resources/jscoverage-common.js +++ b/src/main/resources/jscoverage-common.js @@ -72,7 +72,7 @@ function jscoverage_pad(s) { } function jscoverage_html_escape(s) { - return s.replace(/[<>\&\"\']/g, function (c) { + return s.replace(/[<>&"']/g, function (c) { return '&#' + c.charCodeAt(0) + ';'; }); } diff --git a/src/main/resources/report.js b/src/main/resources/report.js index 55c00184..9821a6eb 100644 --- a/src/main/resources/report.js +++ b/src/main/resources/report.js @@ -21,7 +21,7 @@ if (!window.jscoverage_report) { //console.log("Configuring async jsreport cb"); request.onreadystatechange = function () { //console.log("jsreport cb called"); - if (request.readyState == 4 && callback) { + if (request.readyState === 4 && callback) { callback(request); } }; diff --git a/src/test-integration/resources/test-instrumented-file-system.js b/src/test-integration/resources/test-instrumented-file-system.js index 98e8901e..f0c2edc3 100644 --- a/src/test-integration/resources/test-instrumented-file-system.js +++ b/src/test-integration/resources/test-instrumented-file-system.js @@ -200,7 +200,7 @@ function jscoverage_pad(s) { } function jscoverage_html_escape(s) { - return s.replace(/[<>\&\"\']/g, function (c) { + return s.replace(/[<>&"']/g, function (c) { return '&#' + c.charCodeAt(0) + ';'; }); } @@ -237,13 +237,14 @@ if (!jsCover_isolateBrowser) { try { if (typeof top === 'object' && top !== null && top._$jscoverage) { - this._$jscoverage = top._$jscoverage; + _$jscoverage = top._$jscoverage; } } catch (e) { } } -if (!this._$jscoverage) { - this._$jscoverage = {}; +var _$jscoverage; +if (!_$jscoverage) { + _$jscoverage = {}; } if (! _$jscoverage['test-simple.js']) { _$jscoverage['test-simple.js'] = {}; diff --git a/src/test-integration/resources/test-instrumented-server.js b/src/test-integration/resources/test-instrumented-server.js index c3a3b14b..c88a6d1d 100644 --- a/src/test-integration/resources/test-instrumented-server.js +++ b/src/test-integration/resources/test-instrumented-server.js @@ -21,7 +21,7 @@ if (!window.jscoverage_report) { //console.log("Configuring async jsreport cb"); request.onreadystatechange = function () { //console.log("jsreport cb called"); - if (request.readyState == 4 && callback) { + if (request.readyState === 4 && callback) { callback(request); } }; @@ -231,7 +231,7 @@ function jscoverage_pad(s) { } function jscoverage_html_escape(s) { - return s.replace(/[<>\&\"\']/g, function (c) { + return s.replace(/[<>&"']/g, function (c) { return '&#' + c.charCodeAt(0) + ';'; }); } @@ -268,13 +268,14 @@ if (!jsCover_isolateBrowser) { try { if (typeof top === 'object' && top !== null && top._$jscoverage) { - this._$jscoverage = top._$jscoverage; + _$jscoverage = top._$jscoverage; } } catch (e) { } } -if (!this._$jscoverage) { - this._$jscoverage = {}; +var _$jscoverage; +if (!_$jscoverage) { + _$jscoverage = {}; } if (! _$jscoverage['test-simple.js']) { _$jscoverage['test-simple.js'] = {}; diff --git a/src/test/java/jscover/instrument/InstrumenterTest.java b/src/test/java/jscover/instrument/InstrumenterTest.java index 34c3da13..03b32112 100644 --- a/src/test/java/jscover/instrument/InstrumenterTest.java +++ b/src/test/java/jscover/instrument/InstrumenterTest.java @@ -351,10 +351,9 @@ You should also get your employer (if you work as a programmer) or your import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; -import java.io.IOException; - import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.*; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.hasItem; import static org.junit.Assert.assertEquals; import static org.mockito.BDDMockito.given; @@ -1458,4 +1457,14 @@ public void shouldInstrumentFunctionAfterCommaInAssignment() { "};\n"; assertEquals(expectedSource, instrumentedSource); } + + + @Test + public void shouldInstrumentTemplateLiteral() { + String source = "let x = `\n@mouseenter=\"${(evt) => alert('hovered')}\">`;"; + String instrumentedSource = sourceProcessor.instrumentSource(source); + String expectedSource = "_$jscoverage['test.js'].lineData[1]++;\n" + + "let x = `\n@mouseenter=\"${evt => alert('hovered')}\">`;\n"; + assertEquals(expectedSource, instrumentedSource); + } }