| /** |
| * Module dependencies. |
| */ |
| |
| var fs = require('fs'), |
| path = require('path'), |
| fileURLToPath = require('file-uri-to-path'), |
| join = path.join, |
| dirname = path.dirname, |
| exists = |
| (fs.accessSync && |
| function(path) { |
| try { |
| fs.accessSync(path); |
| } catch (e) { |
| return false; |
| } |
| return true; |
| }) || |
| fs.existsSync || |
| path.existsSync, |
| defaults = { |
| arrow: process.env.NODE_BINDINGS_ARROW || ' → ', |
| compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled', |
| platform: process.platform, |
| arch: process.arch, |
| nodePreGyp: |
| 'node-v' + |
| process.versions.modules + |
| '-' + |
| process.platform + |
| '-' + |
| process.arch, |
| version: process.versions.node, |
| bindings: 'bindings.node', |
| try: [ |
| // node-gyp's linked version in the "build" dir |
| ['module_root', 'build', 'bindings'], |
| // node-waf and gyp_addon (a.k.a node-gyp) |
| ['module_root', 'build', 'Debug', 'bindings'], |
| ['module_root', 'build', 'Release', 'bindings'], |
| // Debug files, for development (legacy behavior, remove for node v0.9) |
| ['module_root', 'out', 'Debug', 'bindings'], |
| ['module_root', 'Debug', 'bindings'], |
| // Release files, but manually compiled (legacy behavior, remove for node v0.9) |
| ['module_root', 'out', 'Release', 'bindings'], |
| ['module_root', 'Release', 'bindings'], |
| // Legacy from node-waf, node <= 0.4.x |
| ['module_root', 'build', 'default', 'bindings'], |
| // Production "Release" buildtype binary (meh...) |
| ['module_root', 'compiled', 'version', 'platform', 'arch', 'bindings'], |
| // node-qbs builds |
| ['module_root', 'addon-build', 'release', 'install-root', 'bindings'], |
| ['module_root', 'addon-build', 'debug', 'install-root', 'bindings'], |
| ['module_root', 'addon-build', 'default', 'install-root', 'bindings'], |
| // node-pre-gyp path ./lib/binding/{node_abi}-{platform}-{arch} |
| ['module_root', 'lib', 'binding', 'nodePreGyp', 'bindings'] |
| ] |
| }; |
| |
| /** |
| * The main `bindings()` function loads the compiled bindings for a given module. |
| * It uses V8's Error API to determine the parent filename that this function is |
| * being invoked from, which is then used to find the root directory. |
| */ |
| |
| function bindings(opts) { |
| // Argument surgery |
| if (typeof opts == 'string') { |
| opts = { bindings: opts }; |
| } else if (!opts) { |
| opts = {}; |
| } |
| |
| // maps `defaults` onto `opts` object |
| Object.keys(defaults).map(function(i) { |
| if (!(i in opts)) opts[i] = defaults[i]; |
| }); |
| |
| // Get the module root |
| if (!opts.module_root) { |
| opts.module_root = exports.getRoot(exports.getFileName()); |
| } |
| |
| // Ensure the given bindings name ends with .node |
| if (path.extname(opts.bindings) != '.node') { |
| opts.bindings += '.node'; |
| } |
| |
| // https://github.com/webpack/webpack/issues/4175#issuecomment-342931035 |
| var requireFunc = |
| typeof __webpack_require__ === 'function' |
| ? __non_webpack_require__ |
| : require; |
| |
| var tries = [], |
| i = 0, |
| l = opts.try.length, |
| n, |
| b, |
| err; |
| |
| for (; i < l; i++) { |
| n = join.apply( |
| null, |
| opts.try[i].map(function(p) { |
| return opts[p] || p; |
| }) |
| ); |
| tries.push(n); |
| try { |
| b = opts.path ? requireFunc.resolve(n) : requireFunc(n); |
| if (!opts.path) { |
| b.path = n; |
| } |
| return b; |
| } catch (e) { |
| if (e.code !== 'MODULE_NOT_FOUND' && |
| e.code !== 'QUALIFIED_PATH_RESOLUTION_FAILED' && |
| !/not find/i.test(e.message)) { |
| throw e; |
| } |
| } |
| } |
| |
| err = new Error( |
| 'Could not locate the bindings file. Tried:\n' + |
| tries |
| .map(function(a) { |
| return opts.arrow + a; |
| }) |
| .join('\n') |
| ); |
| err.tries = tries; |
| throw err; |
| } |
| module.exports = exports = bindings; |
| |
| /** |
| * Gets the filename of the JavaScript file that invokes this function. |
| * Used to help find the root directory of a module. |
| * Optionally accepts an filename argument to skip when searching for the invoking filename |
| */ |
| |
| exports.getFileName = function getFileName(calling_file) { |
| var origPST = Error.prepareStackTrace, |
| origSTL = Error.stackTraceLimit, |
| dummy = {}, |
| fileName; |
| |
| Error.stackTraceLimit = 10; |
| |
| Error.prepareStackTrace = function(e, st) { |
| for (var i = 0, l = st.length; i < l; i++) { |
| fileName = st[i].getFileName(); |
| if (fileName !== __filename) { |
| if (calling_file) { |
| if (fileName !== calling_file) { |
| return; |
| } |
| } else { |
| return; |
| } |
| } |
| } |
| }; |
| |
| // run the 'prepareStackTrace' function above |
| Error.captureStackTrace(dummy); |
| dummy.stack; |
| |
| // cleanup |
| Error.prepareStackTrace = origPST; |
| Error.stackTraceLimit = origSTL; |
| |
| // handle filename that starts with "file://" |
| var fileSchema = 'file://'; |
| if (fileName.indexOf(fileSchema) === 0) { |
| fileName = fileURLToPath(fileName); |
| } |
| |
| return fileName; |
| }; |
| |
| /** |
| * Gets the root directory of a module, given an arbitrary filename |
| * somewhere in the module tree. The "root directory" is the directory |
| * containing the `package.json` file. |
| * |
| * In: /home/nate/node-native-module/lib/index.js |
| * Out: /home/nate/node-native-module |
| */ |
| |
| exports.getRoot = function getRoot(file) { |
| var dir = dirname(file), |
| prev; |
| while (true) { |
| if (dir === '.') { |
| // Avoids an infinite loop in rare cases, like the REPL |
| dir = process.cwd(); |
| } |
| if ( |
| exists(join(dir, 'package.json')) || |
| exists(join(dir, 'node_modules')) |
| ) { |
| // Found the 'package.json' file or 'node_modules' dir; we're done |
| return dir; |
| } |
| if (prev === dir) { |
| // Got to the top |
| throw new Error( |
| 'Could not find module root given file: "' + |
| file + |
| '". Do you have a `package.json` file? ' |
| ); |
| } |
| // Try the parent dir next |
| prev = dir; |
| dir = join(dir, '..'); |
| } |
| }; |