Commits

kai zhu committed 7512dfd

cleanup js instrumenter and rename to coverage. replace manual exports with EXPORTS.exportLocal.

  • Participants
  • Parent commits f66f2f5

Comments (0)

Files changed (3)

 
     init: function () {
       //// EXPORTS
-      EXPORTS.jslintReport = local.jslintReport;
-      EXPORTS.jslintWatch = local.jslintWatch;
-      EXPORTS.moduleWatch = local.moduleWatch;
+      EXPORTS.exportLocal = local.exportLocal;
+      EXPORTS.exportLocal(local);
       EXPORTS.require = EXPORTS.require || require;
       EXPORTS.requireChildProcess = EXPORTS.requireChildProcess || require('child_process');
       EXPORTS.requireConnect = EXPORTS.requireConnect || require('connect');
       EXPORTS.requireUrl = EXPORTS.requireUrl || require('url');
       EXPORTS.requireUtil = EXPORTS.requireUtil || require('util');
       EXPORTS.requireVm = EXPORTS.requireVm || require('vm');
-      EXPORTS.stringFormat = local.stringFormat;
       EXPORTS.FS_MODULE = EXPORTS.FS_MODULE || EXPORTS.requirePath.dirname(module.filename);
       EXPORTS.JSLINT_WATCH = EXPORTS.JSLINT_WATCH || {};
       EXPORTS.MODULE = EXPORTS.MODULE || module;
       EXPORTS.MODULES = EXPORTS.MODULES || {};
-      EXPORTS.MODULE_ACTION = EXPORTS.MODULE_ACTION || {};
-      EXPORTS.MODULE_ACTION.base64Decode = local.moduleBase64Decode;
-      EXPORTS.MODULE_ACTION[String('e' + 'val')] = local.moduleEval;
-      EXPORTS.MODULE_ACTION.jslint = local.moduleJslint;
-      EXPORTS.MODULE_ACTION.watch = local.moduleWatch;
+      EXPORTS.MODULE_ACTION = {
+        base64Decode: local.moduleBase64Decode,
+        eval: local.moduleEval,
+        jslint: local.moduleJslint,
+        watch: local.moduleWatch
+      };
       EXPORTS.MODULE_FILE = EXPORTS.MODULE_FILE || {};
       EXPORTS.MODULE_WATCH = EXPORTS.MODULE_WATCH || {};
       EXPORTS.STR_ASCII = EXPORTS.STR_ASCII || '\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000b\f\r\u000e\u000f\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f !"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~';
       local.jslintWatch('./libUnused.js2');
     },
 
