esprima icon indicating copy to clipboard operation
esprima copied to clipboard

ES2020 Feature: BigInt

Open JosephPecoraro opened this issue 6 years ago • 8 comments

Syntax:

New NumericLiteral syntax with a n suffix. Only decimal numbers with a suffix are valid. LegacyOctal or leading zeros are not valid.

123n

Grammar changes are to NumericLiteral. Basically allowing the BigInt n suffix on modern binary, octal, and hex numbers, or non-legacy-octal decimal literals.

  NumericLiteral::
      LegacyOctalIntegerLiteral
      DecimalLiteral
+     DecimalIntegerLiteral BigIntLiteralSuffix
+     NumericLiteralBase
+     NumericLiteralBase BigIntLiteralSuffix
-     BinaryIntegerLiteral
-     OctalIntegerLiteral
-     HexIntegerLiteral
 
+ NumericLiteralBase::
+     BinaryIntegerLiteral
+     OctalIntegerLiteral
+     HexIntegerLiteral
+ 
+ BigIntLiteralSuffix  ::  n

Spec:

TC39: https://github.com/tc39/proposal-bigint https://tc39.es/proposal-bigint/

ESTree: https://github.com/estree/estree/blob/master/es2020.md


Literal

extend interface Literal <: Expression {
    type: "Literal";
    value: string | boolean | null | number | RegExp | bigint;
}
  • value property can be a BigInt value to represent BigInt literals such as 100n.

BigIntLiteral

interface BigIntLiteral <: Literal {
  bigint: string;
}
  • bigint property is the string representation of the BigInt value. It doesn't include the suffix n.
  • In environments that don't support BigInt values, value property will be null as the BigInt value can't be represented natively.

Additional considerations

  • Supported in Chrome and Firefox. Experimental in WebKit
  • Supported in Node

Remaining Tasks:

  • [ ] Add new BigIntLiteral node (nodes.ts, docs/syntax-tree-format.md)
  • [ ] Update Scanner (scanner.ts changes for n numeric suffix)
  • [ ] Update Parser (parser.ts to create a BigIntLiteral node for those numeric literals)
  • [ ] Provide Unit Tests and Coverage (see below)
  • [ ] Update test262 (~test262.git#2ee3864136) / test262-stream (~1.3.0) (note that test.attrs.negative.phase === 'early' should also now handle test.attrs.negative.phase === 'parse')
  • [ ] Handle runtimes where globalThis.BigInt is available and not available (may require updating typescript to ~3.4

Test Cases

Valid:

0n
123n
0x123n
0o123n
0b101n

Invalid:

1.1n
1e1n
01n // Leading Zero (legacy hex) does not allow it
00n // Leading Zero does not allow it
09n // Leading Zero does not allow it

JosephPecoraro avatar Aug 15 '19 00:08 JosephPecoraro

The tricky part about this is whether or not globalThis.BigInt is available.

If it is, then the BigIntLiteral's value property is a BigInt value. If it is not, then the BitIntLiteral's value property is null.

Test coverage for that may require istanbul comments along the lines of:

const value = globalThis.BigInt ? globalThis.BigInt(string) : /* istanbul ignore next */ null;
return {
    type: Token.NumericLiteral,
    value: value,
    ...
};

Given unit tests run with a node where BigInt will be available but some browsers may not have it available.

JosephPecoraro avatar Aug 15 '19 00:08 JosephPecoraro

I've created a pull for this in my fork: https://github.com/node-projects/esprima-next/pull/12

jogibear9988 avatar Jun 21 '21 20:06 jogibear9988

"dependencies": { "esprima": "^4.0.1", }
In my pakage.json,I use esprima-version-4.0.1 , but it's error when parsing bigint code, such as "var x = 0x123n". How to use the new Feature about ES2020:BigInt?

famgy avatar Dec 14 '21 10:12 famgy

@famgy I've created a fork: esprima-next wich has support. https://github.com/node-projects/esprima-next

jogibear9988 avatar Dec 14 '21 12:12 jogibear9988

@famgy I've created a fork: esprima-next wich has support. https://github.com/node-projects/esprima-next "dependencies": { "@babel/core": "^7.16.5", "@babel/preset-env": "^7.16.5", "esprima-next": "^5.7.0" }

usage: var BABEL = require("@babel/core"), ESPRIMA = require("esprima-next") var esCode = BABEL.transform('var x = 0x123n', { presets: ["@babel/preset-env"] }).code

var astCode = ESPRIMA.parseScript(esCode)

But, It's Error :

Error: Line 3: Unexpected token ILLEGAL at e.constructError (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:20546) at e.createError (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:20765) at e.throwError (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:20888) at e.throwUnexpectedToken (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:122742) at e.scanHexLiteral (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:131016) at e.scanNumericLiteral (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:133188) at e.lex (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:139302) at e.nextToken (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:55026) at e.parseVariableDeclaration (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:91452) at e.parseVariableDeclarationList (E:\Projects\JavaScript\jsobfx-es2020\node_modules\esprima-next\dist\esprima.js:1:91724) { index: 28,

famgy avatar Dec 15 '21 02:12 famgy

I've been fixing issues with parsing on .NET side: https://github.com/sebastienros/esprima-dotnet/pull/214 , currently I haven't found any new problems with the current WIP version while integrating Jint with it.

lahma avatar Dec 15 '21 05:12 lahma

@famgy my fork is not an ES5 lib and more, so it should be loaded via "import".

jogibear9988 avatar Dec 15 '21 06:12 jogibear9988

After clone esprima-next, and run test: var ESPRIMA = require('.');

It's OK ,such as : var astCode = ESPRIMA.parseScript('var x = 123n', { tolerant: true })

It's Error, such as: var astCode = ESPRIMA.parseScript('var x = 0x123n', { tolerant: true })

Is it the result that "123n" is valid, but "0x123n" is invalid ?

famgy avatar Dec 15 '21 08:12 famgy