123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- /**
- * Module dependencies.
- */
- var fs = require('fs')
- , path = require('path')
- , join = path.join
- , dirname = path.dirname
- , exists = 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
- , 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' ]
- ]
- }
- /**
- * 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 = {}
- }
- opts.__proto__ = defaults
- // 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'
- }
- 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 ? require.resolve(n) : require(n)
- if (!opts.path) {
- b.path = n
- }
- return b
- } catch (e) {
- if (!/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
- 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, '..')
- }
- }
|