+    exportLocal: function (local) {
+      //// export local methods to EXPORTS
+      var arr, ii, key;
+      for (key in local) {
+        if (local.hasOwnProperty(key) && !(/^_|^init$/).test(key) && typeof local[key] === 'function') {
+          EXPORTS[key] = local[key];
+        }
+      }
+    },
+
     _jslintIgnore: function (str) {
       //// OPTIMIZATION - cached callback
       return str.match('\n').join('');
         filename,
         {interval: 1000, persistent: false},
         function (curr, prev) {
-          if (curr.mtime > prev.mtime) { local.jslintReport(filename); }
+          if (curr.mtime > prev.mtime) { EXPORTS.jslintReport(filename); }
         }
       );
     },
     },
 
     moduleJslint: function (module, file, str) {
-      local.jslintReport(file.name, str);
+      EXPORTS.jslintReport(file.name, str);
     },
 
     moduleLoad: function (module) {
       //// auto-reload module if modified
       EXPORTS.MODULE_WATCH[module.filename] = EXPORTS.MODULE_WATCH[module.filename] || EXPORTS.requireFs.watchFile(module.filename, {interval: 1000, persistent: false}, function (curr, prev) {
         //// reload module if modified
-        if (curr.mtime > prev.mtime) { local.moduleLoad(module, null, 'reload'); }
+        if (curr.mtime > prev.mtime) { EXPORTS.moduleLoad(module, null, 'reload'); }
       });
     },
 
     stringFormat: function (str, obj) {
       //// shared client / server template engine
-      var arr, fndBraket, fndKey, flag, ii, jj, result, rgxBraket, rgxKey, val;
+      var arr, fndBraket, fndKey, flag, ii = 0, jj, result = '', rgxBraket, rgxKey, val;
       if (!(obj && (/\{\{/).test(str))) { return str; }
-      ii = 0;
-      result = '';
       rgxBraket = (/\{\{(\w[^}]+)([ \w]*)\}\}/g);
       //// search for {{template}} to replace
       while (true) {
-/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libStable.js"}*/
+/*FILE_BEG {"actions": ["jslint", "eval", "watch"], "name": "libCore.js"}*/
 /*jslint bitwise: true, indent: 2, nomen: true, stupid: true*/
 (function () {
 
 
     init: function () {
       //// EXPORTS
-      EXPORTS.arrayZeros = local.arrayZeros;
-      EXPORTS.hashSha256 = local.hashSha256;
-      EXPORTS.jsonStringifyCircular = local.jsonStringifyCircular;
-      EXPORTS.jsonStringifySorted = local.jsonStringifySorted;
-      EXPORTS.objectFirstKey = local.objectFirstKey;
-      EXPORTS.shell = local.shell;
-      EXPORTS.streamReadBuffer = local.streamReadBuffer;
-      EXPORTS.testRun = local.testRun;
-      EXPORTS.uuid4 = local.uuid4;
+      EXPORTS.exportLocal(local);
     },
 
     arrayZeros: function (length) {
 
     init: function () {
       //// EXPORTS
-      EXPORTS.replParse = local.replParse;
-      EXPORTS.startRepl = local.startRepl;
+      EXPORTS.exportLocal(local);
       if (EXPORTS.REPL && EXPORTS.REPL.context) {
         EXPORTS.REPL.context.EXPORTS = EXPORTS;
-        EXPORTS.REPL[String('e' + 'val')] = local.replEval;
+        EXPORTS.REPL[String('e' + 'val')] = EXPORTS.replEval;
       }
     },
 
     startRepl: function () {
       //// start interactive interpreter / debugger
       EXPORTS.REPL = EXPORTS.REPL || EXPORTS.requireRepl.start({
-        eval: local.replEval,
+        eval: EXPORTS.replEval,
         useGlobal: true
       });
       local.init();
 
     init: function () {
       //// EXPORTS
-      EXPORTS.handlerEcho = local.handlerEcho;
-      EXPORTS.handlerHttpProxy = local.handlerHttpProxy;
-      EXPORTS.handlerStatic = local.handlerStatic;
-      EXPORTS.httpGet = local.httpGet;
-      EXPORTS.httpGetLocal = local.httpGetLocal;
-      EXPORTS.httpGetTest = local.httpGetTest;
-      EXPORTS.httpRequest = local.httpRequest;
-      EXPORTS.middlewareInstrumentJs = local.middlewareInstrumentJs;
-      EXPORTS.middlewarePath = local.middlewarePath;
-      EXPORTS.middlewareSecurity = local.middlewareSecurity;
-      EXPORTS.startServer = local.startServer;
+      EXPORTS.exportLocal(local);
+      EXPORTS.COVERAGE = EXPORTS.COVERAGE || new EXPORTS.requireIstanbul.Instrumenter();
       EXPORTS.HTTP_HANDLER = EXPORTS.HTTP_HANDLER || {};
       EXPORTS.HTTP_HANDLER['/echo'] = EXPORTS.handlerEcho;
       EXPORTS.HTTP_HANDLER['/http:'] = EXPORTS.handlerHttpProxy;
         EXPORTS.HTTP_APP.use(EXPORTS.requireConnect.logger('dev'));
         //// middleware - security
         EXPORTS.HTTP_APP.use(EXPORTS.middlewareSecurity);
-        //// middleware - instrument js files
-        EXPORTS.HTTP_APP.use(EXPORTS.middlewareInstrumentJs);
+        //// middleware - js coverage
+        EXPORTS.HTTP_APP.use(EXPORTS.middlewareCoverage);
         //// middleware - dynamic path handler
-        EXPORTS.HTTP_APP.use(local.middlewarePath);
+        EXPORTS.HTTP_APP.use(EXPORTS.middlewarePath);
       }
     },
 
+    coverageInstrument: function (code, filename) {
+      //// instrument js code
+      return EXPORTS.COVERAGE.instrumentSync(code, filename);
+    },
+
+    coverageInstrumentHtml: function (str, filename) {
+      //// instrument js scripts embedded in html
+      var ii = 0;
+      return str.replace((/<script>([\S\s]+)<\/script>/g), function (_, code) {
+        return '<script>' + EXPORTS.coverageInstrument(code, filename + '.script.' + (ii += 1)) + '</script>';
+      });
+    },
+
     handlerEcho: function (request, response) {
       //// echo's back request along with post data if any
       var headers, name;
       if (options.data) {
         options.method = options.method || 'POST';
       }
-      request = local.httpRequest(options);
+      request = EXPORTS.httpRequest(options);
       request.end(options.data);
     },
 
       options.url = 'http://localhost:' + EXPORTS.HTTP_PORT + options.url;
       options.headers = options.headers || {};
       options.headers.authorization = options.headers.authorization || 'Basic ' + EXPORTS.ADMIN_BASIC_AUTH;
-      local.httpGet(options);
+      EXPORTS.httpGet(options);
     },
 
     httpGetTest: function (options) {
           throw err;
         }
         console.assert(response.statusCode < 500, response.statusCode);
-        (callback || local.httpRequestCallback)(err, data, response);
+        (callback || EXPORTS.httpRequestCallback)(err, data, response);
       };
-      local.httpGetLocal(options);
+      EXPORTS.httpGetLocal(options);
     },
 
     httpRequest: function (options) {
       var url = EXPORTS.requireUrl.parse(options.url), request;
       //// OPTIMIZATION - disable socket pooling
       options.agent = false;
-      options.callback = options.callback || local.httpRequestCallback;
+      options.callback = options.callback || EXPORTS.httpRequestCallback;
       options.callbackResponse = options.callbackResponse || function (response) {
         EXPORTS.streamReadBuffer(response, function (err, data) {
           options.callback(err, data, response);
       }
     },
 
-    middlewareInstrumentJs: function (request, response, next) {
+    middlewareCoverage: function (request, response, next) {
       //// TODO - cache instrumented code
-      var chunks = [],
+      var chunks = '',
         end = response.end,
         write = response.write;
-      if (!(request.headers['instrument-js'] && request.url.slice(-3) === '.js')) {
+      if (!(/\bcoverage=1\b/).test(request.url)) {
         next();
         return;
       }
+      //// instrument file
       response.end = function (chunk) {
-        if (chunk) {
-          response.write(chunk);
-        }
+        var instrumented;
+        if (chunk) { chunks += chunk; }
+        //// restore response.end and response.write
         response.end = end;
         response.write = write;
-        new EXPORTS.requireIstanbul.Instrumenter().instrument(Buffer.concat(chunks).toString(), request.url, function (err, instrumented) {
-          if (err) {
-            next(err);
-            return;
+        try {
+          switch ((/\w+$/).exec(request.absolutePath)[0]) {
+          case 'html':
+            instrumented = EXPORTS.coverageInstrumentHtml(chunks, request.absolutePath);
+            break;
+          case 'js':
+            instrumented = EXPORTS.coverageInstrument(chunks, request.absolutePath);
+            break;
           }
           response.setHeader('content-length', Buffer.byteLength(instrumented));
           response.end(instrumented);
-        });
+        } catch (err) {
+          next(err);
+        }
       };
       response.write = function (chunk) {
-        chunks.push(typeof chunk === 'string' ? new Buffer(chunk) : chunk);
+        chunks += chunk;
         return true;
       };
       next();
 
     init: function () {
       //// EXPORTS
-      EXPORTS.externalGet = local.externalGet;
-      EXPORTS.externalRollup = local.externalRollup;
+      EXPORTS.exportLocal(local);
       EXPORTS.EXTERNAL_URL = {
         //// jquery
         'aa.jquery.js': 'http://code.jquery.com/jquery-1.9.1.js',
       switch (filename) {
       case 'bootstrap.css':
         data = data.replace(/"\.\.\/img\/(.+)"/g, function (_, filename) {
-          return local.externalDataUri(EXPORTS.FS_EXTERNAL + '/bootstrap.' + filename);
+          return EXPORTS.externalDataUri(EXPORTS.FS_EXTERNAL + '/bootstrap.' + filename);
         });
         break;
       case 'datatables.css':
         data = data.replace(/'\.\.\/images\/(.+)'/g, function (_, filename) {
-          return local.externalDataUri(EXPORTS.FS_EXTERNAL + '/datatables.' + filename);
+          return EXPORTS.externalDataUri(EXPORTS.FS_EXTERNAL + '/datatables.' + filename);
         });
         break;
       case 'select2.css':
         data = data.replace(/'(\w+\.png)'/g, function (_, filename) {
-          return local.externalDataUri(EXPORTS.FS_EXTERNAL + '/' + filename);
+          return EXPORTS.externalDataUri(EXPORTS.FS_EXTERNAL + '/' + filename);
         });
         break;
       }
       Object.keys(EXPORTS.EXTERNAL_URL).sort().forEach(function (filename) {
         switch (EXPORTS.requirePath.extname(filename)) {
         case '.css':
-          css += local._externalRollup(filename);
+          css += EXPORTS._externalRollup(filename);
           break;
         case '.js':
-          js += local._externalRollup(filename);
+          js += EXPORTS._externalRollup(filename);
           break;
         }
       });
       [
         'imgAjaxLoader.gif'
       ].forEach(function (filename) {
-        css += '.' + (/\w+/).exec(filename) + ' { background: url(' + local.externalDataUri(EXPORTS.FS_EXTERNAL + '/' + filename) + ') no-repeat center center;';
+        css += '.' + (/\w+/).exec(filename) + ' { background: url(' + EXPORTS.externalDataUri(EXPORTS.FS_EXTERNAL + '/' + filename) + ') no-repeat center center;';
       });
       EXPORTS.requireFs.writeFileSync(EXPORTS.FS_EXTERNAL + '/externalRollup.css', css);
       EXPORTS.requireFs.writeFileSync(EXPORTS.FS_EXTERNAL + '/externalRollup.js', js);
 
     init: function () {
       //// EXPORTS
-      EXPORTS.adminBasicAuthGet = local.adminBasicAuthGet;
-      EXPORTS.adminBasicAuthSet = local.adminBasicAuthSet;
-      EXPORTS.handlerAdminEval = local.handlerAdminEval;
-      EXPORTS.handlerAdminBasicAuth = local.handlerAdminBasicAuth;
+      EXPORTS.exportLocal(local);
       EXPORTS.ADMIN_BASIC_AUTH = EXPORTS.ADMIN_BASIC_AUTH || new Buffer(Math.random().toString(16).slice(2) + ':' + Math.random().toString(16).slice(2)).toString('base64');
       EXPORTS.HTTP_HANDLER['/admin'] = EXPORTS.handlerStatic;
       EXPORTS.HTTP_SECURITY['/admin'] = EXPORTS.handlerAdminBasicAuth;
     init: function () {
       if (!EXPORTS.HTTP_PORT) { return; }
       //// EXPORTS
+      EXPORTS.exportLocal(local);
       EXPORTS.FS_CWD = EXPORTS.FS_CWD || process.cwd();
       EXPORTS.FS_TMP = EXPORTS.FS_TMP || '/tmp/' + EXPORTS.FS_CWD.replace(/\W/g, '_') + '_' + EXPORTS.HTTP_PORT;
       EXPORTS.FS_CACHE = EXPORTS.FS_CACHE || EXPORTS.FS_TMP + '/cache';
       EXPORTS.FS_DB = EXPORTS.FS_DB || EXPORTS.FS_TMP + '/db';
-      EXPORTS.HTTP_HANDLER['/admin/db'] = local.dbHandler;
+      EXPORTS.HTTP_HANDLER['/admin/db'] = EXPORTS.dbHandler;
       //// create directories
       EXPORTS.requireFsExtra.mkdirpSync(EXPORTS.FS_CACHE);
       EXPORTS.requireFsExtra.mkdirpSync(EXPORTS.FS_DB);
           response.end(Array.isArray(data) ? JSON.stringify(data) : data);
         }
         try {
-          fnd = /\/db\/([\w]+)(.*)/.exec(local.dbAssertPath(request.absolutePath));
+          fnd = /\/db\/([\w]+)(.*)/.exec(EXPORTS.dbAssertPath(request.absolutePath));
           //// SECURITY - fs
           if (!fnd || fnd[2].length >= 256) {
             next();
           case 'rename2Data':
           //// rename record
           case 'rename3Data':
-            EXPORTS.requireFs.rename(path, path.replace(/[^\/]+$/, '') + local.dbAssertKey(data.toString()), callback);
+            EXPORTS.requireFs.rename(path, path.replace(/[^\/]+$/, '') + EXPORTS.dbAssertKey(data.toString()), callback);
             return;
           //// create table
           case 'set2':
             return;
           //// set record
           case 'set3Data':
-            local.fsWriteFileAtomic(path, data, callback);
+            EXPORTS.fsWriteFileAtomic(path, data, callback);
             return;
           }
           next();
 
     fsWriteFileAtomic: function (filename, data, callback) {
       //// atomicly write file by first writing to temporary file, and then renaming to filename
-      var tmp = local.fsTempFilename(filename);
+      var tmp = EXPORTS.fsTempFilename(filename);
       EXPORTS.requireFs.writeFile(tmp, data, function (err) {
         if (err) {
           callback(err);
   var EXPORTS = process.EXPORTS || {}, local = {
 
     init: function () {
-      if (!EXPORTS.HTTP_SERVER) {
-        return;
-      }
+      //// http tests
+      if (!EXPORTS.HTTP_SERVER) { return; }
       EXPORTS.TEST_HTTP.proxy = function () {
         EXPORTS.httpGetTest({
           callback: function (err, data) {
 /*
 CHANGELOG
-auto-convert object to string in stringFormat. cleanup externalDataUri.
+cleanup js instrumenter and rename to coverage. replace manual exports with EXPORTS.exportLocal.
 
 TODO
 auto-generate online documentation
   var EXPORTS = process.EXPORTS || {}, local = {
 
     init: function () {
-      var arr, ii, key;
-      for (key in local) {
-        if (local.hasOwnProperty(key) && !(/^_|^init$/).test(key)) {
-          EXPORTS[key] = local[key];
-        }
-      }
+      //// EXPORTS
+      EXPORTS.exportLocal(local);
     }
 
   };