@samitouri / QOS-React-2 / commits / 44beb3c023

Collect bailouts in BuildHIR::lowerAssignment

Lauren Tan committed Jan 20, 2023 at 11:47 UTC 44beb3c0238994a61ada2c0386a42107d03dc9ac
3 files changed +172 -100
compiler/forget/src/HIR/BuildHIR.ts
+67 -26
@@ -7,10 +7,8 @@
7
8 import { NodePath, Scope } from "@babel/traverse";
9 import * as t from "@babel/types";
10 -import invariant from "invariant";
10 import { CompilerError, ErrorSeverity } from "../CompilerError";
11 import { Err, Ok, Result } from "../lib/Result";
13 -import todo, { todoInvariant } from "../Utils/todo";
12 import { assertExhaustive } from "../Utils/utils";
13 import {
14 BlockId,
@@ -1724,7 +1722,14 @@ function lowerAssignment(
1722 });
1723 }
1724 if (!lvalue.node.computed) {
1727 - todoInvariant(property.isIdentifier(), "Support private names");
1725 + if (!property.isIdentifier()) {
1726 + builder.pushError({
1727 + reason: "Support private names",
1728 + severity: ErrorSeverity.Todo,
1729 + nodePath: property,
1730 + });
1731 + return { kind: "UnsupportedNode", node: lvalueNode, loc };
1732 + }
1733 return {
1734 kind: "PropertyStore",
1735 object,
@@ -1733,10 +1738,15 @@ function lowerAssignment(
1738 loc,
1739 };
1740 } else {
1736 - invariant(
1737 - property.isExpression(),
1738 - "Expected private name to appear as a non-computed property"
1739 - );
1741 + if (!property.isExpression()) {
1742 + builder.pushError({
1743 + reason:
1744 + "Expected private name to appear as a non-computed property",
1745 + severity: ErrorSeverity.InvalidInput,
1746 + nodePath: property,
1747 + });
1748 + return { kind: "UnsupportedNode", node: lvalueNode, loc };
1749 + }
1750 const propertyPlace = lowerExpressionToPlace(builder, property);
1751 return {
1752 kind: "ComputedStore",
@@ -1757,15 +1767,21 @@ function lowerAssignment(
1767 loc,
1768 });
1769 const elements = lvalue.get("elements");
1770 + let hasError = false;
1771 for (let i = 0; i < elements.length; i++) {
1772 const element = elements[i];
1773 if (!element.hasNode()) {
1774 continue;
1775 }
1765 - todoInvariant(
1766 - element.node.type !== "RestElement",
1767 - "Rest elements are not supported yet"
1768 - );
1776 + if (element.node.type === "RestElement") {
1777 + builder.pushError({
1778 + reason: "Rest elements are not supported yet",
1779 + severity: ErrorSeverity.Todo,
1780 + nodePath: element,
1781 + });
1782 + hasError = true;
1783 + continue;
1784 + }
1785 const property = buildTemporaryPlace(
1786 builder,
1787 element.node.loc ?? GeneratedSource
@@ -1788,7 +1804,9 @@ function lowerAssignment(
1804 };
1805 lowerAssignment(builder, loc, kind, element, value);
1806 }
1791 - return arrayPlace;
1807 + return hasError
1808 + ? { kind: "UnsupportedNode", node: lvalueNode, loc }
1809 + : arrayPlace;
1810 }
1811 case "ObjectPattern": {
1812 const lvalue = lvaluePath as NodePath<t.ObjectPattern>;
@@ -1800,22 +1818,38 @@ function lowerAssignment(
1818 loc,
1819 });
1820 const properties = lvalue.get("properties");
1821 + let hasError = false;
1822 for (let i = 0; i < properties.length; i++) {
1823 const property = properties[i];
1805 - invariant(
1806 - property.isObjectProperty(),
1807 - "Rest elements are not supported yet"
1808 - );
1824 + if (!property.isObjectProperty()) {
1825 + builder.pushError({
1826 + reason: "Rest elements are not supported yet",
1827 + severity: ErrorSeverity.Todo,
1828 + nodePath: property,
1829 + });
1830 + hasError = true;
1831 + continue;
1832 + }
1833 const key = property.get("key");
1810 - invariant(
1811 - key.isIdentifier(),
1812 - "TODO: support non-identifier object property keys"
1813 - );
1834 + if (!key.isIdentifier()) {
1835 + builder.pushError({
1836 + reason: "Support non-identifier object property keys",
1837 + severity: ErrorSeverity.Todo,
1838 + nodePath: key,
1839 + });
1840 + hasError = true;
1841 + continue;
1842 + }
1843 const element = property.get("value");
1815 - invariant(
1816 - element.isLVal(),
1817 - "Expected object property value to be an lvalue"
1818 - );
1844 + if (!element.isLVal()) {
1845 + builder.pushError({
1846 + reason: "Expected object property value to be an lvalue",
1847 + severity: ErrorSeverity.InvalidInput,
1848 + nodePath: element,
1849 + });
1850 + hasError = true;
1851 + continue;
1852 + }
1853 const value: InstructionValue = {
1854 kind: "PropertyLoad",
1855 loc,
@@ -1824,10 +1858,17 @@ function lowerAssignment(
1858 };
1859 lowerAssignment(builder, loc, kind, element, value);
1860 }
1827 - return objectPlace;
1861 + return hasError
1862 + ? { kind: "UnsupportedNode", node: lvalueNode, loc }
1863 + : objectPlace;
1864 }
1865 default: {
1830 - todo("Support other lvalue types beyond identifier");
1866 + builder.pushError({
1867 + reason: "Support other lvalue types beyond identifier",
1868 + severity: ErrorSeverity.Todo,
1869 + nodePath: lvaluePath,
1870 + });
1871 + return { kind: "UnsupportedNode", node: lvalueNode, loc };
1872 }
1873 }
1874 }
compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.expect.md
+103 -74
@@ -21,6 +21,8 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
21 new c(...args);
22 c(...args);
23 g["e"] += 1;
24 + const [y, ...yy] = useState(0);
25 + const { z, aa = "aa", ...zz } = useCustom();
26
27 <Button {...args}></Button>;
28 <Button xlink:href="localhost:3000"></Button>;
@@ -123,7 +125,7 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
125 | ^^^^^^^
126 18 | c(...args);
127 19 | g["e"] += 1;
126 - 20 |
128 + 20 | const [y, ...yy] = useState(0);
129
130 [ReactForget] TodoError: Support non-expression arguments to CallExpression
131 16 | const h = [...b];
@@ -131,122 +133,149 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
133 > 18 | c(...args);
134 | ^^^^^^^
135 19 | g["e"] += 1;
134 - 20 |
135 - 21 | <Button {...args}></Button>;
136 + 20 | const [y, ...yy] = useState(0);
137 + 21 | const { z, aa = "aa", ...zz } = useCustom();
138
139 [ReactForget] TodoError: Assignment expression to dynamic properties is not yet supported
140 17 | new c(...args);
141 18 | c(...args);
142 > 19 | g["e"] += 1;
143 | ^^^
142 - 20 |
143 - 21 | <Button {...args}></Button>;
144 - 22 | <Button xlink:href="localhost:3000"></Button>;
144 + 20 | const [y, ...yy] = useState(0);
145 + 21 | const { z, aa = "aa", ...zz } = useCustom();
146 + 22 |
147
146 -[ReactForget] TodoError: Handle spread attributes
148 +[ReactForget] TodoError: Rest elements are not supported yet
149 + 18 | c(...args);
150 + 19 | g["e"] += 1;
151 +> 20 | const [y, ...yy] = useState(0);
152 + | ^^^^^
153 + 21 | const { z, aa = "aa", ...zz } = useCustom();
154 + 22 |
155 + 23 | <Button {...args}></Button>;
156 +
157 +[ReactForget] TodoError: Support other lvalue types beyond identifier
158 19 | g["e"] += 1;
148 - 20 |
149 -> 21 | <Button {...args}></Button>;
159 + 20 | const [y, ...yy] = useState(0);
160 +> 21 | const { z, aa = "aa", ...zz } = useCustom();
161 + | ^^^^^^^^^
162 + 22 |
163 + 23 | <Button {...args}></Button>;
164 + 24 | <Button xlink:href="localhost:3000"></Button>;
165 +
166 +[ReactForget] TodoError: Rest elements are not supported yet
167 + 19 | g["e"] += 1;
168 + 20 | const [y, ...yy] = useState(0);
169 +> 21 | const { z, aa = "aa", ...zz } = useCustom();
170 + | ^^^^^
171 + 22 |
172 + 23 | <Button {...args}></Button>;
173 + 24 | <Button xlink:href="localhost:3000"></Button>;
174 +
175 +[ReactForget] TodoError: Handle spread attributes
176 + 21 | const { z, aa = "aa", ...zz } = useCustom();
177 + 22 |
178 +> 23 | <Button {...args}></Button>;
179 | ^^^^^^^^^
151 - 22 | <Button xlink:href="localhost:3000"></Button>;
152 - 23 | <Button haha={1}></Button>;
153 - 24 | <Button>{/** empty */}</Button>;
180 + 24 | <Button xlink:href="localhost:3000"></Button>;
181 + 25 | <Button haha={1}></Button>;
182 + 26 | <Button>{/** empty */}</Button>;
183
184 [ReactForget] TodoError: Handle non-identifier jsx attribute names
156 - 20 |
157 - 21 | <Button {...args}></Button>;
158 -> 22 | <Button xlink:href="localhost:3000"></Button>;
185 + 22 |
186 + 23 | <Button {...args}></Button>;
187 +> 24 | <Button xlink:href="localhost:3000"></Button>;
188 | ^^^^^^^^^^
160 - 23 | <Button haha={1}></Button>;
161 - 24 | <Button>{/** empty */}</Button>;
162 - 25 | <DesignSystem.Button />;
189 + 25 | <Button haha={1}></Button>;
190 + 26 | <Button>{/** empty */}</Button>;
191 + 27 | <DesignSystem.Button />;
192
193 [ReactForget] TodoError: Handle empty expressions
165 - 22 | <Button xlink:href="localhost:3000"></Button>;
166 - 23 | <Button haha={1}></Button>;
167 -> 24 | <Button>{/** empty */}</Button>;
194 + 24 | <Button xlink:href="localhost:3000"></Button>;
195 + 25 | <Button haha={1}></Button>;
196 +> 26 | <Button>{/** empty */}</Button>;
197 | ^^^^^^^^^^^^
169 - 25 | <DesignSystem.Button />;
170 - 26 |
171 - 27 | const j = function bar([quz, qux], ...args) {};
198 + 27 | <DesignSystem.Button />;
199 + 28 |
200 + 29 | const j = function bar([quz, qux], ...args) {};
201
202 [ReactForget] TodoError: Handle non-identifier tags
174 - 23 | <Button haha={1}></Button>;
175 - 24 | <Button>{/** empty */}</Button>;
176 -> 25 | <DesignSystem.Button />;
203 + 25 | <Button haha={1}></Button>;
204 + 26 | <Button>{/** empty */}</Button>;
205 +> 27 | <DesignSystem.Button />;
206 | ^^^^^^^^^^^^^^^^^^^
178 - 26 |
179 - 27 | const j = function bar([quz, qux], ...args) {};
207 28 |
208 + 29 | const j = function bar([quz, qux], ...args) {};
209 + 30 |
210
211 [ReactForget] TodoError: Support non-identifier params: ArrayPattern
183 - 25 | <DesignSystem.Button />;
184 - 26 |
185 -> 27 | const j = function bar([quz, qux], ...args) {};
186 - | ^^^^^^^^^^
212 + 27 | <DesignSystem.Button />;
213 28 |
188 - 29 | for (; i < 3; i += 1) {
189 - 30 | x.push(i);
214 +> 29 | const j = function bar([quz, qux], ...args) {};
215 + | ^^^^^^^^^^
216 + 30 |
217 + 31 | for (; i < 3; i += 1) {
218 + 32 | x.push(i);
219
220 [ReactForget] TodoError: Support non-identifier params: RestElement
192 - 25 | <DesignSystem.Button />;
193 - 26 |
194 -> 27 | const j = function bar([quz, qux], ...args) {};
195 - | ^^^^^^^
221 + 27 | <DesignSystem.Button />;
222 28 |
197 - 29 | for (; i < 3; i += 1) {
198 - 30 | x.push(i);
223 +> 29 | const j = function bar([quz, qux], ...args) {};
224 + | ^^^^^^^
225 + 30 |
226 + 31 | for (; i < 3; i += 1) {
227 + 32 | x.push(i);
228
229 [ReactForget] TodoError: Support non-variable initialization in for
201 - 27 | const j = function bar([quz, qux], ...args) {};
202 - 28 |
203 -> 29 | for (; i < 3; i += 1) {
230 + 29 | const j = function bar([quz, qux], ...args) {};
231 + 30 |
232 +> 31 | for (; i < 3; i += 1) {
233 | ^
205 - 30 | x.push(i);
206 - 31 | }
207 - 32 | for (; i < 3; ) {}
234 + 32 | x.push(i);
235 + 33 | }
236 + 34 | for (; i < 3; ) {}
237
238 [ReactForget] TodoError: Support non-variable initialization in for
210 - 30 | x.push(i);
211 - 31 | }
212 -> 32 | for (; i < 3; ) {}
239 + 32 | x.push(i);
240 + 33 | }
241 +> 34 | for (; i < 3; ) {}
242 | ^^^^^^^^^^^^^^^^^^
214 - 33 | for (;;) {}
215 - 34 | }
216 - 35 |
243 + 35 | for (;;) {}
244 + 36 | }
245 + 37 |
246
247 [ReactForget] TodoError: Handle empty for updater
219 - 30 | x.push(i);
220 - 31 | }
221 -> 32 | for (; i < 3; ) {}
248 + 32 | x.push(i);
249 + 33 | }
250 +> 34 | for (; i < 3; ) {}
251 | ^^^^^^^^^^^^^^^^^^
223 - 33 | for (;;) {}
224 - 34 | }
225 - 35 |
252 + 35 | for (;;) {}
253 + 36 | }
254 + 37 |
255
256 [ReactForget] TodoError: Support non-variable initialization in for
228 - 31 | }
229 - 32 | for (; i < 3; ) {}
230 -> 33 | for (;;) {}
257 + 33 | }
258 + 34 | for (; i < 3; ) {}
259 +> 35 | for (;;) {}
260 | ^^^^^^^^^^^
232 - 34 | }
233 - 35 |
261 + 36 | }
262 + 37 |
263
264 [ReactForget] TodoError: Handle empty for updater
236 - 31 | }
237 - 32 | for (; i < 3; ) {}
238 -> 33 | for (;;) {}
265 + 33 | }
266 + 34 | for (; i < 3; ) {}
267 +> 35 | for (;;) {}
268 | ^^^^^^^^^^^
240 - 34 | }
241 - 35 |
269 + 36 | }
270 + 37 |
271
272 [ReactForget] TodoError: ForStatement without test
244 - 31 | }
245 - 32 | for (; i < 3; ) {}
246 -> 33 | for (;;) {}
273 + 33 | }
274 + 34 | for (; i < 3; ) {}
275 +> 35 | for (;;) {}
276 | ^^^^^^^^^^^
248 - 34 | }
249 - 35 |
277 + 36 | }
278 + 37 |
279 ```
280
281
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/hir/error.todo-kitchensink.js
+2
@@ -17,6 +17,8 @@ function foo([a, b], { c, d, e = "e" }, f = "f", ...args) {
17 new c(...args);
18 c(...args);
19 g["e"] += 1;
20 + const [y, ...yy] = useState(0);
21 + const { z, aa = "aa", ...zz } = useCustom();
22
23 <Button {...args}></Button>;
24 <Button xlink:href="localhost:3000"></Button>;