| 'use strict'; |
| const js = require('default-require-extensions/js'); |
| |
| module.exports = appendTransform; |
| |
| let count = 0; |
| |
| function appendTransform(transform, ext, extensions) { |
| // Generate a unique key for this transform |
| var key = __dirname + count; // eslint-disable-line |
| count++; |
| ext = ext || '.js'; |
| extensions = extensions || require.extensions; |
| |
| let forwardGet; |
| let forwardSet; |
| |
| const descriptor = Object.getOwnPropertyDescriptor(extensions, ext) || {value: js, configurable: true}; |
| |
| if ( |
| ((descriptor.get || descriptor.set) && !(descriptor.get && descriptor.set)) || |
| !descriptor.configurable |
| ) { |
| throw new Error('Somebody did bad things to require.extensions["' + ext + '"]'); |
| } |
| |
| if (descriptor.get) { |
| // Wrap a previous append-transform install and pass through to the getter/setter pair it created |
| forwardGet = function () { |
| return descriptor.get(); |
| }; |
| forwardSet = function (val) { |
| descriptor.set(val); |
| return forwardGet(); |
| }; |
| } else { |
| forwardGet = function () { |
| return descriptor.value; |
| }; |
| forwardSet = function (val) { |
| descriptor.value = val; |
| return val; |
| }; |
| } |
| |
| function wrapCustomHook(hook) { |
| return function (module, filename) { |
| // We wrap every added extension, but we only apply the transform to the one on top of the stack |
| if (!module[key]) { |
| module[key] = true; |
| |
| const originalCompile = module._compile; |
| |
| // eslint-disable-next-line func-name-matching func-names |
| module._compile = function replacementCompile(code, filename) { |
| module._compile = originalCompile; |
| code = transform(code, filename); |
| module._compile(code, filename); |
| }; |
| } |
| |
| hook(module, filename); |
| }; |
| } |
| |
| // Wrap the original |
| forwardSet(wrapCustomHook(forwardGet())); |
| |
| const hooks = [forwardGet()]; |
| |
| function setCurrentHook(hook) { |
| const restoreIndex = hooks.indexOf(hook); |
| |
| if (restoreIndex === -1) { |
| hooks.push(forwardSet(wrapCustomHook(hook))); |
| } else { |
| // We have already scene this hook, and it is being reverted (proxyquire, etc) - don't wrap again. |
| hooks.splice(restoreIndex + 1, hooks.length); |
| forwardSet(hook); |
| } |
| } |
| |
| Object.defineProperty(extensions, ext, { |
| configurable: true, |
| enumerable: true, |
| get: forwardGet, |
| set: setCurrentHook |
| }); |
| } |