| 1 | /**
|
|---|
| 2 | * Module dependencies.
|
|---|
| 3 | */
|
|---|
| 4 |
|
|---|
| 5 | var fs = require('fs'),
|
|---|
| 6 | path = require('path'),
|
|---|
| 7 | fileURLToPath = require('file-uri-to-path'),
|
|---|
| 8 | join = path.join,
|
|---|
| 9 | dirname = path.dirname,
|
|---|
| 10 | exists =
|
|---|
| 11 | (fs.accessSync &&
|
|---|
| 12 | function(path) {
|
|---|
| 13 | try {
|
|---|
| 14 | fs.accessSync(path);
|
|---|
| 15 | } catch (e) {
|
|---|
| 16 | return false;
|
|---|
| 17 | }
|
|---|
| 18 | return true;
|
|---|
| 19 | }) ||
|
|---|
| 20 | fs.existsSync ||
|
|---|
| 21 | path.existsSync,
|
|---|
| 22 | defaults = {
|
|---|
| 23 | arrow: process.env.NODE_BINDINGS_ARROW || ' → ',
|
|---|
| 24 | compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled',
|
|---|
| 25 | platform: process.platform,
|
|---|
| 26 | arch: process.arch,
|
|---|
| 27 | nodePreGyp:
|
|---|
| 28 | 'node-v' +
|
|---|
| 29 | process.versions.modules +
|
|---|
| 30 | '-' +
|
|---|
| 31 | process.platform +
|
|---|
| 32 | '-' +
|
|---|
| 33 | process.arch,
|
|---|
| 34 | version: process.versions.node,
|
|---|
| 35 | bindings: 'bindings.node',
|
|---|
| 36 | try: [
|
|---|
| 37 | // node-gyp's linked version in the "build" dir
|
|---|
| 38 | ['module_root', 'build', 'bindings'],
|
|---|
| 39 | // node-waf and gyp_addon (a.k.a node-gyp)
|
|---|
| 40 | ['module_root', 'build', 'Debug', 'bindings'],
|
|---|
| 41 | ['module_root', 'build', 'Release', 'bindings'],
|
|---|
| 42 | // Debug files, for development (legacy behavior, remove for node v0.9)
|
|---|
| 43 | ['module_root', 'out', 'Debug', 'bindings'],
|
|---|
| 44 | ['module_root', 'Debug', 'bindings'],
|
|---|
| 45 | // Release files, but manually compiled (legacy behavior, remove for node v0.9)
|
|---|
| 46 | ['module_root', 'out', 'Release', 'bindings'],
|
|---|
| 47 | ['module_root', 'Release', 'bindings'],
|
|---|
| 48 | // Legacy from node-waf, node <= 0.4.x
|
|---|
| 49 | ['module_root', 'build', 'default', 'bindings'],
|
|---|
| 50 | // Production "Release" buildtype binary (meh...)
|
|---|
| 51 | ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'],
|
|---|
| 52 | // node-qbs builds
|
|---|
| 53 | ['module_root', 'addon-build', 'release', 'install-root', 'bindings'],
|
|---|
| 54 | ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'],
|
|---|
| 55 | ['module_root', 'addon-build', 'default', 'install-root', 'bindings'],
|
|---|
| 56 | // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch}
|
|---|
| 57 | ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings']
|
|---|
| 58 | ]
|
|---|
| 59 | };
|
|---|
| 60 |
|
|---|
| 61 | /**
|
|---|
| 62 | * The main `bindings()` function loads the compiled bindings for a given module.
|
|---|
| 63 | * It uses V8's Error API to determine the parent filename that this function is
|
|---|
| 64 | * being invoked from, which is then used to find the root directory.
|
|---|
| 65 | */
|
|---|
| 66 |
|
|---|
| 67 | function bindings(opts) {
|
|---|
| 68 | // Argument surgery
|
|---|
| 69 | if (typeof opts == 'string') {
|
|---|
| 70 | opts = { bindings: opts };
|
|---|
| 71 | } else if (!opts) {
|
|---|
| 72 | opts = {};
|
|---|
| 73 | }
|
|---|
| 74 |
|
|---|
| 75 | // maps `defaults` onto `opts` object
|
|---|
| 76 | Object.keys(defaults).map(function(i) {
|
|---|
| 77 | if (!(i in opts)) opts[i] = defaults[i];
|
|---|
| 78 | });
|
|---|
| 79 |
|
|---|
| 80 | // Get the module root
|
|---|
| 81 | if (!opts.module_root) {
|
|---|
| 82 | opts.module_root = exports.getRoot(exports.getFileName());
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | // Ensure the given bindings name ends with .node
|
|---|
| 86 | if (path.extname(opts.bindings) != '.node') {
|
|---|
| 87 | opts.bindings += '.node';
|
|---|
| 88 | }
|
|---|
| 89 |
|
|---|
| 90 | // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035
|
|---|
| 91 | var requireFunc =
|
|---|
| 92 | typeof __webpack_require__ === 'function'
|
|---|
| 93 | ? __non_webpack_require__
|
|---|
| 94 | : require;
|
|---|
| 95 |
|
|---|
| 96 | var tries = [],
|
|---|
| 97 | i = 0,
|
|---|
| 98 | l = opts.try.length,
|
|---|
| 99 | n,
|
|---|
| 100 | b,
|
|---|
| 101 | err;
|
|---|
| 102 |
|
|---|
| 103 | for (; i < l; i++) {
|
|---|
| 104 | n = join.apply(
|
|---|
| 105 | null,
|
|---|
| 106 | opts.try[i].map(function(p) {
|
|---|
| 107 | return opts[p] || p;
|
|---|
| 108 | })
|
|---|
| 109 | );
|
|---|
| 110 | tries.push(n);
|
|---|
| 111 | try {
|
|---|
| 112 | b = opts.path ? requireFunc.resolve(n) : requireFunc(n);
|
|---|
| 113 | if (!opts.path) {
|
|---|
| 114 | b.path = n;
|
|---|
| 115 | }
|
|---|
| 116 | return b;
|
|---|
| 117 | } catch (e) {
|
|---|
| 118 | if (e.code !== 'MODULE_NOT_FOUND' &&
|
|---|
| 119 | e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' &&
|
|---|
| 120 | !/not find/i.test(e.message)) {
|
|---|
| 121 | throw e;
|
|---|
| 122 | }
|
|---|
| 123 | }
|
|---|
| 124 | }
|
|---|
| 125 |
|
|---|
| 126 | err = new Error(
|
|---|
| 127 | 'Could not locate the bindings file. Tried:\n' +
|
|---|
| 128 | tries
|
|---|
| 129 | .map(function(a) {
|
|---|
| 130 | return opts.arrow + a;
|
|---|
| 131 | })
|
|---|
| 132 | .join('\n')
|
|---|
| 133 | );
|
|---|
| 134 | err.tries = tries;
|
|---|
| 135 | throw err;
|
|---|
| 136 | }
|
|---|
| 137 | module.exports = exports = bindings;
|
|---|
| 138 |
|
|---|
| 139 | /**
|
|---|
| 140 | * Gets the filename of the JavaScript file that invokes this function.
|
|---|
| 141 | * Used to help find the root directory of a module.
|
|---|
| 142 | * Optionally accepts an filename argument to skip when searching for the invoking filename
|
|---|
| 143 | */
|
|---|
| 144 |
|
|---|
| 145 | exports.getFileName = function getFileName(calling_file) {
|
|---|
| 146 | var origPST = Error.prepareStackTrace,
|
|---|
| 147 | origSTL = Error.stackTraceLimit,
|
|---|
| 148 | dummy = {},
|
|---|
| 149 | fileName;
|
|---|
| 150 |
|
|---|
| 151 | Error.stackTraceLimit = 10;
|
|---|
| 152 |
|
|---|
| 153 | Error.prepareStackTrace = function(e, st) {
|
|---|
| 154 | for (var i = 0, l = st.length; i < l; i++) {
|
|---|
| 155 | fileName = st[i].getFileName();
|
|---|
| 156 | if (fileName !== __filename) {
|
|---|
| 157 | if (calling_file) {
|
|---|
| 158 | if (fileName !== calling_file) {
|
|---|
| 159 | return;
|
|---|
| 160 | }
|
|---|
| 161 | } else {
|
|---|
| 162 | return;
|
|---|
| 163 | }
|
|---|
| 164 | }
|
|---|
| 165 | }
|
|---|
| 166 | };
|
|---|
| 167 |
|
|---|
| 168 | // run the 'prepareStackTrace' function above
|
|---|
| 169 | Error.captureStackTrace(dummy);
|
|---|
| 170 | dummy.stack;
|
|---|
| 171 |
|
|---|
| 172 | // cleanup
|
|---|
| 173 | Error.prepareStackTrace = origPST;
|
|---|
| 174 | Error.stackTraceLimit = origSTL;
|
|---|
| 175 |
|
|---|
| 176 | // handle filename that starts with "file://"
|
|---|
| 177 | var fileSchema = 'file://';
|
|---|
| 178 | if (fileName.indexOf(fileSchema) === 0) {
|
|---|
| 179 | fileName = fileURLToPath(fileName);
|
|---|
| 180 | }
|
|---|
| 181 |
|
|---|
| 182 | return fileName;
|
|---|
| 183 | };
|
|---|
| 184 |
|
|---|
| 185 | /**
|
|---|
| 186 | * Gets the root directory of a module, given an arbitrary filename
|
|---|
| 187 | * somewhere in the module tree. The "root directory" is the directory
|
|---|
| 188 | * containing the `package.json` file.
|
|---|
| 189 | *
|
|---|
| 190 | * In: /home/nate/node-native-module/lib/index.js
|
|---|
| 191 | * Out: /home/nate/node-native-module
|
|---|
| 192 | */
|
|---|
| 193 |
|
|---|
| 194 | exports.getRoot = function getRoot(file) {
|
|---|
| 195 | var dir = dirname(file),
|
|---|
| 196 | prev;
|
|---|
| 197 | while (true) {
|
|---|
| 198 | if (dir === '.') {
|
|---|
| 199 | // Avoids an infinite loop in rare cases, like the REPL
|
|---|
| 200 | dir = process.cwd();
|
|---|
| 201 | }
|
|---|
| 202 | if (
|
|---|
| 203 | exists(join(dir, 'package.json')) ||
|
|---|
| 204 | exists(join(dir, 'node_modules'))
|
|---|
| 205 | ) {
|
|---|
| 206 | // Found the 'package.json' file or 'node_modules' dir; we're done
|
|---|
| 207 | return dir;
|
|---|
| 208 | }
|
|---|
| 209 | if (prev === dir) {
|
|---|
| 210 | // Got to the top
|
|---|
| 211 | throw new Error(
|
|---|
| 212 | 'Could not find module root given file: "' +
|
|---|
| 213 | file +
|
|---|
| 214 | '". Do you have a `package.json` file? '
|
|---|
| 215 | );
|
|---|
| 216 | }
|
|---|
| 217 | // Try the parent dir next
|
|---|
| 218 | prev = dir;
|
|---|
| 219 | dir = join(dir, '..');
|
|---|
| 220 | }
|
|---|
| 221 | };
|
|---|