diff --git a/src/debugMain.js b/src/debugMain.js index e6eccb2..5b86a09 100644 --- a/src/debugMain.js +++ b/src/debugMain.js @@ -20,96 +20,10 @@ const xpath = require('xpath'); const { ADBClient } = require('./adbclient'); const { Debugger } = require('./debugger'); const $ = require('./jq-promise'); +const NumberBaseConverter = require('./nbc'); const { D, isEmptyObject } = require('./util'); const ws_proxy = require('./wsproxy').proxy.Server(6037, 5037); -// arbitrary precision helper class for 64 bit numbers -const NumberBaseConverter = { - // Adds two arrays for the given base (10 or 16), returning the result. - add(x, y, base) { - var z = [], n = Math.max(x.length, y.length), carry = 0, i = 0; - while (i < n || carry) { - var xi = i < x.length ? x[i] : 0; - var yi = i < y.length ? y[i] : 0; - var zi = carry + xi + yi; - z.push(zi % base); - carry = Math.floor(zi / base); - i++; - } - return z; - }, - // Returns a*x, where x is an array of decimal digits and a is an ordinary - // JavaScript number. base is the number base of the array x. - multiplyByNumber(num, x, base) { - if (num < 0) return null; - if (num == 0) return []; - var result = [], power = x; - for(;;) { - if (num & 1) { - result = this.add(result, power, base); - } - num = num >> 1; - if (num === 0) return result; - power = this.add(power, power, base); - } - }, - twosComplement(str, base) { - const invdigits = str.split('').map(c => 15 - parseInt(c,base)).reverse(); - const negdigits = this.add(invdigits, [1], base).slice(0,str.length); - return negdigits.reverse().map(d => d.toString(base)).join(''); - }, - convertBase(str, fromBase, toBase) { - if (fromBase === 10 && /[eE]/.test(str)) { - // convert exponents to a string of zeros - var s = str.split(/[eE]/); - str = s[0] + '0'.repeat(parseInt(s[1],10)); // works for 0/+ve exponent,-ve throws - } - var digits = str.split('').map(d => parseInt(d,fromBase)).reverse(); - var outArray = [], power = [1]; - for (var i = 0; i < digits.length; i++) { - if (digits[i]) { - outArray = this.add(outArray, this.multiplyByNumber(digits[i], power, toBase), toBase); - } - power = this.multiplyByNumber(fromBase, power, toBase); - } - return outArray.reverse().map(d => d.toString(toBase)).join(''); - }, - decToHex(decstr, minlen) { - var res, isneg = decstr[0] === '-'; - if (isneg) decstr = decstr.slice(1) - decstr = decstr.match(/^0*(.+)$/)[1]; // strip leading zeros - if (decstr.length < 16 && !/[eE]/.test(decstr)) { // 16 = Math.pow(2,52).toString().length - // less than 52 bits - just use parseInt - res = parseInt(decstr, 10).toString(16); - } else { - res = NumberBaseConverter.convertBase(decstr, 10, 16); - } - if (isneg) { - res = NumberBaseConverter.twosComplement(res, 16); - if (/^[0-7]/.test(res)) res = 'f'+res; //msb must be set for -ve numbers - } else if (/^[^0-7]/.test(res)) - res = '0' + res; // msb must not be set for +ve numbers - if (minlen && res.length < minlen) { - res = (isneg?'f':'0').repeat(minlen - res.length) + res; - } - return res; - }, - hexToDec(hexstr, signed) { - var res, isneg = /^[^0-7]/.test(hexstr); - if (hexstr.match(/^0*(.+)$/)[1].length*4 < 52) { - // less than 52 bits - just use parseInt - res = parseInt(hexstr, 16); - if (signed && isneg) res = -res; - return res.toString(10); - } - if (isneg) { - hexstr = NumberBaseConverter.twosComplement(hexstr, 16); - } - res = (isneg ? '-' : '') + NumberBaseConverter.convertBase(hexstr, 16, 10); - return res; - }, -}; - // some commonly used Java types in debugger-compatible format const JTYPES = { byte: {name:'int',signature:'B'}, @@ -1440,7 +1354,7 @@ class AndroidDebugSession extends DebugSession { local = { vtype:'literal',name:'',hasnullvalue:true,type:JTYPES.null,value:nullvalue,valid:true }; break; case 'ident': - if (!locals) reject_evaluation(`Cannot find variable: ${expr.root_term}`); + if (!locals) return reject_evaluation(`Cannot find variable: ${expr.root_term}`); local = locals.find(l => l.name === expr.root_term); break; case 'number': diff --git a/src/jq-promise.js b/src/jq-promise.js index a0c726f..f5d982d 100644 --- a/src/jq-promise.js +++ b/src/jq-promise.js @@ -50,6 +50,8 @@ var Deferred = exports.Deferred = function(p, parent) { var res = this.fn.apply(this.def._context,a); if (res === undefined) return a; + if (res && res._isdeferred) + return res._promise; return res; }.bind({def:faildef,fn:fn})); faildef._promise = faildef._original = p; diff --git a/src/nbc.js b/src/nbc.js new file mode 100644 index 0000000..7bbade0 --- /dev/null +++ b/src/nbc.js @@ -0,0 +1,89 @@ + +// arbitrary precision helper class for 64 bit numbers +const NumberBaseConverter = { + // Adds two arrays for the given base (10 or 16), returning the result. + add(x, y, base) { + var z = [], n = Math.max(x.length, y.length), carry = 0, i = 0; + while (i < n || carry) { + var xi = i < x.length ? x[i] : 0; + var yi = i < y.length ? y[i] : 0; + var zi = carry + xi + yi; + z.push(zi % base); + carry = Math.floor(zi / base); + i++; + } + return z; + }, + // Returns a*x, where x is an array of decimal digits and a is an ordinary + // JavaScript number. base is the number base of the array x. + multiplyByNumber(num, x, base) { + if (num < 0) return null; + if (num == 0) return []; + var result = [], power = x; + for(;;) { + if (num & 1) { + result = this.add(result, power, base); + } + num = num >> 1; + if (num === 0) return result; + power = this.add(power, power, base); + } + }, + twosComplement(str, base) { + const invdigits = str.split('').map(c => base - 1 - parseInt(c,base)).reverse(); + const negdigits = this.add(invdigits, [1], base).slice(0,str.length); + return negdigits.reverse().map(d => d.toString(base)).join(''); + }, + convertBase(str, fromBase, toBase) { + if (fromBase === 10 && /[eE]/.test(str)) { + // convert exponents to a string of zeros + var s = str.split(/[eE]/); + str = s[0] + '0'.repeat(parseInt(s[1],10)); // works for 0/+ve exponent,-ve throws + } + var digits = str.split('').map(d => parseInt(d,fromBase)).reverse(); + var outArray = [], power = [1]; + for (var i = 0; i < digits.length; i++) { + if (digits[i]) { + outArray = this.add(outArray, this.multiplyByNumber(digits[i], power, toBase), toBase); + } + power = this.multiplyByNumber(fromBase, power, toBase); + } + return outArray.reverse().map(d => d.toString(toBase)).join(''); + }, + decToHex(decstr, minlen) { + var res, isneg = decstr[0] === '-'; + if (isneg) decstr = decstr.slice(1) + decstr = decstr.match(/^0*(.+)$/)[1]; // strip leading zeros + if (decstr.length < 16 && !/[eE]/.test(decstr)) { // 16 = Math.pow(2,52).toString(10).length + // less than 52 bits - just use parseInt + res = parseInt(decstr, 10).toString(16); + } else { + res = NumberBaseConverter.convertBase(decstr, 10, 16); + } + if (isneg) { + res = NumberBaseConverter.twosComplement(res, 16); + if (/^[0-7]/.test(res)) res = 'f'+res; //msb must be set for -ve numbers + } else if (/^[^0-7]/.test(res)) + res = '0' + res; // msb must not be set for +ve numbers + if (minlen && res.length < minlen) { + res = (isneg?'f':'0').repeat(minlen - res.length) + res; + } + return res; + }, + hexToDec(hexstr, signed) { + var res, isneg = /^[^0-7]/.test(hexstr); + if (hexstr.match(/^0*(.+)$/)[1].length*4 < 52) { + // less than 52 bits - just use parseInt + res = parseInt(hexstr, 16); + if (signed && isneg) res = -res; + return res.toString(10); + } + if (isneg) { + hexstr = NumberBaseConverter.twosComplement(hexstr, 16); + } + res = (isneg ? '-' : '') + NumberBaseConverter.convertBase(hexstr, 16, 10); + return res; + }, +}; + +Object.assign(exports, NumberBaseConverter);