/usr/lib/nodejs/with/index.js is in node-with 3.0.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 'use strict';
var uglify = require('uglify-js')
module.exports = addWith
/**
* Mimic `with` as far as possible but at compile time
*
* @param {String} obj The object part of a with expression
* @param {String} src The body of the with expression
* @param {Array.<String>} exclude A list of variable names to explicitly exclude
*/
function addWith(obj, src, exclude) {
obj = obj + ''
src = src + ''
exclude = exclude || []
exclude = exclude.concat(detect(obj))
var vars = detect(src)
.filter(function (v) {
return exclude.indexOf(v) === -1
})
if (vars.length === 0) return src
var declareLocal = ''
var local = 'locals_for_with'
var result = 'result_of_with'
if (/^[a-zA-Z0-9$_]+$/.test(obj)) {
local = obj
} else {
while (vars.indexOf(local) != -1 || exclude.indexOf(local) != -1) {
local += '_'
}
declareLocal = 'var ' + local + ' = (' + obj + ')'
}
while (vars.indexOf(result) != -1 || exclude.indexOf(result) != -1) {
result += '_'
}
var inputVars = vars.map(function (v) {
return JSON.stringify(v) + ' in ' + local + '?' +
local + '.' + v + ':' +
'typeof ' + v + '!=="undefined"?' + v + ':undefined'
})
src = '(function (' + vars.join(', ') + ') {' +
src +
'}(' + inputVars.join(',') + '))'
return ';' + declareLocal + ';' + unwrapReturns(src, result) + ';'
}
/**
* Detect, and return a list of, any global variables in a function
*
* @param {String} src Some JavaScript code
*/
function detect(src) {
var ast = uglify.parse('(function () {' + src + '}())') // allow return keyword
ast.figure_out_scope()
var globals = ast.globals
.map(function (node, name) {
return name
})
return globals
}
/**
* Take a self calling function, and unwrap it such that return inside the function
* results in return outside the function
*
* @param {String} src Some JavaScript code representing a self-calling function
* @param {String} result A temporary variable to store the result in
*/
function unwrapReturns(src, result) {
var originalSource = src
var hasReturn = false
var ast = uglify.parse(src)
src = src.split('')
if (ast.body.length !== 1 || ast.body[0].TYPE !== 'SimpleStatement' ||
ast.body[0].body.TYPE !== 'Call' || ast.body[0].body.expression.TYPE !== 'Function')
throw new Error('AST does not seem to represent a self-calling function')
var fn = ast.body[0].body.expression
var walker = new uglify.TreeWalker(visitor)
function visitor(node, descend) {
if (node !== fn && (node.TYPE === 'Defun' || node.TYPE === 'Function')) {
return true //don't descend into functions
}
if (node.TYPE === 'Return') {
descend()
hasReturn = true
replace(node, 'return {value: ' + source(node.value) + '};')
return true //don't descend again
}
}
function source(node) {
return src.slice(node.start.pos, node.end.endpos).join('')
}
function replace(node, str) {
for (var i = node.start.pos; i < node.end.endpos; i++) {
src[i] = ''
}
src[node.start.pos] = str
}
ast.walk(walker)
if (!hasReturn) return originalSource
else return 'var ' + result + '=' + src.join('') + ';if (' + result + ') return ' + result + '.value'
}
|