1 | var util = require('util');
|
2 | var fs = require('fs');
|
3 | var FileInstrumenter = require("./file-instrumenter");
|
4 | var MarkupFileParser = require("../markup-files-parser");
|
5 | var FILE_INSTRUMENTATION_ERROR_MESSAGE = "Failed during instrumentation file ";
|
6 | var FILE_WRITING_ERROR_MESSAGE = "Failed while writing instrumented file.";
|
7 | var FILE_READING_ERROR_MESSAGE = "Failed reading file contents.";
|
8 |
|
9 | function MarkupFileInstrumenter() {
|
10 | FileInstrumenter.apply(this, arguments);
|
11 | this.originalFile = "";
|
12 | this.instrumentedFile = "";
|
13 | this.scriptTags = [];
|
14 | this.errorLoggingMessage = "";
|
15 | this.fiileHandler = null;
|
16 | }
|
17 |
|
18 | util.inherits(MarkupFileInstrumenter, FileInstrumenter);
|
19 | module.exports = MarkupFileInstrumenter;
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 | MarkupFileInstrumenter.prototype._instrumentFile = function (inputFile, outputFile, name, preambleHeader, callback) {
|
26 | this.logger.debug("Instrumenting file '" + inputFile + "'.");
|
27 | try {
|
28 | this._extractScripts(inputFile);
|
29 | if(!this._hasJsInFile()) {
|
30 | return this._handleFileWithoutJS(outputFile, name, callback);
|
31 | }
|
32 | this._markScripts();
|
33 | return this._instrumentAndReplace(name, inputFile, outputFile, callback);
|
34 | } catch (err) {
|
35 | return this._handleInstrumentationError(this.errorLoggingMessage, err, name, callback);
|
36 | }
|
37 | };
|
38 |
|
39 | MarkupFileInstrumenter.prototype._extractScripts = function(inputFile) {
|
40 | this.errorLoggingMessage = FILE_READING_ERROR_MESSAGE;
|
41 | var fileContents = fs.readFileSync(inputFile, 'utf8');
|
42 | fileContents = this._onBeforeInstrumentation(fileContents);
|
43 | this.originalFile = fileContents;
|
44 | this.instrumentedFile = fileContents;
|
45 | this.fileParser = getFileParser(fileContents, inputFile, this.logger);
|
46 | this.scriptTags = cloneTagsArray(this.fileParser.scriptTags);
|
47 | }
|
48 |
|
49 | MarkupFileInstrumenter.prototype.instrumentationCallback = function (err, instrumentedContent, outputFile, name, callback) {
|
50 | if (err) {
|
51 | throw err;
|
52 | }
|
53 | this._replaceOldJsByInstrumented(instrumentedContent);
|
54 | this._insertCoverageCodeTag(instrumentedContent);
|
55 | this._insertPreambleTag();
|
56 | this.instrumentedFile = this._onAfterInstrumentation(this.instrumentedFile);
|
57 | return this._saveFileContent(outputFile, name, callback);
|
58 | }
|
59 |
|
60 | MarkupFileInstrumenter.prototype._instrumentAndReplace = function(name, inputFile, outputFile, callback) {
|
61 | var _this = this;
|
62 | var jsCode = this.fileParser.getAllJsInFile();
|
63 | this.errorLoggingMessage = FILE_INSTRUMENTATION_ERROR_MESSAGE + name;
|
64 | this.instrumenter.instrument(jsCode, inputFile, function (err, instrumentedContent) {
|
65 | return _this.instrumentationCallback(err, instrumentedContent, outputFile, name, callback);
|
66 | }, {
|
67 | filename: name,
|
68 | inputSourceMap: null
|
69 | });
|
70 | }
|
71 |
|
72 | MarkupFileInstrumenter.prototype._replaceOldJsByInstrumented = function(instrumentedContent){
|
73 | for (var i = 0; i < this.scriptTags.length; i++) {
|
74 | var currentTag = this.scriptTags[i];
|
75 | var scriptMarker = createScriptMarker(i);
|
76 | var scriptStartIndex = instrumentedContent.indexOf(scriptMarker);
|
77 | scriptStartIndex += scriptMarker.length;
|
78 | var scriptEndIndex = instrumentedContent.lastIndexOf(scriptMarker);
|
79 | var instrumentedScript = instrumentedContent.substring(scriptStartIndex, scriptEndIndex);
|
80 | this.instrumentedFile = this.instrumentedFile.replace(currentTag.content, instrumentedScript);
|
81 | }
|
82 | }
|
83 |
|
84 | MarkupFileInstrumenter.prototype._saveFileContent = function(outputFile, name, callback) {
|
85 | if (this.opts.onFileInstrumented != null) {
|
86 | this.opts.onFileInstrumented(name);
|
87 | }
|
88 | this.errorLoggingMessage = FILE_WRITING_ERROR_MESSAGE;
|
89 | fs.writeFileSync(outputFile, this.instrumentedFile, 'utf8');
|
90 | return callback(null, name);
|
91 | }
|
92 |
|
93 | MarkupFileInstrumenter.prototype._handleFileWithoutJS = function (outputFile, name, callback) {
|
94 | if (this.opts.onFileCopied != null) {
|
95 | this.opts.onFileCopied(name);
|
96 | }
|
97 | return this._saveFileContent(outputFile, name, callback);
|
98 | }
|
99 |
|
100 | MarkupFileInstrumenter.prototype._hasJsInFile = function() {
|
101 | return this.scriptTags.length !== 0 && isJSEmbeddedInFile(this.fileParser);
|
102 | }
|
103 |
|
104 | MarkupFileInstrumenter.prototype._insertCoverageCodeTag = function(instrumentedCode){
|
105 | var firstTagMarker = createScriptMarker(0);
|
106 | var firstTagStart = instrumentedCode.indexOf(firstTagMarker);
|
107 | var istanbulCoverageCode = instrumentedCode.substring(0, firstTagStart);
|
108 | var coverageCodeTag = "<script>\n\t" + istanbulCoverageCode + "\n</script>\n";
|
109 | this.instrumentedFile = this._insertTagAtBeginning(coverageCodeTag);
|
110 | }
|
111 |
|
112 | MarkupFileInstrumenter.prototype._insertPreambleTag = function() {
|
113 | var preambleTag = "<script>\n\t" + this.preambleHeader.join("\n") + "\n</script>\n";
|
114 | this.instrumentedFile = this._insertTagAtBeginning(preambleTag);
|
115 | };
|
116 |
|
117 | MarkupFileInstrumenter.prototype._markScripts = function(){
|
118 | var marked = [];
|
119 | for (var i = 0; i < this.fileParser.scriptTags.length; i++) {
|
120 | var slComment = createScriptMarker(i);
|
121 | var currentTag = this.fileParser.scriptTags[i];
|
122 | currentTag.content = slComment + currentTag.content + slComment;
|
123 | marked.push(currentTag);
|
124 | }
|
125 | this.fileParser.scriptTags = marked;
|
126 | }
|
127 |
|
128 | MarkupFileInstrumenter.prototype._insertTagAtBeginning = function(newTag) {
|
129 | var firstScriptTagIndex = this.instrumentedFile.search(/<script[\s\S]*?>/);
|
130 | return this.instrumentedFile.slice(0, firstScriptTagIndex) + newTag +
|
131 | this.instrumentedFile.slice(firstScriptTagIndex);
|
132 | };
|
133 |
|
134 | function getFileParser(fileContents, inputFile, logger) {
|
135 | var handler = new MarkupFileParser(fileContents, inputFile, logger);
|
136 | handler.extractScriptTags();
|
137 | return handler;
|
138 | }
|
139 |
|
140 |
|
141 |
|
142 | function isJSEmbeddedInFile(fileParser) {
|
143 | return fileParser.getAllJsInFile() !== "";
|
144 | }
|
145 |
|
146 |
|
147 | function createScriptMarker(index) {
|
148 | return "/********** SL tag no " + index + " **********/"
|
149 | }
|
150 |
|
151 |
|
152 |
|
153 |
|
154 | function cloneTagsArray(tagsArray){
|
155 | return JSON.parse(JSON.stringify( tagsArray));
|
156 | }
|
157 |
|
158 |
|