Skip to content

Commit

Permalink
make jsbi code paths optional
Browse files Browse the repository at this point in the history
  • Loading branch information
Tony Crisci committed Aug 15, 2020
1 parent 369173a commit f1e2b4a
Show file tree
Hide file tree
Showing 5 changed files with 144 additions and 39 deletions.
49 changes: 44 additions & 5 deletions lib/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,48 @@ MessageFlag.NO_REPLY_EXPECTED = 1;
*/
MessageFlag.NO_AUTO_START = 2;

const MAX_INT64_STR = '9223372036854775807';
const MIN_INT64_STR = '-9223372036854775807';
const MAX_UINT64_STR = '18446744073709551615';
const MIN_UINT64_STR = '0';

const _JSBIConstants = {};

function _getJSBIConstants () {
if (Object.keys(_JSBIConstants).length !== 0) {
return _JSBIConstants;
}

const JSBI = require('jsbi');

_JSBIConstants.MAX_INT64 = JSBI.BigInt(MAX_INT64_STR);
_JSBIConstants.MIN_INT64 = JSBI.BigInt(MIN_INT64_STR);
_JSBIConstants.MAX_UINT64 = JSBI.BigInt(MAX_UINT64_STR);
_JSBIConstants.MIN_UINT64 = JSBI.BigInt(MIN_UINT64_STR);

return _JSBIConstants;
}

const _BigIntConstants = {};

function _getBigIntConstants () {
if (Object.keys(_BigIntConstants).length !== 0) {
return _BigIntConstants;
}

_BigIntConstants.MAX_INT64 = BigInt(MAX_INT64_STR);
_BigIntConstants.MIN_INT64 = BigInt(MIN_INT64_STR);
_BigIntConstants.MAX_UINT64 = BigInt(MAX_UINT64_STR);
_BigIntConstants.MIN_UINT64 = BigInt(MIN_UINT64_STR);

return _BigIntConstants;
}

module.exports = {
MAX_INT64_STR: '9223372036854775807',
MIN_INT64_STR: '-9223372036854775807',
MAX_UINT64_STR: '18446744073709551615',
MIN_UINT64_STR: '0',
MAX_INT64_STR: MAX_INT64_STR,
MIN_INT64_STR: MIN_INT64_STR,
MAX_UINT64_STR: MAX_UINT64_STR,
MIN_UINT64_STR: MIN_UINT64_STR,

NameFlag: NameFlag,
RequestNameReply: RequestNameReply,
Expand Down Expand Up @@ -256,5 +293,7 @@ module.exports = {
be: 66
},
messageSignature: 'yyyyuua(yv)',
defaultAuthMethods: ['EXTERNAL', 'DBUS_COOKIE_SHA1', 'ANONYMOUS']
defaultAuthMethods: ['EXTERNAL', 'DBUS_COOKIE_SHA1', 'ANONYMOUS'],
_getJSBIConstants: _getJSBIConstants,
_getBigIntConstants: _getBigIntConstants
};
65 changes: 45 additions & 20 deletions lib/marshallers.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
const Buffer = require('safe-buffer').Buffer;
const align = require('./align').align;
const { parseSignature } = require('../lib/signature');
const JSBI = require('jsbi');
const Long = require('long');
const { getBigIntCompat } = require('./library-options');
const JSBI = require('jsbi');

const {
MAX_INT64_STR, MIN_INT64_STR,
MAX_UINT64_STR, MIN_UINT64_STR
_getJSBIConstants, _getBigIntConstants
} = require('./constants');

