123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- /**
- * 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, '..');
- }
- };
|