1 | /*
|
2 | Copyright (c) 2014 Google Inc. All rights reserved.
|
3 | Copyright (c) 2012-2013 Johannes Ewald.
|
4 |
|
5 | Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
6 | or at http://opensource.org/licenses/MIT.
|
7 | */
|
8 | ;
|
9 |
|
10 | /** @module lib/requizzle */
|
11 |
|
12 | var _ = require('underscore');
|
13 | var loader = require('./loader');
|
14 | var Module = require('module');
|
15 | var path = require('path');
|
16 |
|
17 | /**
|
18 | * Function that returns text to swizzle into the module.
|
19 | *
|
20 | * @typedef module:lib/requizzle~wrapperFunction
|
21 | * @type {function}
|
22 | * @param {string} targetPath - The path to the target module.
|
23 | * @param {string} parentModulePath - The path to the module that is requiring the target module.
|
24 | * @return {string} The text to insert before or after the module's source code.
|
25 | */
|
26 |
|
27 | /**
|
28 | * Options for the wrappers that will be swizzled into the target module.
|
29 | *
|
30 | * @typedef module:lib/requizzle~options
|
31 | * @type {Object}
|
32 | * @property {Object=} options.extras - Functions that generate text to swizzle into the target
|
33 | * module.
|
34 | * @property {module:lib/requizzle~wrapperFunction} options.extras.after - Function that returns
|
35 | * text to insert after the module's source code.
|
36 | * @property {module:lib/requizzle~wrapperFunction} options.extras.before - Function that returns
|
37 | * text to insert before the module's source code.
|
38 | * @property {(Array.<string>|string)} options.requirePaths - Additional paths to search when
|
39 | * resolving module paths in the target module.
|
40 | */
|
41 |
|
42 | function isNativeModule(targetPath, parentModule) {
|
43 | var lookupPaths = Module._resolveLookupPaths(targetPath, parentModule);
|
44 |
|
45 | if (lookupPaths[0] === targetPath && lookupPaths[1].length === 0) {
|
46 | return true;
|
47 | }
|
48 |
|
49 | return false;
|
50 | }
|
51 |
|
52 | /**
|
53 | * Create a `Requizzle` instance. If you provide options, Requizzle will default to those options
|
54 | * when you call {@link Requizzle#requizzle}.
|
55 | *
|
56 | * @class
|
57 | * @param {!module:lib/requizzle~options} options - Options for the wrappers that will be swizzled
|
58 | * into the target module.
|
59 | * @param {Object=} cache - For internal use.
|
60 | */
|
61 | function Requizzle(options, cache) {
|
62 | this._options = options;
|
63 | this._cache = cache || {
|
64 | module: {},
|
65 | source: {}
|
66 | };
|
67 | }
|
68 |
|
69 | /**
|
70 | * Load the module, swizzling in the requested changes.
|
71 | *
|
72 | * @param {!string} targetPath - The path to the module that will be loaded.
|
73 | * @return {Module} The swizzled module.
|
74 | */
|
75 | Requizzle.prototype.requizzle = function requizzle(targetPath) {
|
76 | var options = this._options;
|
77 | var parentModule = options.parent;
|
78 | var targetModule;
|
79 | var wrapper;
|
80 |
|
81 | // Don't interfere with native modules
|
82 | if (isNativeModule(targetPath, parentModule)) {
|
83 | return require(targetPath);
|
84 | }
|
85 |
|
86 | // Resolve the filename relative to the parent module
|
87 | targetPath = Module._resolveFilename(targetPath, parentModule);
|
88 |
|
89 | wrapper = loader.createWrapper(targetPath, parentModule, this._cache, this._options);
|
90 | targetModule = loader.load(targetPath, parentModule, wrapper, this._cache, this._options);
|
91 |
|
92 | return targetModule.exports;
|
93 | };
|
94 |
|
95 | module.exports = Requizzle;
|