pax_global_header00006660000000000000000000000064131042357140014512gustar00rootroot0000000000000052 comment=80489389e74c6877c49a916bf87826bf2b4ba1c8 stealthy-require-1.1.1/000077500000000000000000000000001310423571400150215ustar00rootroot00000000000000stealthy-require-1.1.1/.editorconfig000066400000000000000000000006601310423571400175000ustar00rootroot00000000000000# EditorConfig is awesome: http://EditorConfig.org root = true [*] charset = utf-8 end_of_line = lf [*.js] indent_style = space indent_size = 4 trim_trailing_whitespace = true insert_final_newline = true [*.{json,xml}] indent_style = space indent_size = 2 trim_trailing_whitespace = true insert_final_newline = true [*.{md,txt}] indent_style = space indent_size = 4 trim_trailing_whitespace = false insert_final_newline = falsestealthy-require-1.1.1/.eslintrc.json000066400000000000000000000103531310423571400176170ustar00rootroot00000000000000{ "root": true, "parser": "espree", "parserOptions": { "ecmaVersion": 5, "sourceType": "script", "ecmaFeatures": {} }, "plugins": [], "env": { "node": true }, "globals": {}, "rules": { // Possible Errors (fully reviewed 2016-07-05) "no-cond-assign": 2, "no-console": 0, "no-constant-condition": 2, "no-control-regex": 2, "no-debugger": 2, "no-dupe-args": 2, "no-dupe-keys": 2, "no-duplicate-case": 2, "no-empty": [2, { "allowEmptyCatch": false }], "no-empty-character-class": 2, "no-ex-assign": 2, "no-extra-boolean-cast": 2, "no-extra-parens": [2, "all"], "no-extra-semi": 2, "no-func-assign": 2, "no-inner-declarations": [2, "functions"], "no-invalid-regexp": 2, "no-irregular-whitespace": [2, { "skipComments": false }], "no-negated-in-lhs": 2, "no-obj-calls": 2, "no-prototype-builtins": 2, "no-regex-spaces": 2, "no-sparse-arrays": 2, "no-unexpected-multiline": 2, "no-unreachable": 2, "no-unsafe-finally": 2, "use-isnan": 2, "valid-jsdoc": 0, "valid-typeof": 2, // Best Practices "accessor-pairs": 2, "curly": [2, "multi-line"], "dot-location": [2, "property"], "eqeqeq": 2, "no-caller": 2, "no-empty-pattern": 0, // for ES6 destructuring "no-eval": 2, "no-extend-native": 2, "no-extra-bind": 2, "no-fallthrough": 2, "no-floating-decimal": 2, "no-implied-eval": 2, "no-iterator": 2, "no-labels": 2, "no-lone-blocks": 2, "no-magic-numbers": 0, "no-multi-spaces": 2, "no-multi-str": 2, "no-native-reassign": 2, "no-new": 2, "no-new-func": 2, "no-new-wrappers": 2, "no-octal": 2, "no-octal-escape": 2, "no-proto": 2, "no-redeclare": 2, "no-return-assign": [2, "except-parens"], "no-self-assign": 2, "no-self-compare": 2, "no-sequences": 2, "no-throw-literal": 2, "no-unmodified-loop-condition": 2, "no-useless-call": 2, "no-useless-escape": 2, "no-with": 2, "wrap-iife": [2, "inside"], "yoda": 2, // Strict Mode (fully reviewed 2016-07-05) "strict": [2, "safe"], // Variables (fully reviewed 2016-07-05) "init-declarations": [2, "always"], "no-catch-shadow": 0, "no-delete-var": 2, "no-label-var": 2, "no-restricted-globals": 0, "no-shadow": [2, { "builtinGlobals": false, "hoist": "all", "allow": [] }], "no-shadow-restricted-names": 2, "no-undef": [2, { "typeof": true }], "no-undef-init": 2, "no-undefined": 0, "no-unused-vars": [2, { "vars": "local", "args": "none", "caughtErrors": "none" }], "no-use-before-define": [2, { "functions": false, "classes": true }], // Node.js and CommonJS (fully reviewed 2016-07-05) "callback-return": 0, "global-require": 0, "handle-callback-err": [2, "^(err|error)$" ], "no-mixed-requires": 0, "no-new-require": 2, "no-path-concat": 2, "no-process-env": 2, "no-process-exit": 2, "no-restricted-modules": 0, "no-sync": 2, // Stylistic Issues "block-spacing": 2, "brace-style": [2, "1tbs", { "allowSingleLine": true }], "camelcase": [2, { "properties": "never" }], "comma-dangle": [2, "never"], "comma-spacing": 2, "comma-style": 2, "eol-last": 2, "indent": [2, 4, { "SwitchCase": 1 }], "jsx-quotes": 0, "key-spacing": 2, "keyword-spacing": 2, "new-cap": 0, "new-parens": 2, "no-array-constructor": 2, "no-mixed-spaces-and-tabs": 2, "no-multiple-empty-lines": [2, { "max": 2, "maxBOF": 0, "maxEOF": 1 }], "no-new-object": 2, "no-plusplus": [2, { "allowForLoopAfterthoughts": false }], "no-spaced-func": 2, "no-trailing-spaces": 2, "no-unneeded-ternary": [2, { "defaultAssignment": false }], "no-whitespace-before-property": 2, "one-var": 0, "operator-linebreak": [2, "after", { "overrides": { "?": "before", ":": "before" } }], "padded-blocks": 0, "quotes": [2, "single", "avoid-escape"], "semi": [2, "always"], "semi-spacing": 2, "space-before-blocks": 2, "space-before-function-paren": [2, {"anonymous": "always", "named": "never"}], "space-in-parens": 0, "space-infix-ops": 0, "space-unary-ops": 2, "spaced-comment": 0 } } stealthy-require-1.1.1/.gitignore000066400000000000000000000001111310423571400170020ustar00rootroot00000000000000/.idea/ /coverage/ /node_modules/ /test/results/ .DS_Store npm-debug.logstealthy-require-1.1.1/.npmignore000066400000000000000000000002041310423571400170140ustar00rootroot00000000000000/.idea/ /coverage/ /test/ /.editorconfig /.eslintrc.json /.gitignore /.publishrc /.travis.yml /gulpfile.js .DS_Store npm-debug.logstealthy-require-1.1.1/.publishrc000066400000000000000000000004331310423571400170150ustar00rootroot00000000000000{ "validations": { "vulnerableDependencies": true, "uncommittedChanges": true, "untrackedFiles": true, "sensitiveData": true, "branch": "master", "gitTag": true }, "confirm": true, "publishTag": "latest", "prePublishScript": "npm run test-publish" }stealthy-require-1.1.1/.travis.yml000066400000000000000000000003431310423571400171320ustar00rootroot00000000000000language: node_js node_js: - "0.10" - "0.12" - "iojs" - "4" - "6" - "7" addons: apt: sources: - ubuntu-toolchain-r-test packages: - gcc-4.8 - g++-4.8 env: - TRAVIS=travis CXX=g++-4.8stealthy-require-1.1.1/LICENSE000066400000000000000000000013741310423571400160330ustar00rootroot00000000000000ISC License Copyright (c) 2017, Nicolai Kamenzky and contributors Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.stealthy-require-1.1.1/README.md000066400000000000000000000173621310423571400163110ustar00rootroot00000000000000# Stealthy-Require [![Build Status](https://img.shields.io/travis/analog-nico/stealthy-require/master.svg?style=flat-square)](https://travis-ci.org/analog-nico/stealthy-require) [![Coverage Status](https://img.shields.io/coveralls/analog-nico/stealthy-require.svg?style=flat-square)](https://coveralls.io/r/analog-nico/stealthy-require) [![Dependency Status](https://img.shields.io/david/analog-nico/stealthy-require.svg?style=flat-square)](https://david-dm.org/analog-nico/stealthy-require) This is probably the closest you can currently get to require something in node.js with completely bypassing the require cache. `stealthy-require` works like this: 1. It clears the require cache. 2. It calls a callback in which you require your module(s) without the cache kicking in. 3. It clears the cache again and restores its old state. The restrictions are: - [Native modules cannot be required twice.](https://github.com/nodejs/node/issues/5016) Thus this module bypasses the require cache only for non-native (e.g. JS) modules. - The require cache is only bypassed for all operations that happen synchronously when a module is required. If a module lazy loads another module at a later time that require call will not bypass the cache anymore. This means you should have a close look at all internal require calls before you decide to use this library. ## Installation [![NPM Stats](https://nodei.co/npm/stealthy-require.png?downloads=true)](https://npmjs.org/package/stealthy-require) This is a module for node.js and is installed via npm: ``` bash npm install stealthy-require --save ``` ## Usage Let's say you want to bypass the require cache for this require call: ``` js var request = require('request'); ``` With `stealthy-require` you can do that like this: ``` js var stealthyRequire = require('stealthy-require'); var requestFresh = stealthyRequire(require.cache, function () { return require('request'); }); ``` The require cache is bypassed for the module you require (i.e. `request`) as well as all modules the module requires (i.e. `http` and many more). Sometimes the require cache shall not be bypassed for specific modules. E.g. `request` is required but `tough-cookie` – on which `request` depends on – shall be required using the regular cache. For that you can pass two extra arguments to `stealthyRequire(...)`: - A callback that requires the modules that shall be required without bypassing the cache - The `module` variable ``` js var stealthyRequire = require('stealthy-require'); var requestFresh = stealthyRequire(require.cache, function () { return require('request'); }, function () { require('tough-cookie'); // No return needed // You can require multiple modules here }, module); ``` ## Usage with Module Bundlers - [Webpack](https://webpack.github.io) works out-of-the-box like described in the [Usage section](#usage) above. - [Browserify](http://browserify.org) does not expose `require.cache`. However, as of `browserify@13.0.1` the cache is passed as the 6th argument to CommonJS modules. Thus you can pass this argument instead: ``` js // Tweak for Browserify - using arguments[5] instead of require.cache var requestFresh = stealthyRequire(arguments[5], function () { return require('request'); }); ``` ## Preventing a Memory Leak When Repeatedly Requiring Fresh Module Instances in Node.js If you are using `stealthy-require` in node.js and repeatedly require fresh module instances the `module.children` array will hold all module instances which prevents unneeded instances to be garbage collected. Assume your code calls `doSomething()` repeatedly. ``` js var stealthyRequire = require('stealthy-require'); function doSomething() { var freshInstance = stealthyRequire(require.cache, function () { return require('some-module'); }); return freshInstance.calc(); } ``` After `doSomething()` returns `freshInstance` is not used anymore but won’t be garbage collected because `module.children` still holds a reference. The solution is to truncate `module.children` accordingly: ``` js var stealthyRequire = require('stealthy-require'); function doSomething() { var initialChildren = module.children.slice(); // Creates a shallow copy of the array var freshInstance = stealthyRequire(require.cache, function () { return require('some-module'); }); module.children = initialChildren; return freshInstance.calc(); } ``` The `slice` operation removes all new `module.children` entries created during the `stealthyRequire(...)` call and thus `freshInstance` gets garbage collected after `doSomething()` returns. ## Technical Walkthrough ``` js // 1. Load stealthy-require var stealthyRequire = require('stealthy-require'); // This does nothing but loading the code. // It has no side-effects like patching the module loader or anything. // Any regular require works as always. var request1 = require('request'); // 2. Call stealthyRequire with passing the require cache and a callback. var requestFresh = stealthyRequire(require.cache, function () { // 2a. Before this callback gets called the require cache is cleared. // 2b. Any require taking place here takes place on a clean require cache. // Since the require call is part of the user's code it also works with module bundlers. return require('request'); // Anything returned here will be returned by stealthyRequire(...). // 2c. After this callback gets called the require cache is // - cleared again and // - restored to its old state before step 2. }); // Any regular require again works as always. // In this case require returns the cached request module instance. var request2 = require('request'); // And voilà: request1 === request2 // -> true request1 === requestFresh // -> false ``` ## Contributing To set up your development environment for `stealthy-require`: 1. Clone this repo to your desktop, 2. in the shell `cd` to the main folder, 3. hit `npm install`, 4. hit `npm install gulp -g` if you haven't installed gulp globally yet, and 5. run `gulp dev`. (Or run `node ./node_modules/.bin/gulp dev` if you don't want to install gulp globally.) `gulp dev` watches all source files and if you save some changes it will lint the code and execute all tests. The test coverage report can be viewed from `./coverage/lcov-report/index.html`. If you want to debug a test you should use `gulp test-without-coverage` to run all tests without obscuring the code by the test coverage instrumentation. ## Change History - v1.1.1 (2017-05-08) - Fix that stops `undefined` entries from appearing in `require.cache` *(Thanks to @jasperjn from reporting this in [issue #4](https://github.com/analog-nico/stealthy-require/issues/4))* - v1.1.0 (2017-04-25) - Added ability to disable bypassing the cache for certain modules *(Thanks to @novemberborn for suggesting this in [issue #3](https://github.com/analog-nico/stealthy-require/issues/3))* - Added section in README about a [potential memory leak](#preventing-a-memory-leak-when-repeatedly-requiring-fresh-module-instances-in-nodejs) *(Thanks to @Flarna and @novemberborn for bringing that up in [issue #2](https://github.com/analog-nico/stealthy-require/issues/2))* - Performance optimizations *(Thanks to @jcready for [pull request #1](https://github.com/analog-nico/stealthy-require/pull/1))* - v1.0.0 (2016-07-18) - **Breaking Change:** API completely changed. Please read the [Usage section](#usage) again. - Redesigned library to support module bundlers like [Webpack](https://webpack.github.io) and [Browserify](http://browserify.org) - v0.1.0 (2016-05-26) - Initial version ## License (ISC) In case you never heard about the [ISC license](http://en.wikipedia.org/wiki/ISC_license) it is functionally equivalent to the MIT license. See the [LICENSE file](LICENSE) for details. stealthy-require-1.1.1/gulpfile.js000066400000000000000000000056771310423571400172050ustar00rootroot00000000000000'use strict'; var gulp = require('gulp'); var runSequence = require('run-sequence'); var istanbul = require('gulp-istanbul'); var mocha = require('gulp-mocha'); var chalk = require('chalk'); var rimraf = require('rimraf'); var coveralls = require('gulp-coveralls'); var eslint = require('gulp-eslint'); var mkdirp = require('mkdirp'); var chai = require('chai'); global.expect = chai.expect; var paths = { libJsFiles: './lib/**/*.js', specFiles: './test/spec/**/*.js', fixtureFiles: './test/fixtures/**/*.js', gulpfile: './gulpfile.js', eslintrc: './.eslintrc.json' }; gulp.task('dev', ['watch', 'validate']); gulp.task('watch', function () { gulp.watch([ paths.libJsFiles, paths.specFiles, paths.fixtureFiles, paths.gulpfile ], [ 'validate' ]); gulp.watch([ paths.eslintrc ], [ 'lint' ]); }); gulp.task('validate', function (done) { runSequence('lint', 'test', done); }); gulp.task('lint', function () { return gulp.src([ paths.libJsFiles, paths.gulpfile, paths.specFiles, paths.fixtureFiles, paths.gulpfile ]) .pipe(eslint()) .pipe(eslint.format()) .pipe(eslint.failAfterError()); }); gulp.task('test', ['clean'], function (done) { var coverageVariable = '$$cov_' + new Date().getTime() + '$$'; gulp.src(paths.libJsFiles) .pipe(istanbul({ coverageVariable: coverageVariable })) .pipe(istanbul.hookRequire()) .on('finish', function () { gulp.src(paths.specFiles) .pipe(mocha()) .on('error', function (err) { console.error(String(err)); console.error(chalk.bold.bgRed(' TESTS FAILED ')); done(new Error(' TESTS FAILED ')); }) .pipe(istanbul.writeReports({ reporters: ['lcov'], coverageVariable: coverageVariable })) .on('end', done); }); }); gulp.task('test-without-coverage', function () { return gulp.src(paths.specFiles) .pipe(mocha()) .on('error', function () { console.log(chalk.bold.bgRed(' TESTS FAILED ')); }); }); gulp.task('clean', ['clean-coverage', 'clean-results']); gulp.task('clean-coverage', function (done) { rimraf('./coverage', done); }); gulp.task('clean-results', function (done) { rimraf('./test/results', function (err) { if (err) { return done(err); } mkdirp('./test/results', done); }); }); gulp.task('ci', function (done) { runSequence('validate', 'coveralls', 'test-without-coverage', done); }); gulp.task('ci-no-cov', function (done) { runSequence('validate', 'test-without-coverage', done); }); gulp.task('coveralls', function () { return gulp.src('coverage/**/lcov.info') .pipe(coveralls()); }); stealthy-require-1.1.1/lib/000077500000000000000000000000001310423571400155675ustar00rootroot00000000000000stealthy-require-1.1.1/lib/index.js000066400000000000000000000045361310423571400172440ustar00rootroot00000000000000'use strict'; var isNative = /\.node$/; function forEach(obj, callback) { for ( var key in obj ) { if (!Object.prototype.hasOwnProperty.call(obj, key)) { continue; } callback(key); } } function assign(target, source) { forEach(source, function (key) { target[key] = source[key]; }); return target; } function clearCache(requireCache) { forEach(requireCache, function (resolvedPath) { if (!isNative.test(resolvedPath)) { delete requireCache[resolvedPath]; } }); } module.exports = function (requireCache, callback, callbackForModulesToKeep, module) { var originalCache = assign({}, requireCache); clearCache(requireCache); if (callbackForModulesToKeep) { var originalModuleChildren = module.children ? module.children.slice() : false; // Creates a shallow copy of module.children callbackForModulesToKeep(); // Lists the cache entries made by callbackForModulesToKeep() var modulesToKeep = []; forEach(requireCache, function (key) { modulesToKeep.push(key); }); // Discards the modules required in callbackForModulesToKeep() clearCache(requireCache); if (module.children) { // Only true for node.js module.children = originalModuleChildren; // Removes last references to modules required in callbackForModulesToKeep() -> No memory leak } // Takes the cache entries of the original cache in case the modules where required before for ( var i = 0; i < modulesToKeep.length; i+=1 ) { if (originalCache[modulesToKeep[i]]) { requireCache[modulesToKeep[i]] = originalCache[modulesToKeep[i]]; } } } var freshModule = callback(); var stealthCache = callbackForModulesToKeep ? assign({}, requireCache) : false; clearCache(requireCache); if (callbackForModulesToKeep) { // In case modules to keep were required inside the stealthy require for the first time, copy them to the restored cache for ( var k = 0; k < modulesToKeep.length; k+=1 ) { if (stealthCache[modulesToKeep[k]]) { requireCache[modulesToKeep[k]] = stealthCache[modulesToKeep[k]]; } } } assign(requireCache, originalCache); return freshModule; }; stealthy-require-1.1.1/package.json000066400000000000000000000024111310423571400173050ustar00rootroot00000000000000{ "name": "stealthy-require", "version": "1.1.1", "description": "The closest you can get to require something with bypassing the require cache", "keywords": [ "require", "bypass", "no", "cache", "fresh" ], "main": "./lib/index.js", "scripts": { "test": "./node_modules/.bin/gulp ci", "test-publish": "./node_modules/.bin/gulp ci-no-cov", "publish-please": "publish-please", "prepublish": "publish-please guard" }, "repository": { "type": "git", "url": "git+https://github.com/analog-nico/stealthy-require.git" }, "author": "Nicolai Kamenzky (https://github.com/analog-nico)", "license": "ISC", "bugs": { "url": "https://github.com/analog-nico/stealthy-require/issues" }, "homepage": "https://github.com/analog-nico/stealthy-require#readme", "engines": { "node": ">=0.10.0" }, "dependencies": {}, "devDependencies": { "bcrypt": "~1.0.2", "browserify": "~14.3.0", "chai": "~3.5.0", "chalk": "~1.1.3", "gulp": "~3.9.1", "gulp-coveralls": "~0.1.4", "gulp-eslint": "~2.1.0", "gulp-istanbul": "~1.1.1", "gulp-mocha": "~3.0.1", "mkdirp": "~0.5.1", "publish-please": "~2.3.1", "rimraf": "~2.6.1", "run-sequence": "~1.2.2", "webpack": "~1.15.0" } } stealthy-require-1.1.1/test/000077500000000000000000000000001310423571400160005ustar00rootroot00000000000000stealthy-require-1.1.1/test/.eslintrc.json000066400000000000000000000002471310423571400205770ustar00rootroot00000000000000{ "env": { "mocha": true }, "globals": { "expect": true }, "rules": { // Node.js and CommonJS "no-process-env": 0, "no-sync": 0 } } stealthy-require-1.1.1/test/fixtures/000077500000000000000000000000001310423571400176515ustar00rootroot00000000000000stealthy-require-1.1.1/test/fixtures/async-deps.js000066400000000000000000000002701310423571400222540ustar00rootroot00000000000000'use strict'; module.exports = { me: Math.random(), sync_dep: require('./no-deps.js') }; setTimeout(function () { module.exports.async_dep = require('./no-deps.js'); }); stealthy-require-1.1.1/test/fixtures/deep-sync-deps.js000066400000000000000000000001371310423571400230300ustar00rootroot00000000000000'use strict'; module.exports = { me: Math.random(), dep: require('./sync-deps.js') }; stealthy-require-1.1.1/test/fixtures/native-deps.js000066400000000000000000000001361310423571400224260ustar00rootroot00000000000000'use strict'; module.exports = { me: Math.random(), native_dep: require('bcrypt') }; stealthy-require-1.1.1/test/fixtures/no-deps.js000066400000000000000000000000571310423571400215560ustar00rootroot00000000000000'use strict'; module.exports = Math.random(); stealthy-require-1.1.1/test/fixtures/stealthy-require-and-keep-browserify.js000066400000000000000000000006741310423571400274000ustar00rootroot00000000000000'use strict'; var stealthyRequire = require('../../lib/index.js'); var req1 = require('../fixtures/sync-deps.js'); var req2 = stealthyRequire(arguments[5], function () { return require('./deep-sync-deps.js'); }, function () { require('../fixtures/sync-deps.js'); }, module); var req3 = require('../fixtures/sync-deps.js'); console.log(JSON.stringify(req1)); console.log(JSON.stringify(req2.dep)); console.log(JSON.stringify(req3)); stealthy-require-1.1.1/test/fixtures/stealthy-require-and-keep.js000066400000000000000000000006751310423571400252100ustar00rootroot00000000000000'use strict'; var stealthyRequire = require('../../lib/index.js'); var req1 = require('../fixtures/sync-deps.js'); var req2 = stealthyRequire(require.cache, function () { return require('./deep-sync-deps.js'); }, function () { require('../fixtures/sync-deps.js'); }, module); var req3 = require('../fixtures/sync-deps.js'); console.log(JSON.stringify(req1)); console.log(JSON.stringify(req2.dep)); console.log(JSON.stringify(req3)); stealthy-require-1.1.1/test/fixtures/stealthy-require-browserify.js000066400000000000000000000005611310423571400257110ustar00rootroot00000000000000'use strict'; var stealthyRequire = require('../../lib/index.js'); var req1 = require('../fixtures/sync-deps.js'); var req2 = stealthyRequire(arguments[5], function () { return require('./sync-deps.js'); }); var req3 = require('../fixtures/sync-deps.js'); console.log(JSON.stringify(req1)); console.log(JSON.stringify(req2)); console.log(JSON.stringify(req3)); stealthy-require-1.1.1/test/fixtures/stealthy-require.js000066400000000000000000000005621310423571400235210ustar00rootroot00000000000000'use strict'; var stealthyRequire = require('../../lib/index.js'); var req1 = require('../fixtures/sync-deps.js'); var req2 = stealthyRequire(require.cache, function () { return require('./sync-deps.js'); }); var req3 = require('../fixtures/sync-deps.js'); console.log(JSON.stringify(req1)); console.log(JSON.stringify(req2)); console.log(JSON.stringify(req3)); stealthy-require-1.1.1/test/fixtures/sync-deps.js000066400000000000000000000001351310423571400221130ustar00rootroot00000000000000'use strict'; module.exports = { me: Math.random(), dep: require('./no-deps.js') }; stealthy-require-1.1.1/test/spec/000077500000000000000000000000001310423571400167325ustar00rootroot00000000000000stealthy-require-1.1.1/test/spec/browserify.js000066400000000000000000000056021310423571400214660ustar00rootroot00000000000000'use strict'; var browserify = require('browserify'); var fs = require('fs'); var path = require('path'); describe('When using Browserify, Stealthy-Require', function () { it('should allow Browserify to replace the require call (not working for require.cache)', function (done) { var b = browserify(); b.add(path.join(__dirname, '../fixtures/stealthy-require.js')); b.bundle() .pipe(fs.createWriteStream(path.join(__dirname, '../results/browserify.bundle.js'))) .on('finish', function () { var log = []; var origConsoleLog = console.log; console.log = function (text) { log.push(text); }; require('../results/browserify.bundle.js'); console.log = origConsoleLog; expect(log.length).to.eql(3); expect(log[0]).to.eql(log[2]); // expect(log[0]).to.not.eql(log[1]); // Browserify doesn't provide require.cache expect(log[0]).to.eql(log[1]); done(); }); }); it('should allow Browserify to replace the require call (working for 6th argument as cache)', function (done) { var b = browserify(); b.add(path.join(__dirname, '../fixtures/stealthy-require-browserify.js')); b.bundle() .pipe(fs.createWriteStream(path.join(__dirname, '../results/browserify.custom.bundle.js'))) .on('finish', function () { var log = []; var origConsoleLog = console.log; console.log = function (text) { log.push(text); }; require('../results/browserify.custom.bundle.js'); console.log = origConsoleLog; expect(log.length).to.eql(3); expect(log[0]).to.eql(log[2]); expect(log[0]).to.not.eql(log[1]); done(); }); }); it('should allow Browserify to replace the require call for keeping modules (working for 6th argument as cache)', function (done) { var b = browserify(); b.add(path.join(__dirname, '../fixtures/stealthy-require-and-keep-browserify.js')); b.bundle() .pipe(fs.createWriteStream(path.join(__dirname, '../results/browserify.keep.custom.bundle.js'))) .on('finish', function () { var log = []; var origConsoleLog = console.log; console.log = function (text) { log.push(text); }; require('../results/browserify.keep.custom.bundle.js'); console.log = origConsoleLog; expect(log.length).to.eql(3); expect(log[0]).to.eql(log[2]); expect(log[0]).to.eql(log[1]); done(); }); }); }); stealthy-require-1.1.1/test/spec/native.js000066400000000000000000000012421310423571400205550ustar00rootroot00000000000000'use strict'; var stealthyRequire = require('../../'); describe('When native modules are involved, Stealthy-Require', function () { it('should require a module with native deps', function () { var req1 = require('../fixtures/native-deps.js'); var req2 = null; expect(function () { req2 = stealthyRequire(require.cache, function () { return require('../fixtures/native-deps.js'); }); }).not.to.throw(/* Error: Module did not self-register. */); var req3 = require('../fixtures/native-deps.js'); expect(req1).to.eql(req3); expect(req1).to.not.eql(req2); }); }); stealthy-require-1.1.1/test/spec/non-native.js000066400000000000000000000112251310423571400213470ustar00rootroot00000000000000'use strict'; var stealthyRequire = require('../../'); describe('When only non-native modules are involved, Stealthy-Require', function () { it('should require a module without deps', function () { var req1 = require('../fixtures/no-deps.js'); var req2 = stealthyRequire(require.cache, function () { return require('../fixtures/no-deps.js'); }); var req3 = require('../fixtures/no-deps.js'); expect(req1).to.eql(req3); expect(req1).to.not.eql(req2); }); it('should require a module with sync deps', function () { var req1 = require('../fixtures/sync-deps.js'); var req2 = stealthyRequire(require.cache, function () { return require('../fixtures/sync-deps.js'); }); var req3 = require('../fixtures/sync-deps.js'); expect(req1).to.eql(req3); expect(req1).to.not.eql(req2); }); it('should require a module with the exception of async deps', function () { var req1 = require('../fixtures/async-deps.js'); var req2 = stealthyRequire(require.cache, function () { return require('../fixtures/async-deps.js'); }); var req3 = require('../fixtures/async-deps.js'); expect(req1).to.eql(req3); expect(req1.me).to.not.eql(req2.me); expect(req1.sync_dep).to.not.eql(req2.sync_dep); expect(req1.async_dep).to.eql(req2.async_dep); // <-- exception }); it('should require a module while keeping a dependency that was required before', function () { var req1 = require('../fixtures/sync-deps.js'); var lenChildrenBeforeReq2 = module.children.length; var req2 = stealthyRequire(require.cache, function () { return require('../fixtures/deep-sync-deps.js'); }, function () { require('../fixtures/sync-deps.js'); }, module); var lenChildrenAfterReq2 = module.children.length; var req3 = require('../fixtures/sync-deps.js'); expect(req1).to.eql(req3); expect(req1).to.eql(req2.dep); expect(req1.dep).to.eql(req2.dep.dep); expect(lenChildrenAfterReq2).to.eql(lenChildrenBeforeReq2+1); }); it('should require a module while keeping a dependency that will be required afterwards', function () { var testReq1 = require('../fixtures/sync-deps.js'); var testReq2 = require('../fixtures/no-deps.js'); delete require.cache[require.resolve('../fixtures/sync-deps.js')]; delete require.cache[require.resolve('../fixtures/no-deps.js')]; var testReq3 = require('../fixtures/sync-deps.js'); var testReq4 = require('../fixtures/no-deps.js'); expect(testReq1).to.not.eql(testReq3); expect(testReq2).to.not.eql(testReq4); delete require.cache[require.resolve('../fixtures/sync-deps.js')]; delete require.cache[require.resolve('../fixtures/no-deps.js')]; var lenChildrenBeforeReq2 = module.children.length; var req2 = stealthyRequire(require.cache, function () { return require('../fixtures/deep-sync-deps.js'); }, function () { require('../fixtures/sync-deps.js'); }, module); var lenChildrenAfterReq2 = module.children.length; var req3 = require('../fixtures/sync-deps.js'); expect(req3).to.eql(req2.dep); expect(req3.dep).to.eql(req2.dep.dep); expect(lenChildrenAfterReq2).to.eql(lenChildrenBeforeReq2+1); }); it('should not pollute require cache with dependencies that should be kept but are never required', function () { var testReq1 = require('../fixtures/sync-deps.js'); var testReq2 = require('../fixtures/no-deps.js'); delete require.cache[require.resolve('../fixtures/sync-deps.js')]; delete require.cache[require.resolve('../fixtures/no-deps.js')]; var testReq3 = require('../fixtures/sync-deps.js'); var testReq4 = require('../fixtures/no-deps.js'); expect(testReq1).to.not.eql(testReq3); expect(testReq2).to.not.eql(testReq4); delete require.cache[require.resolve('../fixtures/sync-deps.js')]; delete require.cache[require.resolve('../fixtures/no-deps.js')]; stealthyRequire(require.cache, function () { return require('../fixtures/no-deps.js'); }, function () { require('../fixtures/sync-deps.js'); }, module); expect(require.cache[require.resolve('../fixtures/sync-deps.js')]).to.eql(undefined); expect(require.cache.hasOwnProperty(require.resolve('../fixtures/sync-deps.js'))).to.eql(false); // eslint-disable-line no-prototype-builtins }); }); stealthy-require-1.1.1/test/spec/webpack.js000066400000000000000000000044331310423571400207100ustar00rootroot00000000000000'use strict'; var path = require('path'); var webpack = require('webpack'); describe('When using Webpack, Stealthy-Require', function () { it('should allow Webpack to replace the require call', function (done) { var config = { entry: path.join(__dirname, '../fixtures/stealthy-require.js'), output: { path: path.join(__dirname, '../results'), filename: 'webpack.bundle.js' } }; webpack(config, function (err, stats) { if (err) { done(err); return; } stats = stats.toJson(); if (stats.errors && stats.errors.length > 0) { done(stats.errors); return; } var log = []; var origConsoleLog = console.log; console.log = function (text) { log.push(text); }; require('../results/webpack.bundle.js'); console.log = origConsoleLog; expect(log.length).to.eql(3); expect(log[0]).to.eql(log[2]); expect(log[0]).to.not.eql(log[1]); done(); }); }); it('should allow Webpack to replace the require call for keeping modules', function (done) { var config = { entry: path.join(__dirname, '../fixtures/stealthy-require-and-keep.js'), output: { path: path.join(__dirname, '../results'), filename: 'webpack.keep.bundle.js' } }; webpack(config, function (err, stats) { if (err) { done(err); return; } stats = stats.toJson(); if (stats.errors && stats.errors.length > 0) { done(stats.errors); return; } var log = []; var origConsoleLog = console.log; console.log = function (text) { log.push(text); }; require('../results/webpack.keep.bundle.js'); console.log = origConsoleLog; expect(log.length).to.eql(3); expect(log[0]).to.eql(log[2]); expect(log[0]).to.eql(log[1]); done(); }); }); });