From e42ac8e35e2efbceb790681fc655917643542dc8 Mon Sep 17 00:00:00 2001 From: djulien Date: Sat, 12 Sep 2015 15:43:58 -0700 Subject: [PATCH 1/3] allow nested transforms within extension The original code only allowed one transform for each file extension. This change allows multiple, nested transforms for each file extension by keeping a stack instead of just a previous value. --- index.js | 25 ++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/index.js b/index.js index 112692e..02ce092 100644 --- a/index.js +++ b/index.js @@ -1,4 +1,6 @@ + // based on https://github.com/gotwarlost/istanbul/blob/master/lib/hook.js +'use strict'; //catch errors more easily /* Copyright (c) 2012, Yahoo! Inc. All rights reserved. @@ -9,6 +11,7 @@ var fs = require('fs'), Module = require('module'); var originalLoaders = {}; +var nestedTransforms = {}; //allow nested transforms var verify = { extension: function (str) { @@ -40,14 +43,28 @@ function hook(extension, transform, options) { verify.extension(extension); verify.transform(transform); - originalLoaders[extension] = Module._extensions[extension]; + if (!nestedTransforms[extension]) nestedTransforms[extension] = []; + if (!nestedTransforms[extension].length) //only store the first one -DJ + originalLoaders[extension] = Module._extensions[extension]; + nestedTransforms[extension].push(transform); //allow nested transforms -DJ + Module._extensions[extension] = function (module, filename) { if (options.verbose) { console.log('transforming', filename); } var source = fs.readFileSync(filename, 'utf8'); - var ret = transform(source, filename); + var ret = null; //transform(source, filename); + nestedTransforms[extension].every(function(nested) //nesting order performs earlier first, later last + { +// console.log("IN: " + source); + ret = nested(source, filename); +// console.log("OUT: " + ret); +// if (typeof ret !== 'string') return false; //break +// if (!options.toString) return false; //stop here + source = ret + ""; //convert to string and keep going + return true; //continue + }); if (typeof ret === 'string') { module._compile(ret, filename); } else if (options.verbose) { @@ -64,7 +81,9 @@ function unhook(extension) { extension = '.js'; } verify.extension(extension); - Module._extensions[extension] = originalLoaders[extension]; + nestedTransforms[extension].pop(); //assumes no stack underflow + if (!nestedTransforms[extension].length) //restore original only once + Module._extensions[extension] = originalLoaders[extension]; } module.exports = { diff --git a/package.json b/package.json index 185b046..f625f85 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "node-hook", - "version": "0.1.0", + "version": "0.1.1", "description": "Run source transform function on Node require", "main": "index.js", "scripts": { From 33092da522fcec6b41cef5f6018bc16a80deebe7 Mon Sep 17 00:00:00 2001 From: djulien Date: Sat, 12 Sep 2015 15:56:53 -0700 Subject: [PATCH 2/3] add dummy defs in Module not present added dummy defs to avoid run-time errors if Module is not present --- index.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/index.js b/index.js index 02ce092..07520be 100644 --- a/index.js +++ b/index.js @@ -10,6 +10,10 @@ var fs = require('fs'), Module = require('module'); +//dummy definition in case module is not available: +if (!Module) Module = {}; +if (!Module._extensions) { console.log("dummy module def"); Module._extensions = []; } + var originalLoaders = {}; var nestedTransforms = {}; //allow nested transforms From 8ed943aaf84855083d66d5b91ffac057a4d89cf0 Mon Sep 17 00:00:00 2001 From: djulien Date: Wed, 16 Sep 2015 23:02:47 -0700 Subject: [PATCH 3/3] added test case for nested hooks Added a test case for nested hooks. see test/use-case-nested.js --- package.json | 2 +- test/use-case-nested.js | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 test/use-case-nested.js diff --git a/package.json b/package.json index 06ed071..2db9617 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "test": "gt test/jsTest.js --output", - "use-case": "node test/use-case.js" + "use-case": "node test/use-case.js & node test/use-case-nested.js" }, "repository": { "type": "git", diff --git a/test/use-case-nested.js b/test/use-case-nested.js new file mode 100644 index 0000000..6cdc7e7 --- /dev/null +++ b/test/use-case-nested.js @@ -0,0 +1,36 @@ +var hook = require('../index'); +var path = require('path'); + +function outer_hook(source, filename) { + console.log('wedge +10 into filename', path.relative(__dirname, filename)); + source = source.replace(/return a \+ b/, "return a + b + 10"); +// console.log(source); + return source; +} + +function inner_hook(source, filename) { + console.log('wedge *3 into filename', path.relative(__dirname, filename)); + source = source.replace(/return a \+ b/, "return a + b * 3"); +// console.log(source); + return source; +} + +hook.hook('.js', outer_hook); //+ 10 +hook.hook('.js', inner_hook); //* 3 + +var add = require('./dummy'); + +console.assert(typeof add === 'function', 'got a function'); +//NOTE: +//if inner_hook runs after outer_hook, result will be 2 + 3 * 3 + 10 = 21 +//if outer_hook runs after inner_hook, result will be 2 + 3 + 10 * 3 = 35 +//if only outer_hook runs, result will be 2 + 3 + 10 = 15 +//if only inner_hook runs, result will be 2 + 3 * 3 = 11 +//since inner_hook is attached last, it should run after outer_hook +console.log("result: ", add(2, 3)); +console.assert(add(2, 3) === 21, 'computed correct function'); + +console.log('nested test: all seems good'); + +//eof +