Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
81146 views
1
2
/**
3
* Module dependencies.
4
*/
5
6
var fs = require('fs')
7
, path = require('path')
8
, join = path.join
9
, dirname = path.dirname
10
, exists = fs.existsSync || path.existsSync
11
, defaults = {
12
arrow: process.env.NODE_BINDINGS_ARROW || ' → '
13
, compiled: process.env.NODE_BINDINGS_COMPILED_DIR || 'compiled'
14
, platform: process.platform
15
, arch: process.arch
16
, version: process.versions.node
17
, bindings: 'bindings.node'
18
, try: [
19
// node-gyp's linked version in the "build" dir
20
[ 'module_root', 'build', 'bindings' ]
21
// node-waf and gyp_addon (a.k.a node-gyp)
22
, [ 'module_root', 'build', 'Debug', 'bindings' ]
23
, [ 'module_root', 'build', 'Release', 'bindings' ]
24
// Debug files, for development (legacy behavior, remove for node v0.9)
25
, [ 'module_root', 'out', 'Debug', 'bindings' ]
26
, [ 'module_root', 'Debug', 'bindings' ]
27
// Release files, but manually compiled (legacy behavior, remove for node v0.9)
28
, [ 'module_root', 'out', 'Release', 'bindings' ]
29
, [ 'module_root', 'Release', 'bindings' ]
30
// Legacy from node-waf, node <= 0.4.x
31
, [ 'module_root', 'build', 'default', 'bindings' ]
32
// Production "Release" buildtype binary (meh...)
33
, [ 'module_root', 'compiled', 'version', 'platform', 'arch', 'bindings' ]
34
]
35
}
36
37
/**
38
* The main `bindings()` function loads the compiled bindings for a given module.
39
* It uses V8's Error API to determine the parent filename that this function is
40
* being invoked from, which is then used to find the root directory.
41
*/
42
43
function bindings (opts) {
44
45
// Argument surgery
46
if (typeof opts == 'string') {
47
opts = { bindings: opts }
48
} else if (!opts) {
49
opts = {}
50
}
51
opts.__proto__ = defaults
52
53
// Get the module root
54
if (!opts.module_root) {
55
opts.module_root = exports.getRoot(exports.getFileName())
56
}
57
58
// Ensure the given bindings name ends with .node
59
if (path.extname(opts.bindings) != '.node') {
60
opts.bindings += '.node'
61
}
62
63
var tries = []
64
, i = 0
65
, l = opts.try.length
66
, n
67
, b
68
, err
69
70
for (; i<l; i++) {
71
n = join.apply(null, opts.try[i].map(function (p) {
72
return opts[p] || p
73
}))
74
tries.push(n)
75
try {
76
b = opts.path ? require.resolve(n) : require(n)
77
if (!opts.path) {
78
b.path = n
79
}
80
return b
81
} catch (e) {
82
if (!/not find/i.test(e.message)) {
83
throw e
84
}
85
}
86
}
87
88
err = new Error('Could not locate the bindings file. Tried:\n'
89
+ tries.map(function (a) { return opts.arrow + a }).join('\n'))
90
err.tries = tries
91
throw err
92
}
93
module.exports = exports = bindings
94
95
96
/**
97
* Gets the filename of the JavaScript file that invokes this function.
98
* Used to help find the root directory of a module.
99
* Optionally accepts an filename argument to skip when searching for the invoking filename
100
*/
101
102
exports.getFileName = function getFileName (calling_file) {
103
var origPST = Error.prepareStackTrace
104
, origSTL = Error.stackTraceLimit
105
, dummy = {}
106
, fileName
107
108
Error.stackTraceLimit = 10
109
110
Error.prepareStackTrace = function (e, st) {
111
for (var i=0, l=st.length; i<l; i++) {
112
fileName = st[i].getFileName()
113
if (fileName !== __filename) {
114
if (calling_file) {
115
if (fileName !== calling_file) {
116
return
117
}
118
} else {
119
return
120
}
121
}
122
}
123
}
124
125
// run the 'prepareStackTrace' function above
126
Error.captureStackTrace(dummy)
127
dummy.stack
128
129
// cleanup
130
Error.prepareStackTrace = origPST
131
Error.stackTraceLimit = origSTL
132
133
return fileName
134
}
135
136
/**
137
* Gets the root directory of a module, given an arbitrary filename
138
* somewhere in the module tree. The "root directory" is the directory
139
* containing the `package.json` file.
140
*
141
* In: /home/nate/node-native-module/lib/index.js
142
* Out: /home/nate/node-native-module
143
*/
144
145
exports.getRoot = function getRoot (file) {
146
var dir = dirname(file)
147
, prev
148
while (true) {
149
if (dir === '.') {
150
// Avoids an infinite loop in rare cases, like the REPL
151
dir = process.cwd()
152
}
153
if (exists(join(dir, 'package.json')) || exists(join(dir, 'node_modules'))) {
154
// Found the 'package.json' file or 'node_modules' dir; we're done
155
return dir
156
}
157
if (prev === dir) {
158
// Got to the top
159
throw new Error('Could not find module root given file: "' + file
160
+ '". Do you have a `package.json` file? ')
161
}
162
// Try the parent dir next
163
prev = dir
164
dir = join(dir, '..')
165
}
166
}
167
168