-
-
Notifications
You must be signed in to change notification settings - Fork 569
Align JS-side AST with standard for TypeScript #9705
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I think you should target TS-ESLint for anything non supported by acorn, this will simplify the setup. JSX is small enough so that it will probably not conflict, but today most JSX code is TSX so IMO I think you can avoid the intermediary step. |
#9774 implements a TS conformance suite. Continuing the conversation from that PR about current state of our conformance... @hi-ogawa said:
Oh dear! Well, we had a similar result when we started on ESTree conformance, and within a few days we were at 99%. Maybe it'll be the same this time, inshallah. But...
In The order of keys doesn't really matter. What does matter is that it's consistent, to make operating on the objects in JS code efficient, as consistent object shapes allow JS engines to monomorphize functions that operate on those objects. The other advantage of testing for correct field order is that conformance tests can compare the JSON produced by our serializer directly to the snapshotted JSON, with a simple string comparison. This is much faster than using I can see 2 possible ways forward:
Perhaps (1) is a good place to start, and then we do (2) later on?
That's problematic. We could match that behavior in raw transfer without any perf hit, but obviously we can't when transferring the AST via JSON. We'd have to add a "fixup" pass on JS side to convert I think we need to keep the JSON-based transfer method alive for the foreseeable future. Raw transfer is experimental, and quite possible it has show-stopper bugs. We've already found it doesn't work on Node 20 or Bun, and we've not got it working on WASM yet. I would also be loathe to remove empty TS-specific fields entirely in JS-side AST. That'd be a big perf hit for the consumer, as it'd result in variable object shapes. I'd suggest the best starting point on this one is to modify the AST in But does |
@hi-ogawa Do you have write access to |
Part of #9705 Requires oxc-project/acorn-test262#6 Current result `Positive Passed: 32/10725 (0.30%)` 😢 What I observed from a few diffs I looked at: - typescript-eslint parser's field ordering is not a super set of acorn (maybe keys are ordered alphabetically) - example: `ClassDeclaration` - typescript-eslint https://ast-explorer.dev/#eNolyDEKgDAMBdCrlD/rBTyIOGQJJUOlpqUpgpTe3YjrG8jYcPLNFluqHQuqQ3+q/LCK5aSfR/eY2SwcYUxSp+I0SEMgSLx4l2apKGFzyNzFOoF0Yr7njiIU - abstract, body, declare, decorators, id, implements, superClass, superTypeArguments, typeParameters, - acorn https://ast-explorer.dev/#eNolyTEKwzAMRuGrmH/OCXKOUjpoEaqGFMcyllMIxnePQrbH9wYyVvz4zy5tqx0LagCLtRIt0ZLZPX3SmHSTBQ0qKRFUdn5r880KYQ3I3NU7YXm+29FEX2fVZ+/2PXI0lYl5ATuZJ1U= - id, superClass, body - typescript-eslint parser uses `undefined` instead of `null` for optional ts-specific field - example: `ClassDeclaration.typeParameters` - https://ast-explorer.dev/#eNolyDEKgDAMBdCrlD/rBTyIOGQJJUOlpqUpgpTe3YjrG8jYcPLNFluqHQuqQ3+q/LCK5aSfR/eY2SwcYUxSp+I0SEMgSLx4l2apKGFzyNzFOoF0Yr7njiIU - spec https://github.com/typescript-eslint/typescript-eslint/blob/2224f12ff05b59c5a459291fe93fc8099221089d/packages/ast-spec/src/base/ClassBase.ts#L62
@overlookmotel Yes, I saw a green merge button myself, so I should be able to push it. 👍 |
You will have pre-processing to do anyway to convert TS-ESLint location to start/end. You could also do the null/undefined change during that process. |
Just to clarify one point:
I mean alter conformance tester for TypeScript only. We have succeeded in getting field order aligned with Acorn (and I made some PRs on Acorn acornjs/acorn#1347 acornjs/acorn#1346 to make Acorn align with us!), so would be ideal not to accidentally regress that. |
AST of ts-eslint should be 100% aligned with estree (extended), but there is sometimes differences when new js features are added (stage 3) and there is small period of time where AST may differ
yes to my knowledge there is few cases where https://github.com/estree/estree/blob/master/es2015.md#expressions eg. [,2]
/// elements: [null, Literal] additionally ts-eslint adds empty array's and defaults "flags" to |
I'm going to do this part now. |
I'm thinking about this, but to reorder this, we need to know acorn's order in js script of acorn-test262. Is there any easy-to-use format of estree spec providing this data? Either generating our own from ast tools or somehow extracting it from markdown https://github.com/estree/estree or dts https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/estree/index.d.ts? For now I went with 2st option of normalizing oxc output #9813. |
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
#9813) Part of #9705 This doesn't magically improve passes, but it makes it easier to digest mismatch diff. <details><summary>tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff</summary> ```diff @@ -20,12 +20,12 @@ "type": "Identifier", "start": 6, "end": 10, - "decorators": [], - "name": "Cell", - "optional": false + "name": "Cell" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -41,6 +41,7 @@ "type": "PropertyDefinition", "start": 33, "end": 49, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -49,9 +50,7 @@ "type": "Identifier", "start": 33, "end": 39, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" }, "optional": false, "override": false, @@ -77,12 +76,12 @@ "type": "Identifier", "start": 22, "end": 26, - "decorators": [], - "name": "Ship", - "optional": false + "name": "Ship" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null }, { "type": "ClassDeclaration", @@ -98,6 +97,7 @@ "type": "PropertyDefinition", "start": 71, "end": 85, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -106,9 +106,7 @@ "type": "Identifier", "start": 71, "end": 76, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" }, "optional": false, "override": false, @@ -130,10 +128,9 @@ "type": "Identifier", "start": 78, "end": 82, - "decorators": [], - "name": "Ship", - "optional": false - } + "name": "Ship" + }, + "typeParameters": null } } }, @@ -143,6 +140,7 @@ "type": "PropertyDefinition", "start": 90, "end": 104, + "accessibility": null, "computed": false, "declare": false, "decorators": [], @@ -151,9 +149,7 @@ "type": "Identifier", "start": 90, "end": 95, - "decorators": [], - "name": "cells", - "optional": false + "name": "cells" }, "optional": false, "override": false, @@ -175,10 +171,9 @@ "type": "Identifier", "start": 97, "end": 101, - "decorators": [], - "name": "Cell", - "optional": false - } + "name": "Cell" + }, + "typeParameters": null } } }, @@ -195,9 +190,7 @@ "type": "Identifier", "start": 118, "end": 130, - "decorators": [], - "name": "allShipsSunk", - "optional": false + "name": "allShipsSunk" }, "kind": "method", "optional": false, @@ -245,18 +238,14 @@ "type": "Identifier", "start": 191, "end": 194, - "decorators": [], - "name": "val", - "optional": false + "name": "val" }, "optional": false, "property": { "type": "Identifier", "start": 195, "end": 201, - "decorators": [], - "name": "isSunk", - "optional": false + "name": "isSunk" } } } @@ -271,11 +260,18 @@ "type": "Identifier", "start": 177, "end": 180, + "accessibility": null, "decorators": [], "name": "val", - "optional": false + "optional": false, + "override": false, + "readonly": false, + "typeAnnotation": null } - ] + ], + "returnType": null, + "thisParam": null, + "typeParameters": null } ], "callee": { @@ -298,9 +294,7 @@ "type": "Identifier", "start": 155, "end": 160, - "decorators": [], - "name": "ships", - "optional": false + "name": "ships" } }, "optional": false, @@ -308,12 +302,11 @@ "type": "Identifier", "start": 161, "end": 166, - "decorators": [], - "name": "every", - "optional": false + "name": "every" } }, - "optional": false + "optional": false, + "typeParameters": null } } ] @@ -322,7 +315,10 @@ "expression": false, "generator": false, "id": null, - "params": [] + "params": [], + "returnType": null, + "thisParam": null, + "typeParameters": null } } ] @@ -333,12 +329,12 @@ "type": "Identifier", "start": 59, "end": 64, - "decorators": [], - "name": "Board", - "optional": false + "name": "Board" }, - "implements": [], - "superClass": null + "implements": null, + "superClass": null, + "superTypeParameters": null, + "typeParameters": null } ], "sourceType": "script", ``` </details> It slows down a bit, but not so much?
This is now done. It actually affected very few types. #9820
OK great. Yes, probably easiest to get content aligned first before we worry about field order. Maybe the slow speed I noticed previously was from generating diffs for mismatches, rather than the
Yes. I've written something to output a list of types with their field order, based on Oxc's AST schema: overlookmotel/estree-field-orders branch + oxc-project/acorn-test262#11 We can do that whenever we're ready. Right now it's not perfect, because there are some types which exist in our AST which don't exist in TS-ESLint's (and probably vice-versa). |
Thanks for the feedback.
This is great to hear. Hopefully we won't have trouble with the ESTree-compatible and TSESLint-compatible ASTs diverging from each other (apart from, obviously, the TS AST having more fields e.g.
We do handle that one correctly. I think our best starting point is to treat
Interesting. Babel is a whole other thing, though. Babel's AST is quite different from ESTree, and we're not seeking to replicate its AST (though we might offer that as an option later on, if there's a demand for it). |
If anyone is interested in helping out this, here is my workflow to understand estree mismatches: # this runs full estree conformance and updates estree_xxx.snap
# but doesn't generate diff
cargo run -p oxc_coverage -- estree
# SAVE_DIFF=true to save diff files in tasks/coverage/acorn-test262-diff
# saving many files is too slow, so using --filter is recommended
SAVE_DIFF=true cargo run -p oxc_coverage -- estree --filter compiler/2dArray
# also you can use `just example parser` for any file to dump ast output
just example parser --estree test.ts And this is an example diff, which shows tasks/coverage/acorn-test262-diff/typescript/tests/cases/compiler/2dArrays.diff@@ -20,10 +20,7 @@
"type": "Identifier",
"start": 6,
"end": 10,
- "decorators": [],
- "name": "Cell",
- "optional": false,
- "typeAnnotation": null
+ "name": "Cell"
},
"implements": [],
"superClass": null,
@@ -53,10 +50,7 @@
"type": "Identifier",
"start": 33,
"end": 39,
- "decorators": [],
- "name": "isSunk",
- "optional": false,
- "typeAnnotation": null
+ "name": "isSunk"
},
"optional": false,
"override": false,
@@ -82,10 +76,7 @@
"type": "Identifier",
"start": 22,
"end": 26,
- "decorators": [],
- "name": "Ship",
- "optional": false,
- "typeAnnotation": null
+ "name": "Ship"
},
"implements": [],
"superClass": null,
@@ -115,10 +106,7 @@
"type": "Identifier",
"start": 71,
"end": 76,
- "decorators": [],
- "name": "ships",
- "optional": false,
- "typeAnnotation": null
+ "name": "ships"
},
"optional": false,
"override": false,
@@ -141,10 +129,7 @@
"type": "Identifier",
"start": 78,
"end": 82,
- "decorators": [],
- "name": "Ship",
- "optional": false,
- "typeAnnotation": null
+ "name": "Ship"
}
}
}
@@ -164,10 +149,7 @@
"type": "Identifier",
"start": 90,
"end": 95,
- "decorators": [],
- "name": "cells",
- "optional": false,
- "typeAnnotation": null
+ "name": "cells"
},
"optional": false,
"override": false,
@@ -190,10 +172,7 @@
"type": "Identifier",
"start": 97,
"end": 101,
- "decorators": [],
- "name": "Cell",
- "optional": false,
- "typeAnnotation": null
+ "name": "Cell"
}
}
}
@@ -211,10 +190,7 @@
"type": "Identifier",
"start": 118,
"end": 130,
- "decorators": [],
- "name": "allShipsSunk",
- "optional": false,
- "typeAnnotation": null
+ "name": "allShipsSunk"
},
"kind": "method",
"optional": false,
@@ -262,20 +238,14 @@
"type": "Identifier",
"start": 191,
"end": 194,
- "decorators": [],
- "name": "val",
- "optional": false,
- "typeAnnotation": null
+ "name": "val"
},
"optional": false,
"property": {
"type": "Identifier",
"start": 195,
"end": 201,
- "decorators": [],
- "name": "isSunk",
- "optional": false,
- "typeAnnotation": null
+ "name": "isSunk"
}
}
}
@@ -290,13 +260,17 @@
"type": "Identifier",
"start": 177,
"end": 180,
+ "accessibility": null,
"decorators": [],
"name": "val",
"optional": false,
+ "override": false,
+ "readonly": false,
"typeAnnotation": null
}
],
"returnType": null,
+ "thisParam": null,
"typeParameters": null
}
],
@@ -320,10 +294,7 @@
"type": "Identifier",
"start": 155,
"end": 160,
- "decorators": [],
- "name": "ships",
- "optional": false,
- "typeAnnotation": null
+ "name": "ships"
}
},
"optional": false,
@@ -331,10 +302,7 @@
"type": "Identifier",
"start": 161,
"end": 166,
- "decorators": [],
- "name": "every",
- "optional": false,
- "typeAnnotation": null
+ "name": "every"
}
},
"optional": false,
@@ -349,6 +317,7 @@
"id": null,
"params": [],
"returnType": null,
+ "thisParam": null,
"typeParameters": null
}
}
@@ -360,10 +329,7 @@
"type": "Identifier",
"start": 59,
"end": 64,
- "decorators": [],
- "name": "Board",
- "optional": false,
- "typeAnnotation": null
+ "name": "Board"
},
"implements": [],
"superClass": null, Original ts source file is found in |
I agree with that direction. Regarding TS ASTs, it feels difficult to determine the criteria for what is a parse error, how much incomplete AST is acceptable, etc seems vague...
Let's focus on these 35 cases! 🏁 (First, I'll recreate the TODO list later.) |
This comment has been minimized.
This comment has been minimized.
Related to #9705. Ignore errors from `serde_json` failing to parse JSON AST from `acorn-test262` TS-ESLint parser fixtures. These errors are due to deficiencies in `serde_json` and don't represent real problems. When we switch over to comparing ASTs as JSON strings (as we do in the Acorn and JSX tests), these problems should disappear.
Related to #9705. Skip tests in TS-ESTree conformance which do fail to parse, but fail because of bugs which are not related to ESTree serialization. We should eventually try to make these tests pass, but when we do, that'll show up in the parser conformance snapshots. So no need to repeat them in the ESTree conformance snapshot too - so we can more easily see what our ESTree-related problems are. Note: `typescript/tests/cases/conformance/jsx/jsxReactTestSuite.tsx` is *not* included in ignore list because that's not a fail in parser conformance (see #10578).
I don't think we need to worry about the "Expect to Parse" is a bit more complicated. Some of these should pass, but the bugs aren't related to ESTree conversion - cause is either in parser or in conformance tester. #10661 skips 5 of them (out of 6) where the case is already listed as a fail in parser conformance snapshot. I'm going to go through the mismatches now. These are the ones that are related to ESTree conversion, and that we do need to fix. |
Oh man these span mismatches are hard! I'm having trouble even figuring out which node is different, because ASTs produced by even a single statement are quite large with multiple nodes called I've opened an issue about The mismatches we have left: |
Great progress while I was away~! I'll also try to work on the remaining mismatches when I am available.
It seems that these rest mismatches are all the same root, which was described in #9705 (comment) 👉🏻 #10711 |
Part of #9705 Given code like this: ```ts function f(v): v is (1|2) {} ``` Currently, `TSTypePredicate`.`type_annotation`.span contains positions for `(` and `)`, but it should not when `preserveParens: false` for TS-ESTree. > https://playground.oxc.rs/#eNptj01vgzAMhv8KyqmVkAp03QfnqddN25VLCKaKFBxkJ2wV478vKR/bob7EVl4/ft9RKFGK1qNy2mLS7oZ9mQyJ5mSX/xT7ZJwqPByK48Pp8en5JcvvdFGQLZVvVWx1rLBCkQorylGQx/jwFZ38FqUjD6kwGp0oW2k4DKxsD+sPX7vamnVyJJFbS90inlLRS2KgiJTG2K8PcJ7wzTvWDZyXVOt6TxC0A7xLAuQ/Rjx/Y4R+OzFDnaQLBG8CuMjyU0ih2RrpoHkFZSTJyP+HUraBC9wiAsrawKf1pKCT/WwiSDqNutXrPWXRkTXn4D0uDUC15RB/Bk7TL/T+ijY= --- BTW, `TypePredicate`.`type_annotation` should be just `TSType` instead of `TSTypeAnnotation`(And generate extra `TSTypeAnnotation` for TS-ESTree)? https://github.com/oxc-project/oxc/blob/7d8efd872e9481821325d58c63f11fbd2ade2dc8/crates/oxc_ast/src/ast/ts.rs#L1123-L1135 --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Part of #9705, fixes #10578. Continuing to treat the following code as an error: ```ts // conformance/jsx/jsxParsingError1.tsx <div className={class1, class2}/> ``` also enables the following code to be parsed: ```ts // conformance/jsx/jsxReactTestSuite.tsx <Comp {...(z = { a: "1" }, z)} /> ``` by deferring the check to the semantic checker.
Amazing! It's required a herculean effort by many people to get us this far. I'll tackle field order in next few days, and convert the conformance tester to compare ASTs JSON-to-JSON, which I'm afraid will probably throw up more errors. I suspect in places we're generating JSON like: {
"type": "Identifier",
"name": "foo",
"optional": false,
"typeAnnotation": null,
"optional": true,
"typeAnnotation": null,
} But hopefully they won't be too hard to fix. ...and then I'll try to fix #9667. |
My thinking is that both Acorn and TS-ESLint's field orders are pretty arbitrary. TS-ESLint has fields in alphabetical order (but with some random exceptions to that rule!). Acorn's field ordering seems to follow little logic at all. The field order isn't important per se. What is important is that field order is consistent within our AST for nodes with the same type (i.e. So I now think that my insistence on aligning field order with Acorn was misguided. I'm planning on taking a different approach now: Order fields in visitation order, based on So, in short, our field order won't match either Acorn or TS-ESLint. But in my opinion, that's OK! I also intend to move That's less ideal from a human-readability perspective, but on positive side will allow removing the extra AST traversal to update spans to UTF-16. Updating spans can happen during serialization/raw deserialization pass instead. Removing the extra pass will give us a perf boost. But that requires the span fields to be last, as the most efficient way to do UTF-8 -> UTF-16 conversion is in ascending order of source position, in which case you can't calculate If anyone thinks this is unacceptable, please speak now! Side note: @leaysgur I see you archived https://github.com/leaysgur/oxc_estree_ts-ast-diff-viewer. Would you mind bringing it back? I used it to help with #10874 after updating to latest TS-ESLint. And field ordering will no doubt throw up more problems, which I'd like to use your excellent tool to help fix! |
The number of people that look up AST directly from the output is very low so I don't think this is an issue. AST explorer can re-roder fields and put them after |
I also think both directions make sense. No problem at all! — I’ve restored it. If you have any requests, feel free to let me know~! |
I added 2 scripts to leaysgur/oxc_estree_ts-ast-diff-viewer repo. (no view, just scripts) One is for:
I have made a PR for this, and no other problems seemed to be found. ✨ The other one compares with the order of their According to this script, it seems that there are mismatches in the following 32 nodes.
NOTE:
|
Part of #9705 With this PR, all AST nodes now have a consistent key order for each node type. (Checked by https://github.com/leaysgur/oxc_estree_ts-ast-diff-viewer/blob/main/scripts/verify-key-order-oxc.js) Except for: - `Literal`: `regex` and `bigint` keys - `TSModuleDeclaration`: `body` key is missing when `declare module "jq";`
This comment is a really good find. I have found 6 types where TS-ESLint's visitor keys are not in source code order:
I'm going to open an issue on TS-ESLint to fix them, and the fact that they have a comment saying "important: should be sorted in the order that they appear in the source code" will be really helpful in arguing the case. Unfortunately I'm still working on making sure there aren't any more cases before I open that issue, though. Am using #10887 to make sure that we have all our fields in the Rust types in source code order first! Currently we have a bug somewhere which I'm still trying to hunt down. |
eslint doesn't really care about order of properties in objects, and instead uses predefined visitor keys eslint visitor keys can be found in https://github.com/eslint/js/blob/main/packages/eslint-visitor-keys/lib/visitor-keys.js and ts-eslint just extends it with additional values
ref:
this comment refers to visitable fields, and not all fields can/should be visited, Note The iteration order for |
Uh oh!
There was an error while loading. Please reload this page.
Our AST on JS side (via oxc-parser NPM package) is now aligned with ESTree standard for JS syntax. We have conformance tests which ensure our AST is exactly the same as Acorn's AST for all Test262 test cases which Acorn can parse.
However, we do not yet guarantee that our AST for TypeScript types is aligned with any particular standard.
TS-ESLint's parser seems like the obvious target.
Achieving alignment
Recently there have been various PRs to align parts of the AST with TS-ESLint.
In my opinion, it'd be preferable if we took a more systematic approach, using a conformance suite. This will ensure:
This methodology proved successful while working on ESTree comatibility. Once we had the conformance suite working, we got to 99% passing within a few days!
I suggest we adopt same approach as I've outlined in #9703, with the target snapshots generated in and committed to
acorn-test262
repo. We can:How
Wherever possible, it's preferable to use the DSL (domain specific language) provided by
#[estree]
attributes on AST types to control how the AST gets converted e.g.#[estree(flatten)]
,#[estree(rename = "...")]
,#[estree(append_to = "...")]
.We can also use custom converters
#[estree(via = ...)]
where necessary, but the less we have to resort to that, the better.Conflicts between ESTree and TS-ESLint
It's possible that we'll run into cases where Acorn and TS-ESLint produce a different AST for some JS syntax. If so, that'll be problematic. Ideally we want a single AST shape which is compatible with both ESTree and TS-ESLint.
If we do find such cases, I suggest that we just skip them initially. Once we have everything else passing, we can see how broad a problem this is, and figure out how best to deal with it.
Raw transfer
I suggest that in the inital alignment effort, we don't worry about raw transfer.
Let's only adapt the AST that Oxc generates as JSON via
ESTree
trait. This will be simpler to do, and will get us to the finish line faster.Only once we have all the tests passing, we can then work on getting the AST generated by raw transfer aligned too. This is generally much easier once you have a working
ESTree
impl to translate from.JSX
See #9703. I suggest we do JSX first before TS.
The text was updated successfully, but these errors were encountered: