Bug:Fix file validation issue
[vnfsdk/refrepo.git] / vnfmarket / src / main / webapp / vnfmarket / node_modules / istanbul / lib / hook.js
1 /*
2  Copyright (c) 2012, Yahoo! Inc.  All rights reserved.
3  Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms.
4  */
5
6 /**
7  * provides a mechanism to transform code in the scope of `require` or `vm.createScript`.
8  * This mechanism is general and relies on a user-supplied `matcher` function that determines when transformations should be
9  * performed and a user-supplied `transformer` function that performs the actual transform.
10  * Instrumenting code for coverage is one specific example of useful hooking.
11  *
12  * Note that both the `matcher` and `transformer` must execute synchronously.
13  *
14  * For the common case of matching filesystem paths based on inclusion/ exclusion patterns, use the `matcherFor`
15  * function in the istanbul API to get a matcher.
16  *
17  * It is up to the transformer to perform processing with side-effects, such as caching, storing the original
18  * source code to disk in case of dynamically generated scripts etc. The `Store` class can help you with this.
19  *
20  * Usage
21  * -----
22  *
23  *      var hook = require('istanbul').hook,
24  *          myMatcher = function (file) { return file.match(/foo/); },
25  *          myTransformer = function (code, file) { return 'console.log("' + file + '");' + code; };
26  *
27  *      hook.hookRequire(myMatcher, myTransformer);
28  *
29  *      var foo = require('foo'); //will now print foo's module path to console
30  *
31  * @class Hook
32  * @module main
33  */
34 var path = require('path'),
35     fs = require('fs'),
36     Module = require('module'),
37     vm = require('vm'),
38     originalLoaders = {},
39     originalCreateScript = vm.createScript,
40     originalRunInThisContext = vm.runInThisContext;
41
42 function transformFn(matcher, transformer, verbose) {
43
44     return function (code, filename) {
45         var shouldHook = typeof filename === 'string' && matcher(path.resolve(filename)),
46             transformed,
47             changed = false;
48
49         if (shouldHook) {
50             if (verbose) {
51                 console.error('Module load hook: transform [' + filename + ']');
52             }
53             try {
54                 transformed = transformer(code, filename);
55                 changed = true;
56             } catch (ex) {
57                 console.error('Transformation error; return original code');
58                 console.error(ex);
59                 transformed = code;
60             }
61         } else {
62             transformed = code;
63         }
64         return { code: transformed, changed: changed };
65     };
66 }
67
68 function unloadRequireCache(matcher) {
69     if (matcher && typeof require !== 'undefined' && require && require.cache) {
70         Object.keys(require.cache).forEach(function (filename) {
71             if (matcher(filename)) {
72                 delete require.cache[filename];
73             }
74         });
75     }
76 }
77 /**
78  * hooks `require` to return transformed code to the node module loader.
79  * Exceptions in the transform result in the original code being used instead.
80  * @method hookRequire
81  * @static
82  * @param matcher {Function(filePath)} a function that is called with the absolute path to the file being
83  *  `require`-d. Should return a truthy value when transformations need to be applied to the code, a falsy value otherwise
84  * @param transformer {Function(code, filePath)} a function called with the original code and the associated path of the file
85  *  from where the code was loaded. Should return the transformed code.
86  * @param options {Object} options Optional.
87  * @param {Boolean} [options.verbose] write a line to standard error every time the transformer is called
88  * @param {Function} [options.postLoadHook] a function that is called with the name of the file being
89  *  required. This is called after the require is processed irrespective of whether it was transformed.
90  */
91 function hookRequire(matcher, transformer, options) {
92     options = options || {};
93     var extensions,
94         fn = transformFn(matcher, transformer, options.verbose),
95         postLoadHook = options.postLoadHook &&
96             typeof options.postLoadHook === 'function' ? options.postLoadHook : null;
97
98     extensions = options.extensions || ['.js'];
99
100     extensions.forEach(function(ext){
101         if (!(ext in originalLoaders)) { 
102             originalLoaders[ext] = Module._extensions[ext] || Module._extensions['.js'];
103         } 
104         Module._extensions[ext] = function (module, filename) {
105             var ret = fn(fs.readFileSync(filename, 'utf8'), filename);
106             if (ret.changed) {
107                 module._compile(ret.code, filename);
108             } else {
109                 originalLoaders[ext](module, filename);
110             }
111             if (postLoadHook) {
112                 postLoadHook(filename);
113             }
114         };
115     });
116 }
117 /**
118  * unhook `require` to restore it to its original state.
119  * @method unhookRequire
120  * @static
121  */
122 function unhookRequire() {
123     Object.keys(originalLoaders).forEach(function(ext) {
124         Module._extensions[ext] = originalLoaders[ext];
125     });
126 }
127 /**
128  * hooks `vm.createScript` to return transformed code out of which a `Script` object will be created.
129  * Exceptions in the transform result in the original code being used instead.
130  * @method hookCreateScript
131  * @static
132  * @param matcher {Function(filePath)} a function that is called with the filename passed to `vm.createScript`
133  *  Should return a truthy value when transformations need to be applied to the code, a falsy value otherwise
134  * @param transformer {Function(code, filePath)} a function called with the original code and the filename passed to
135  *  `vm.createScript`. Should return the transformed code.
136  * @param options {Object} options Optional.
137  * @param {Boolean} [options.verbose] write a line to standard error every time the transformer is called
138  */
139 function hookCreateScript(matcher, transformer, opts) {
140     opts = opts || {};
141     var fn = transformFn(matcher, transformer, opts.verbose);
142     vm.createScript = function (code, file) {
143         var ret = fn(code, file);
144         return originalCreateScript(ret.code, file);
145     };
146 }
147
148 /**
149  * unhooks vm.createScript, restoring it to its original state.
150  * @method unhookCreateScript
151  * @static
152  */
153 function unhookCreateScript() {
154     vm.createScript = originalCreateScript;
155 }
156
157
158 /**
159  * hooks `vm.runInThisContext` to return transformed code.
160  * @method hookRunInThisContext
161  * @static
162  * @param matcher {Function(filePath)} a function that is called with the filename passed to `vm.createScript`
163  *  Should return a truthy value when transformations need to be applied to the code, a falsy value otherwise
164  * @param transformer {Function(code, filePath)} a function called with the original code and the filename passed to
165  *  `vm.createScript`. Should return the transformed code.
166  * @param options {Object} options Optional.
167  * @param {Boolean} [options.verbose] write a line to standard error every time the transformer is called
168  */
169 function hookRunInThisContext(matcher, transformer, opts) {
170     opts = opts || {};
171     var fn = transformFn(matcher, transformer, opts.verbose);
172     vm.runInThisContext = function (code, file) {
173         var ret = fn(code, file);
174         return originalRunInThisContext(ret.code, file);
175     };
176 }
177
178 /**
179  * unhooks vm.runInThisContext, restoring it to its original state.
180  * @method unhookRunInThisContext
181  * @static
182  */
183 function unhookRunInThisContext() {
184     vm.runInThisContext = originalRunInThisContext;
185 }
186
187
188 module.exports = {
189     hookRequire: hookRequire,
190     unhookRequire: unhookRequire,
191     hookCreateScript: hookCreateScript,
192     unhookCreateScript: unhookCreateScript,
193     hookRunInThisContext : hookRunInThisContext,
194     unhookRunInThisContext : unhookRunInThisContext,
195     unloadRequireCache: unloadRequireCache
196 };
197
198