@gi-tcg/gts-transpiler 0.6.2 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ function loosePlugin() {
70
70
  if (this.type.label === "name" || this.type.keyword) return super.parseIdent(liberal);
71
71
  else return this.createDummyIdentifier();
72
72
  };
73
- #proxiedThis = new Proxy(this, { get: (target, prop) => {
73
+ #proxiedThisTrapParseIdent = new Proxy(this, { get: (target, prop) => {
74
74
  if (prop === "parseIdent") return this._patchedParseIdent;
75
75
  const value = Reflect.get(target, prop);
76
76
  if (typeof value === "function") return value.bind(target);
@@ -83,7 +83,38 @@ function loosePlugin() {
83
83
  return this.finishNode(dummy, "Identifier");
84
84
  }
85
85
  parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit) {
86
- return super.parseSubscript.call(this.#proxiedThis, base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
86
+ return super.parseSubscript.call(this.#proxiedThisTrapParseIdent, base, startPos, startLoc, noCalls, maybeAsyncArrow, optionalChained, forInit);
87
+ }
88
+ #proxiedThisTrapEofToRbrace = new Proxy(this, { get: (target, prop) => {
89
+ if (prop === "type" && target.type === tokTypes.eof) return tokTypes.braceR;
90
+ const value = Reflect.get(target, prop);
91
+ if (typeof value === "function") return value.bind(target);
92
+ return value;
93
+ } });
94
+ parseBlock(createNewLexicalScope, node, exitStrict) {
95
+ return super.parseBlock.call(this.#proxiedThisTrapEofToRbrace, createNewLexicalScope, node, exitStrict);
96
+ }
97
+ parseClassStaticBlock(node) {
98
+ return super.parseClassStaticBlock.call(this.#proxiedThisTrapEofToRbrace, node);
99
+ }
100
+ parseSwitchStatement(node) {
101
+ return super.parseSwitchStatement.call(this.#proxiedThisTrapEofToRbrace, node);
102
+ }
103
+ parseStatement(context, topLevel, exports) {
104
+ const { start, startLoc, lastTokEnd, lastTokEndLoc } = this;
105
+ if (topLevel && this.eat(tokTypes.braceR)) {
106
+ const errorNode = this.startNodeAt(start, startLoc);
107
+ errorNode.error = "Unexpected token }";
108
+ return this.finishNode(errorNode, "ErrorStatement");
109
+ }
110
+ try {
111
+ return super.parseStatement(context, topLevel, exports);
112
+ } catch (e) {
113
+ const errorNode = this.startNodeAt(lastTokEnd, lastTokEndLoc);
114
+ errorNode.error = e?.message;
115
+ while (this.type !== tokTypes.eof && this.type !== tokTypes.semi && this.type !== tokTypes.braceR) this.next();
116
+ return this.finishNode(errorNode, "ErrorStatement");
117
+ }
87
118
  }
88
119
  };
89
120
  };
@@ -537,6 +568,11 @@ function parseLoose(input, options) {
537
568
  const ast = GtsParser.parse(input, {
538
569
  ecmaVersion: "latest",
539
570
  sourceType: "module",
571
+ allowImportExportEverywhere: true,
572
+ allowReturnOutsideFunction: true,
573
+ allowAwaitOutsideFunction: true,
574
+ allowSuperOutsideMethod: true,
575
+ checkPrivateFields: false,
540
576
  locations: true,
541
577
  ranges: true,
542
578
  onComment
@@ -1659,6 +1695,7 @@ function getPrintOptions(source, state) {
1659
1695
  source,
1660
1696
  isUntouched: (node) => {
1661
1697
  if (node.type === "Identifier" && node.isDummy) return false;
1698
+ if (node.type === "ErrorStatement") return false;
1662
1699
  if (state.attributeNameNodes.has(node)) return false;
1663
1700
  return state.sourceNodes.has(node);
1664
1701
  },
@@ -1689,8 +1726,17 @@ function getPrintOptions(source, state) {
1689
1726
  if (identifier.isDummy && identifier.range) {
1690
1727
  const text = state.lastArgNodes.has(identifier) ? "," : "";
1691
1728
  let firstNonWhiteSpaceIndex = context.source.slice(identifier.range[1]).search(/\S/);
1692
- const rangeEnd = firstNonWhiteSpaceIndex === -1 ? context.source.length : identifier.range[1] + firstNonWhiteSpaceIndex;
1693
- context.writeMapped(text, identifier.range[0], rangeEnd);
1729
+ if (firstNonWhiteSpaceIndex !== 0) {
1730
+ const rangeEnd = firstNonWhiteSpaceIndex === -1 ? context.source.length : identifier.range[1] + firstNonWhiteSpaceIndex;
1731
+ context.writeMapped(text, identifier.range[0], rangeEnd);
1732
+ } else {
1733
+ const rangeEnd = Math.min(node.range[0] + 1, context.source.length);
1734
+ context.createExtraMapping({
1735
+ start: identifier.range[0],
1736
+ end: rangeEnd
1737
+ }, context.generatedOffset, context.generatedOffset + 1, DEFAULT_VOLAR_MAPPING_DATA);
1738
+ context.write(text);
1739
+ }
1694
1740
  } else if (identifier.range && state.attributeNameNodes.has(identifier)) context.writeMapped(identifier.name, identifier.range[0], identifier.range[1], ATTRIBUTE_NAME_MAPPING_DATA);
1695
1741
  else defaultPrinters.Identifier(node, context);
1696
1742
  },
@@ -1740,6 +1786,16 @@ function getPrintOptions(source, state) {
1740
1786
  context.write(".");
1741
1787
  context.writeSource(node.whiteSpaceStart, node.whiteSpaceEnd);
1742
1788
  context.write(";");
1789
+ },
1790
+ ErrorStatement(node, context) {
1791
+ if (node.range) {
1792
+ context.writePreservedNode(node);
1793
+ const rangeEnd = Math.min(node.range[1] + 1, context.source.length);
1794
+ context.createExtraMapping({
1795
+ start: node.range[1],
1796
+ end: rangeEnd
1797
+ }, context.generatedOffset, context.generatedOffset + 1, VERIFICATION_ONLY_MAPPING_DATA);
1798
+ } else context.write(`((_: never) => 0)(${JSON.stringify(node.error ?? "Unknown error")});`);
1743
1799
  }
1744
1800
  },
1745
1801
  experimentalGetLeftParenSourceRange: (node) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gi-tcg/gts-transpiler",
3
- "version": "0.6.2",
3
+ "version": "0.6.3",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/piovium/gts.git"
@@ -59,6 +59,11 @@ export function parseLoose(
59
59
  const ast = GtsParser.parse(input, {
60
60
  ecmaVersion: "latest",
61
61
  sourceType: "module",
62
+ allowImportExportEverywhere: true,
63
+ allowReturnOutsideFunction: true,
64
+ allowAwaitOutsideFunction: true,
65
+ allowSuperOutsideMethod: true,
66
+ checkPrivateFields: false,
62
67
  locations: true,
63
68
  ranges: true,
64
69
  onComment,
@@ -15,7 +15,7 @@ export function loosePlugin() {
15
15
  return this.createDummyIdentifier();
16
16
  }
17
17
  };
18
- readonly #proxiedThis = new Proxy(this, {
18
+ readonly #proxiedThisTrapParseIdent = new Proxy(this, {
19
19
  get: (target, prop) => {
20
20
  if (prop === "parseIdent") {
21
21
  return this._patchedParseIdent;
@@ -48,7 +48,7 @@ export function loosePlugin() {
48
48
  forInit?: boolean | "await",
49
49
  ): AST.Expression {
50
50
  return super.parseSubscript.call(
51
- this.#proxiedThis,
51
+ this.#proxiedThisTrapParseIdent,
52
52
  base,
53
53
  startPos,
54
54
  startLoc,
@@ -58,6 +58,80 @@ export function loosePlugin() {
58
58
  forInit,
59
59
  );
60
60
  }
61
+
62
+ // Parsing block statements typically has:
63
+ // ```js
64
+ // while (this.type !== tokTypes.braceR) {
65
+ // this.parseStatement();
66
+ // }
67
+ // ```
68
+ // But what happens if the next token is EOF? Since we tolerate errors inside `parseStatement`,
69
+ // it can fall into an infinite loop. To avoid this, we use a proxy to trap `this.type`
70
+ // access and return a fake `braceR` when the current token is EOF.
71
+ readonly #proxiedThisTrapEofToRbrace = new Proxy(this, {
72
+ get: (target, prop) => {
73
+ if (prop === "type" && target.type === tokTypes.eof) {
74
+ return tokTypes.braceR;
75
+ }
76
+ const value = Reflect.get(target, prop);
77
+ if (typeof value === "function") {
78
+ return value.bind(target);
79
+ }
80
+ return value;
81
+ },
82
+ });
83
+
84
+ override parseBlock(
85
+ createNewLexicalScope?: boolean,
86
+ node?: AST.BlockStatement,
87
+ exitStrict?: boolean,
88
+ ): AST.BlockStatement {
89
+ return super.parseBlock.call(
90
+ this.#proxiedThisTrapEofToRbrace,
91
+ createNewLexicalScope,
92
+ node,
93
+ exitStrict,
94
+ );
95
+ }
96
+ override parseClassStaticBlock(node: AST.Node): AST.StaticBlock {
97
+ return super.parseClassStaticBlock.call(
98
+ this.#proxiedThisTrapEofToRbrace,
99
+ node,
100
+ );
101
+ }
102
+ override parseSwitchStatement(node: AST.Node): AST.SwitchStatement {
103
+ return super.parseSwitchStatement.call(
104
+ this.#proxiedThisTrapEofToRbrace,
105
+ node,
106
+ );
107
+ }
108
+
109
+ override parseStatement(
110
+ context?: string | null,
111
+ topLevel?: boolean,
112
+ exports?: AST.ExportSpecifier,
113
+ ): AST.ExpressionStatement | AST.Statement | AST.GTSDefineStatement {
114
+ const { start, startLoc, lastTokEnd, lastTokEndLoc } = this;
115
+ if (topLevel && this.eat(tokTypes.braceR)) {
116
+ const errorNode: any = this.startNodeAt(start, startLoc);
117
+ errorNode.error = "Unexpected token }";
118
+ return this.finishNode(errorNode, "ErrorStatement");
119
+ }
120
+ try {
121
+ return super.parseStatement(context, topLevel, exports);
122
+ } catch (e) {
123
+ const errorNode: any = this.startNodeAt(lastTokEnd, lastTokEndLoc);
124
+ errorNode.error = (e as Error)?.message;
125
+ while (
126
+ this.type !== tokTypes.eof &&
127
+ this.type !== tokTypes.semi &&
128
+ this.type !== tokTypes.braceR
129
+ ) {
130
+ this.next();
131
+ }
132
+ return this.finishNode(errorNode, "ErrorStatement");
133
+ }
134
+ }
61
135
  };
62
136
  };
63
137
  }
@@ -35,12 +35,15 @@ export function getPrintOptions(
35
35
  if (node.type === "Identifier" && (node as Identifier).isDummy) {
36
36
  return false;
37
37
  }
38
+ if ((node.type as string) === "ErrorStatement") {
39
+ return false;
40
+ }
38
41
  if (state.attributeNameNodes.has(node as Identifier | Literal)) {
39
42
  return false;
40
43
  }
41
44
  return state.sourceNodes.has(node as Node);
42
45
  },
43
-
46
+
44
47
  printCommentsOnUntouchedNodes: true,
45
48
  getLeadingComments: (node) => (node as Node).leadingComments,
46
49
  getTrailingComments: (node) => (node as Node).trailingComments,
@@ -111,15 +114,28 @@ export function getPrintOptions(
111
114
  const identifier = node as Identifier;
112
115
  if (identifier.isDummy && identifier.range) {
113
116
  const text = state.lastArgNodes.has(identifier) ? "," : "";
114
- // extend the source mapping of dummy id to the before next token
117
+ // extend the source mapping of dummy id.
115
118
  let firstNonWhiteSpaceIndex = context.source
116
119
  .slice(identifier.range[1])
117
120
  .search(/\S/);
118
- const rangeEnd =
119
- firstNonWhiteSpaceIndex === -1
120
- ? context.source.length
121
- : identifier.range[1] + firstNonWhiteSpaceIndex;
122
- context.writeMapped(text, identifier.range[0], rangeEnd);
121
+ if (firstNonWhiteSpaceIndex !== 0) {
122
+ // a) if next char-seq is whitespaces, write them as mapped
123
+ const rangeEnd =
124
+ firstNonWhiteSpaceIndex === -1
125
+ ? context.source.length
126
+ : identifier.range[1] + firstNonWhiteSpaceIndex;
127
+ context.writeMapped(text, identifier.range[0], rangeEnd);
128
+ } else {
129
+ // b) otherwise create extra mapping directly for next character
130
+ const rangeEnd = Math.min(node.range[0] + 1, context.source.length);
131
+ context.createExtraMapping(
132
+ { start: identifier.range[0], end: rangeEnd },
133
+ context.generatedOffset,
134
+ context.generatedOffset + 1,
135
+ DEFAULT_VOLAR_MAPPING_DATA,
136
+ );
137
+ context.write(text);
138
+ }
123
139
  } else if (
124
140
  identifier.range &&
125
141
  state.attributeNameNodes.has(identifier)
@@ -222,6 +238,23 @@ export function getPrintOptions(
222
238
  context.writeSource(node.whiteSpaceStart, node.whiteSpaceEnd);
223
239
  context.write(";");
224
240
  },
241
+ ErrorStatement(node: any, context: PrinterContext<CodeInformation>) {
242
+ if (node.range) {
243
+ context.writePreservedNode(node);
244
+ const rangeEnd = Math.min(node.range[1] + 1, context.source.length);
245
+ context.createExtraMapping(
246
+ { start: node.range[1], end: rangeEnd },
247
+ context.generatedOffset,
248
+ context.generatedOffset + 1,
249
+ VERIFICATION_ONLY_MAPPING_DATA,
250
+ );
251
+ } else {
252
+ // Emit a TS error indicate the error. This should not happen.
253
+ context.write(
254
+ `((_: never) => 0)(${JSON.stringify(node.error ?? "Unknown error")});`,
255
+ );
256
+ }
257
+ },
225
258
  },
226
259
  // Enable triggering signature completion
227
260
  experimentalGetLeftParenSourceRange: (node) => {