/*
Expand Down Expand Up @@ -184,10 +184,9 @@ var MakeSimpleMarshaller = function (signature) {
};
marshaller.marshall = function (ps, data) {
data = this.check(data);
const long = Long.fromString(data.toString(), true);
align(ps, 8);
ps.word32le(long.low);
ps.word32le(long.high);
ps.word32le(data.low);
ps.word32le(data.high);
ps._offset += 8;
};
break;
Expand All @@ -198,10 +197,9 @@ var MakeSimpleMarshaller = function (signature) {
};
marshaller.marshall = function (ps, data) {
data = this.check(data);
const long = Long.fromString(data.toString(), false);
align(ps, 8);
ps.word32le(long.low);
ps.word32le(long.high);
ps.word32le(data.low);
ps.word32le(data.high);
ps._offset += 8;
};
break;
Expand Down Expand Up @@ -251,17 +249,10 @@ var checkBoolean = function (data) {
if (!(typeof data === 'boolean' || data === 0 || data === 1)) { throw new Error(`Data: ${data} was not of type boolean`); }
};

const MAX_INT64 = JSBI.BigInt(MAX_INT64_STR);
const MIN_INT64 = JSBI.BigInt(MIN_INT64_STR);
const MAX_UINT64 = JSBI.BigInt(MAX_UINT64_STR);
const MIN_UINT64 = JSBI.BigInt(MIN_UINT64_STR);
const checkJSBILong = function (data, signed) {
const { MAX_INT64, MIN_INT64, MAX_UINT64, MIN_UINT64 } = _getJSBIConstants();

var checkLong = function (data, signed) {
if (typeof data === 'bigint') {
data = JSBI.BigInt(data.toString());
} else {
data = JSBI.BigInt(data);
}
data = JSBI.BigInt(data.toString());

if (signed) {
if (JSBI.greaterThan(data, MAX_INT64)) {
Expand All @@ -277,5 +268,39 @@ var checkLong = function (data, signed) {
}
}

return data;
return Long.fromString(data.toString(), true);
};

const checkBigIntLong = function (data, signed) {
const { MAX_INT64, MIN_INT64, MAX_UINT64, MIN_UINT64 } = _getBigIntConstants();

if (typeof data !== 'bigint') {
data = BigInt(data.toString());
}

if (signed) {
if (data > MAX_INT64) {
throw new Error('data was out of range (greater than max int64)');
} else if (data < MIN_INT64) {
throw new Error('data was out of range (less than min int64)');
}
} else {
if (data > MAX_UINT64) {
throw new Error('data was out of range (greater than max uint64)');
} else if (data < MIN_UINT64) {
throw new Error('data was out of range (less than min uint64)');
}
}

return Long.fromString(data.toString(), true);
};

var checkLong = function (data, signed) {
const compat = getBigIntCompat();

if (compat) {
return checkJSBILong(data, signed);
} else {
return checkBigIntLong(data, signed);
}
};
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"unit": "jest ./test/*.test.js",
"test": "dbus-run-session -- jest",
"doc": "jsdoc --verbose -c jsdoc.conf --readme README.md -r lib index.js -d doc",
"format": "cd lib && semistandard --fix && cd ../test && semistandard --env jest --parser babel-eslint --global BigInt --fix"
"format": "cd lib && semistandard --global BigInt --fix && cd ../test && semistandard --env jest --parser babel-eslint --global BigInt --fix"
},
"jest": {
"testEnvironment": "node",
Expand Down
35 changes: 28 additions & 7 deletions test/integration/long-compat.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,9 @@ const {
} = dbus.interface;

const {
MAX_INT64_STR, MIN_INT64_STR,
MAX_UINT64_STR, MIN_UINT64_STR
_getJSBIConstants
} = require('../../lib/constants');

const MAX_INT64 = JSBI.BigInt(MAX_INT64_STR);
const MIN_INT64 = JSBI.BigInt(MIN_INT64_STR);
const MAX_UINT64 = JSBI.BigInt(MAX_UINT64_STR);
const MIN_UINT64 = JSBI.BigInt(MIN_UINT64_STR);

const TEST_NAME = 'org.test.long_compat';
const TEST_PATH = '/org/test/path';
const TEST_IFACE = 'org.test.iface';
Expand Down Expand Up @@ -59,6 +53,7 @@ afterAll(() => {
});

test('test long type works correctly in compatibility mode', async () => {
const { MAX_INT64, MIN_INT64, MAX_UINT64, MIN_UINT64 } = _getJSBIConstants();
const object = await bus.getProxyObject(TEST_NAME, TEST_PATH);
const test = object.getInterface(TEST_IFACE);

Expand All @@ -81,21 +76,47 @@ test('test long type works correctly in compatibility mode', async () => {
expect(result.prototype).toEqual(JSBI.BigInt.prototype);
expect(JSBI.equal(result, what)).toEqual(true);

expect((async () => {
result = await test.EchoSigned(JSBI.add(what, JSBI.BigInt(1)));
return result.toString();
})()).rejects.toThrow();

// int64 min
what = MIN_INT64;
result = await test.EchoSigned(what);
expect(result.prototype).toEqual(JSBI.BigInt.prototype);
expect(JSBI.equal(result, what)).toEqual(true);

await expect((async () => {
result = await test.EchoSigned(JSBI.subtract(what, JSBI.BigInt(1)));
return result.toString();
})()).rejects.toThrow();

// uint64 max
what = MAX_UINT64;
result = await test.EchoUnsigned(what);
expect(result.prototype).toEqual(JSBI.BigInt.prototype);
expect(JSBI.equal(result, what)).toEqual(true);

await expect((async () => {
result = await test.EchoUnsigned(JSBI.add(what, JSBI.BigInt(1)));
return result.toString();
})()).rejects.toThrow();

// uint64 min
what = MIN_UINT64;
result = await test.EchoUnsigned(what);
expect(result.prototype).toEqual(JSBI.BigInt.prototype);
expect(JSBI.equal(result, what)).toEqual(true);

await expect((async () => {
result = await test.EchoUnsigned(JSBI.subtract(what, JSBI.BigInt(1)));
return result.toString();
})()).rejects.toThrow();

// int conversion
what = 500;
result = await test.EchoUnsigned(what);
expect(result.prototype).toEqual(JSBI.BigInt.prototype);
expect(JSBI.equal(result, JSBI.BigInt(what))).toEqual(true);
});
32 changes: 26 additions & 6 deletions test/integration/long.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,20 @@ if (typeof BigInt !== 'function') {
}

const dbus = require('../../');
const DBusError = dbus.DBusError;

const {
Interface, method
} = dbus.interface;

const {
MAX_INT64_STR, MIN_INT64_STR,
MAX_UINT64_STR, MIN_UINT64_STR
_getBigIntConstants
} = require('../../lib/constants');

const TEST_NAME = 'org.test.long';
const TEST_PATH = '/org/test/path';
const TEST_IFACE = 'org.test.iface';
const TEST_ERROR_PATH = 'org.test.name.error';

const bus = dbus.sessionBus();
bus.on('error', (err) => {
Expand All @@ -30,11 +31,17 @@ bus.on('error', (err) => {
class LongInterface extends Interface {
@method({ inSignature: 'x', outSignature: 'x' })
EchoSigned (what) {
if (typeof what !== 'bigint') {
throw new DBusError(TEST_ERROR_PATH, 'interface with long expected a BigInt for type x');
}
return what;
}

@method({ inSignature: 't', outSignature: 't' })
EchoUnsigned (what) {
if (typeof what !== 'bigint') {
throw new DBusError(TEST_ERROR_PATH, 'interface with long expected a BigInt for type t');
}
return what;
}
}
Expand All @@ -51,10 +58,7 @@ afterAll(() => {
});

testIfHasBigInt('test long type works correctly', async () => {
const MAX_INT64 = BigInt(MAX_INT64_STR);
const MIN_INT64 = BigInt(MIN_INT64_STR);
const MAX_UINT64 = BigInt(MAX_UINT64_STR);
const MIN_UINT64 = BigInt(MIN_UINT64_STR);
const { MAX_INT64, MIN_INT64, MAX_UINT64, MIN_UINT64 } = _getBigIntConstants();

const object = await bus.getProxyObject(TEST_NAME, TEST_PATH);
const test = object.getInterface(TEST_IFACE);
Expand All @@ -76,18 +80,34 @@ testIfHasBigInt('test long type works correctly', async () => {
result = await test.EchoSigned(what);
expect(result === what).toEqual(true);

expect((async () => {
return await test.EchoSigned(what + 1n);
})()).rejects.toThrow();

// int64 min
what = MIN_INT64;
result = await test.EchoSigned(what);
expect(result === what).toEqual(true);

expect((async () => {
return await test.EchoSigned(what - 1n);
})()).rejects.toThrow();

// uint64 max
what = MAX_UINT64;
result = await test.EchoUnsigned(what);
expect(result === what).toEqual(true);

expect((async () => {
return await test.EchoUnsigned(what + 1n);
})()).rejects.toThrow();

// uint64 min
what = MIN_UINT64;
result = await test.EchoUnsigned(what);
expect(result === what).toEqual(true);

expect((async () => {
return await test.EchoUnsigned(what - 1n);
})()).rejects.toThrow();
});

0 comments on commit f1e2b4a

Please sign in to comment.