protobuf.js使用uint64类型超过16位长度decode的bug
原版在这里:
https://www.npmjs.com/package/protobufjs
protobuf-library.js里有个LongBits的原型toNumber是这样写的:
LongBits.prototype.toNumber = function toNumber(unsigned) { if (!unsigned && this.hi >>> 31) { var lo = ~this.lo + 1 >>> 0, hi = ~this.hi >>> 0; if (!lo) hi = hi + 1 >>> 0; return -(lo + hi * 4294967296); } return this.lo + this.hi * 4294967296; };我一步步查到
this.lo + this.hi * 4294967296;
的时候发现精度有问题
搜了好久发现了一个BigInt解决这个问题
修改后如下:
LongBits.prototype.toNumber = function toNumber(unsigned) { if (!unsigned && this.hi >>> 31) { var lo = ~this.lo + 1 >>> 0, hi = ~this.hi >>> 0; if (!lo) hi = hi + 1 >>> 0; return -(lo + hi * 4294967296); } return (BigInt(this.lo) + BigInt(this.hi * 4294967296)).toString(); };proto_bundle.min文件搜索
this.lo+4294967296*this.hi进行替换
(BigInt(this.lo)+BigInt(4294967296*this.hi)).toString()
protobuf-library.min文件搜
this.lo+this.hi*4294967296进行替换
(BigInt(this.lo)+BigInt(this.hi*4294967296)).toString()
解决方案2:
protobuf-library.js开头引用
let bigIntXXX; if(!window.bigInt) { bigIntXXX = require("./BigInteger.js"); } else { bigIntXXX = bigInt; }
LongBits.prototype.toNumber修改为
LongBits.prototype.toNumber = function toNumber(unsigned) { if (!unsigned && this.hi >>> 31) { var lo = ~this.lo + 1 >>> 0, hi = ~this.hi >>> 0; if (!lo) hi = hi + 1 >>> 0; return -(lo + hi * 4294967296); } let xxx = bigIntXXX(this.lo.toString()).add(bigIntXXX(this.hi.toString()).multiply(4294967296)); return xxx.toString(); };