Skip to content

Commit

Permalink
Port babel-parser changes from 2019-09-06 to 2019-12-22 (#487)
Browse files Browse the repository at this point in the history
Fixes #483

cbd5a26e5 v7.6.0
🚫 Release only.

daf25af47 Fix typo in changelog (#10409)
🚫 Docs only.

4395c22f3 Miscellaneous perf tweak (#10421)
βœ… Ported one small optimization.

cb881e6b3 [parser] Report escapes in kws only if they won't be used as i… (#10455)
🚫 Not relevant for Sucrase since Sucrase doesn't do validation.

9c1ad0a9f [parser] Disallow static fields named `constructor` (#10461)
🚫 Validation-only change.

b7333ea97 added check to disallow super.private variable access and test case added (#10472)
🚫 Validation-only change.

3069747a8 Leave trailing comments after handling a possible trailing com… (#10445)
🚫 Only affects comments, which aren't relevant for Sucrase.

f339d2d03 [parser] Disallow numeric separator in unicode scape sequences (#10468)
🚫 Validation only.

69d00dc5b [parser] Invalid NonOctal Decimal (#10467)
🚫 Validation only.

b9cb4af95 v7.6.2
🚫 Release only.

6f3460c76 chore: add access: public to babel parser publish config (#10487)
🚫 package.json only.

0e9502685 [parser] Don't crash on comment after trailing comma after eli… (#10490)
βœ… Was already working, but I added a test anyway.

490798a26 [parser] Disallow numeric separators in legacy octal like inte… (#10493)
🚫 Validation only.

80d99b4d4 Do not allow member expressions to start async arrows (#10332)
🚫 Doesn't appear to affect current Sucrase code.

fa5057f9f Flow: interface identifier should be declared in the scope (#10220)
🚫 Scope-only change.

a219b6de7 Disallow await inside async arrow params (#10469)
🚫 Validation only, not relevant for Sucrase.

0856618ed perf: replace lookahead by lookaheadCharCode (#10371)
🚫 I'll hold off on this for now, but seems good to explore at some point.

b0acfb24d add scope to TSModuleDeclaration (#10119)
🚫 Scope only.

d329156eb v7.6.3
🚫 Release only.

34937f13d Trailing comma after rest - The final fix (#10491)
🚫 Looks like this is only for validation, so doesn't affect Sucrase.

a422ea64e v7.6.4
🚫 Release only.

06313a628 Allow duplicate __proto__ keys in patterns, simple case (#6705) (#10532)
🚫 Validation only.

5800fc97b [parser] Exception to 8 and 9 in tagged template (#10567)
🚫 Validation only.

095f28a91 fix: Exclude catch clause from let identifier error (#10559)
🚫 Doesn't apply to strict mode, Sucrase is always strict mode.

78cd63d9c Fix invalid test layout in @babel/parser
🚫 Test only.

b6ef9689b [parser] Parse only modifiers of actual methods (#10594)
🚫 Validation only.

1d1fab4ea [parser] Add support for private fields in TypeScript (#10483)
βœ… Already seems to be working (aside from validation), and I added a test.

4cd93ab5f [parser] Enable "exportNamespaceFrom" by default (#10521)
🚫 Already enabled in Sucrase.

38a306311 add assertions signature for TypeScript (#10543)
βœ… Implemented separately in Sucrase.

63f9a3c94 rename `assertsModifier` to `asserts` (#10613)
🚫 AST-only change.

143d15998 Create parser plugin "topLevelAwait" (#10449)
🚫 Sucrase already supports top-level await, and the ambiguities don't apply
since Sucrase assumes module code where await is reserved.

4b3a19ea9 fixed missing errors on assignment pattern in object expression (#10607)
🚫 Validation only.

ec3345bb5 Flow enums parsing (#10344)
🚫 For now I won't support Flow enums since it looks like the runtime semantics
aren't figured out yet.

d023e105b [TS] Parse calls with type args in optional chains (#10631)
βœ… This seems to already work, and I added a test.

87feda7c2 @babel/parser error recovery (#10363)
🚫 Big restructure, but I think doesn't have an effect on Sucrase since Sucrase
isn't interested in reporting detailed errors.

e9c1bce50 Add support for TS declare modifier on fields (#10545)
🚫 Filed #486 to track this issue.

97faa8395 v7.7.0
🚫 Release only.

2cd5ad0c8 fix typo: identifer -> identifier (#10647)
🚫 Docs only.

9082e68d6 Parse arrows with params annotations in conditional expressions (#10669)
🚫 Parsing edge case that shouldn't affect emit anyway, and the parsing code
works differently now in Sucrase.

35f4d1276 v7.7.2
🚫 Release only.

0287c0f02 Don't recover from "adjacent jsx elements" parser error (#10682)
🚫 Error recovery not relevant for Sucrase.

e315d65a7 v7.7.3
🚫 Release only.

4cb5e0a01 Allow TypeScript type assertions in array destructuring (#10592)
🚫 Already works in Sucrase.

d413a3078 Add `asserts this [is type]` parsing support (#10677)
βœ… Implemented in a simpler way in Sucrase.

a6d134804 Unify build step for ESLint packages (#10723)
🚫 Test only.

cfd26fdbf register ImportEqualsSpecifier to scope (#10710)
🚫 Scope code not relevant to Sucrase.

10213655b [parser] Allow optional async methods (#10582)
βœ… Same bug fix applied.

a502d8804 Fix some incorrect typeof parsing in flow (#10657)
🚫 Doesn't seem to affect Sucrase.

01d6d6dd3 Flow enums: fix enum body location (#10737)
🚫 Not supporting flow enums yet.

75767d87c v7.7.4
🚫 Release only.

5440ae1ca Correctly disambiguate / after async fuctions (#10475)
🚫 Fix wouldn't apply to Sucrase, and seems obscure enough to ignore and likely
wouldn't affect Sucrase output anyway.

d18afbd7c Allow tuple rest trailing comma (#10800)
βœ… Already works in Sucrase, and I added a test.

bb6cc6197 fix(optional chaining): Optional delete returns true with nullish base (#10806)
🚫 Test only.

c6e966cac [parser] Use scope flags to check arguments (#10801)
🚫 Validation only.

d04508e51 v7.7.5
🚫 Release only.

fb100eee4 @babel/eslint-parser: fix BigIntLiteral node to match ESTree spec (#10827)
🚫 Sucrase doesn't support ESTree parsing.

20e43ad10 validate parentheses in the left-hand side of assignment expressions (#10576)
🚫 Validation only.

5156d3ea0 Restore `@babel/parser` tests (#10854)
🚫 Test only.

7b54a9438 @babel/eslint-parser: fix ImportExpression node to match ESTree spec  (#10828)
🚫 Sucrase doesn't support ESTree parsing.

0b3f883ed Properly serialize non-json values in parser tests (#10858)
🚫 Test only.

12da0941c v7.7.7
🚫 Release only.

f651f22f9 fix: lost leading comment after named import (#10901)
🚫 Doesn't affect Sucrase.
  • Loading branch information
alangpierce authored Dec 25, 2019
1 parent ff0c26c commit 2498bcc
Show file tree
Hide file tree
Showing 9 changed files with 413 additions and 235 deletions.
1 change: 1 addition & 0 deletions generator/generateReadWordTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ const KEYWORDS = [
const CONTEXTUAL_KEYWORDS = [
"abstract",
"as",
"asserts",
"async",
"await",
"checks",
Expand Down
35 changes: 27 additions & 8 deletions src/parser/plugins/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -575,9 +575,9 @@ function tsIsUnambiguouslyStartOfFunctionType(): boolean {
function tsParseTypeOrTypePredicateAnnotation(returnToken: TokenType): void {
const oldIsType = pushTypeContext(0);
expect(returnToken);
tsParseTypePredicatePrefix();
// Regardless of whether we found an "is" token, there's now just a regular type in front of
// us.
tsParseTypePredicateOrAssertsPrefix();
// Regardless of whether we found an "asserts" or "is" token, there's now just a regular type in
// front of us.
tsParseType();
popTypeContext(oldIsType);
}
Expand All @@ -600,13 +600,32 @@ function tsTryParseType(): void {
}
}

function tsParseTypePredicatePrefix(): void {
function tsParseTypePredicateOrAssertsPrefix(): void {
const snapshot = state.snapshot();
parseIdentifier();
if (isContextual(ContextualKeyword._is) && !hasPrecedingLineBreak()) {
if (isContextual(ContextualKeyword._asserts) && !hasPrecedingLineBreak()) {
// Normally this is `asserts x is T`, but at this point, it might be `asserts is T` (a user-
// defined type guard on the `asserts` variable) or just a type called `asserts`.
next();
} else {
state.restoreFromSnapshot(snapshot);
if (isContextual(ContextualKeyword._is)) {
// If we see `asserts is`, then this must be of the form `asserts is T`, since
// `asserts is is T` isn't valid.
next();
} else if (tsIsIdentifier() || match(tt._this)) {
next();
expectContextual(ContextualKeyword._is);
} else {
// Regular type, so bail out and start type parsing from scratch.
state.restoreFromSnapshot(snapshot);
}
} else if (tsIsIdentifier() || match(tt._this)) {
// This is a regular identifier, which may or may not have "is" after it.
next();
if (isContextual(ContextualKeyword._is) && !hasPrecedingLineBreak()) {
next();
} else {
// Regular type, so bail out and start type parsing from scratch.
state.restoreFromSnapshot(snapshot);
}
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/parser/tokenizer/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,7 @@ function readToken_dot(): void {
return;
}

const next2 = input.charCodeAt(state.pos + 2);
if (nextChar === charCodes.dot && next2 === charCodes.dot) {
if (nextChar === charCodes.dot && input.charCodeAt(state.pos + 2) === charCodes.dot) {
state.pos += 3;
finishToken(tt.ellipsis);
} else {
Expand Down
1 change: 1 addition & 0 deletions src/parser/tokenizer/keywords.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export enum ContextualKeyword {
NONE,
_abstract,
_as,
_asserts,
_async,
_await,
_checks,
Expand Down
458 changes: 234 additions & 224 deletions src/parser/tokenizer/readWordTree.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/parser/traverser/statement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -744,6 +744,7 @@ function parseClassMemberWithIsStatic(

// The so-called parsed name would have been "async": get the real name.
parseClassPropertyName(classContextId);
parsePostMemberNameModifiers();
parseClassMethod(memberStart, false /* isConstructor */);
} else if (
(token.contextualKeyword === ContextualKeyword._get ||
Expand Down
14 changes: 14 additions & 0 deletions test/sucrase-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -859,4 +859,18 @@ describe("sucrase", () => {
{transforms: []},
);
});

it("handles comments after trailing comma after elision", () => {
assertResult(
`
function foo([foo, /* not used */, /* not used */]) {
}
`,
`
function foo([foo, /* not used */, /* not used */]) {
}
`,
{transforms: []},
);
});
});
133 changes: 133 additions & 0 deletions test/typescript-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,25 @@ describe("typescript transform", () => {
);
});

it("handles type predicates involving this", () => {
assertTypeScriptResult(
`
class A {
foo(): this is B {
return false;
}
}
`,
`"use strict";
class A {
foo() {
return false;
}
}
`,
);
});

it("export default functions with type parameters", () => {
assertTypeScriptResult(
`
Expand Down Expand Up @@ -1797,4 +1816,118 @@ describe("typescript transform", () => {
`,
);
});

it("allows private field syntax", () => {
assertTypeScriptResult(
`
class Foo {
readonly #x: number;
}
`,
`"use strict";
class Foo {
}
`,
);
});

it("allows assertion signature syntax", () => {
assertTypeScriptResult(
`
function assertIsDefined<T>(x: T): asserts x is NonNullable<T> {
if (x == null) throw "oh no";
}
`,
`"use strict";
function assertIsDefined(x) {
if (x == null) throw "oh no";
}
`,
);
});

it("allows assertion signature syntax using this", () => {
assertTypeScriptResult(
`
class Foo {
isBar(): asserts this is Foo {}
isBaz = (): asserts this is Foo => {}
}
`,
`"use strict";
class Foo {constructor() { Foo.prototype.__init.call(this); }
isBar() {}
__init() {this.isBaz = () => {}}
}
`,
);
});

it("does not get confused by a user-defined type guard on a variable called asserts", () => {
assertTypeScriptResult(
`
function checkIsDefined(asserts: any): asserts is NonNullable<T> {
return false;
}
`,
`"use strict";
function checkIsDefined(asserts) {
return false;
}
`,
);
});

it("does not get confused by a return type called asserts", () => {
assertTypeScriptResult(
`
function checkIsDefined(x: any): asserts {
return false;
}
`,
`"use strict";
function checkIsDefined(x) {
return false;
}
`,
);
});

it("correctly parses optional chain calls with type arguments", () => {
assertTypeScriptResult(
`
example.inner?.greet<string>()
`,
`"use strict";
example.inner?.greet()
`,
);
});

it("allows optional async methods", () => {
assertTypeScriptResult(
`
class A extends B {
async method?(val: string): Promise<void>;
}
`,
`"use strict";
class A extends B {
}
`,
);
});

it("handles trailing commas at the end of tuple type with rest", () => {
assertTypeScriptResult(
`
let x: [string, ...string[],]
`,
`"use strict";
let x
`,
);
});
});
2 changes: 1 addition & 1 deletion website/src/Constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ interface TransformInfo {

export const TRANSFORMS: Array<TransformInfo> = [
{name: "jsx", presetName: ["react", {development: true}]},
{name: "typescript", presetName: "typescript"},
{name: "typescript", presetName: ["typescript", {allowDeclareFields: true}]},
{name: "flow", presetName: "flow"},
{name: "imports", babelName: "transform-modules-commonjs"},
{name: "react-hot-loader", babelName: "react-hot-loader"},
Expand Down

0 comments on commit 2498bcc

Please sign in to comment.