From be7afede32e290f77e947ac911d16e6489318dd9 Mon Sep 17 00:00:00 2001 From: Lukas Taegert-Atkinson Date: Sat, 5 Jan 2019 12:34:11 +0100 Subject: [PATCH] Treat bigints as unknown for now on all systems to avoid accidentally (#2640) passing them to Math.pow or having "null" wrongly as a literal value --- package-lock.json | 6 ++++++ package.json | 1 + src/ast/nodes/BinaryExpression.ts | 3 ++- src/ast/nodes/Literal.ts | 10 +++++++--- test/form/samples/big-int/_config.js | 8 ++++++++ test/form/samples/big-int/_expected.js | 20 ++++++++++++++++++++ test/form/samples/big-int/main.js | 18 ++++++++++++++++++ 7 files changed, 62 insertions(+), 4 deletions(-) create mode 100644 test/form/samples/big-int/_config.js create mode 100644 test/form/samples/big-int/_expected.js create mode 100644 test/form/samples/big-int/main.js diff --git a/package-lock.json b/package-lock.json index 0ebec701df0..5ab0a91da24 100644 --- a/package-lock.json +++ b/package-lock.json @@ -159,6 +159,12 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.0.4.tgz", "integrity": "sha512-VY4i5EKSKkofY2I+6QLTbTTN/UvEQPCo6eiwzzSaSWfpaDhOmStMCMod6wmuPciNq+XS0faCglFu2lHZpdHUtg==" }, + "acorn-bigint": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/acorn-bigint/-/acorn-bigint-0.3.1.tgz", + "integrity": "sha512-WT9LheDC4/d/sD/jgC6L5UMq4U9X3KNMy0JrXp/MdJL83ZqcuPQuMkj50beOX0dMub8IoZUYycfN7bIVZuU5zg==", + "dev": true + }, "acorn-dynamic-import": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/acorn-dynamic-import/-/acorn-dynamic-import-4.0.0.tgz", diff --git a/package.json b/package.json index f7b1b369a9f..d530760e2a8 100644 --- a/package.json +++ b/package.json @@ -66,6 +66,7 @@ "@types/chokidar": "^1.7.5", "@types/minimist": "^1.2.0", "@types/pretty-ms": "^3.0.0", + "acorn-bigint": "^0.3.1", "acorn-dynamic-import": "^4.0.0", "acorn-import-meta": "^0.3.0", "acorn-jsx": "^5.0.1", diff --git a/src/ast/nodes/BinaryExpression.ts b/src/ast/nodes/BinaryExpression.ts index 759f836d0a2..ccef28f47da 100644 --- a/src/ast/nodes/BinaryExpression.ts +++ b/src/ast/nodes/BinaryExpression.ts @@ -28,7 +28,8 @@ const binaryOperators: { '|': (left: any, right: any) => left | right, '^': (left: any, right: any) => left ^ right, '&': (left: any, right: any) => left & right, - '**': (left: any, right: any) => Math.pow(left, right), + // At the moment, "**" will be transpiled to Math.pow + '**': (left: any, right: any) => left ** right, in: () => UNKNOWN_VALUE, instanceof: () => UNKNOWN_VALUE }; diff --git a/src/ast/nodes/Literal.ts b/src/ast/nodes/Literal.ts index ed94f374af9..77670b493fe 100644 --- a/src/ast/nodes/Literal.ts +++ b/src/ast/nodes/Literal.ts @@ -28,11 +28,15 @@ export default class Literal extends NodeBase { private members: { [key: string]: MemberDescription }; getLiteralValueAtPath(path: ObjectPath): LiteralValueOrUnknown { - if (path.length > 0) { + if ( + path.length > 0 || + // unknown literals such as bigints can also be null but do not start with an "n" + (this.value === null && this.context.code.charCodeAt(this.start) !== 110) || + typeof this.value === 'bigint' + ) { return UNKNOWN_VALUE; } - // not sure why we need this type cast here - return this.value; + return this.value as any; } getReturnExpressionWhenCalledAtPath(path: ObjectPath) { diff --git a/test/form/samples/big-int/_config.js b/test/form/samples/big-int/_config.js new file mode 100644 index 00000000000..80bcfbcb518 --- /dev/null +++ b/test/form/samples/big-int/_config.js @@ -0,0 +1,8 @@ +const bigInt = require('acorn-bigint'); + +module.exports = { + description: 'supports bigint via acorn plugin', + options: { + acornInjectPlugins: [bigInt] + } +}; diff --git a/test/form/samples/big-int/_expected.js b/test/form/samples/big-int/_expected.js new file mode 100644 index 00000000000..88a90aaf59d --- /dev/null +++ b/test/form/samples/big-int/_expected.js @@ -0,0 +1,20 @@ +if (1n > 0) { + console.log('ok'); +} + +if (1n + 1n > 0) { + console.log('ok'); +} + +if (1n ** 1n > 0) { + console.log('ok'); +} + +const max = 2n**64n; +const min = -max; + +function isSafe (int) { + return min<=int && int<=max; +} + +export default isSafe; diff --git a/test/form/samples/big-int/main.js b/test/form/samples/big-int/main.js new file mode 100644 index 00000000000..cff26413d9a --- /dev/null +++ b/test/form/samples/big-int/main.js @@ -0,0 +1,18 @@ +if (1n > 0) { + console.log('ok'); +} + +if (1n + 1n > 0) { + console.log('ok'); +} + +if (1n ** 1n > 0) { + console.log('ok'); +} + +const max = 2n**64n; +const min = -max; + +export default function isSafe (int) { + return min<=int && int<=max; +};