diff options
author | 2022-03-05 19:15:25 -0800 | |
---|---|---|
committer | 2022-03-05 19:33:25 -0800 | |
commit | 093807391a9563ad36c2b04a286da23d09fad835 (patch) | |
tree | 5485bda684d4f04b6a5af9a12f509fd47e906be1 /src/js_parser/js_parser.zig | |
parent | 18c923596a5b6480fa5a841bd0a6adfdb365b831 (diff) | |
download | bun-093807391a9563ad36c2b04a286da23d09fad835.tar.gz bun-093807391a9563ad36c2b04a286da23d09fad835.tar.zst bun-093807391a9563ad36c2b04a286da23d09fad835.zip |
[JS Parser] dot property shorthand for JSX
This is a non-standard backwards-compatible feature that I suspect other tooling will soon adopt (and expect to help other tooling adopt it)
```jsx
var hello = {hi: 'yo'};
export const Foo = () => <Bar {hello.hi} />
```
Desugars into:
```jsx
var hello = {hi: 'yo'};
export const Foo = () => <Bar hi={hello.hi} />
```
This works with defines and macros too.
```jsx
export const Foo = () => <Bar {process.env.NODE_ENV} />
```
```jsx
export const Foo = () => <Bar NODE_ENV="development" />
```
Diffstat (limited to '')
-rw-r--r-- | src/js_parser/js_parser.zig | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index b299b4498..afe429e9e 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -11356,16 +11356,35 @@ fn NewParser_( // -> // <div foo={foo} /> T.t_identifier => { - const name = p.lexer.identifier; - if (strings.eqlComptime(name, "let")) { - p.lexer.addError(p.source, p.lexer.loc(), "\"let\" is not allowed with JSX prop punning") catch unreachable; - } - const key = p.e(E.String{ .utf8 = name }, p.lexer.loc()); - const ref = p.storeNameInRef(name) catch unreachable; - const value = p.e(E.Identifier{ .ref = ref }, key.loc); - try p.lexer.next(); + // we need to figure out what the key they mean is + // to do that, we must determine the key name + const expr = try p.parseExpr(Level.lowest); + + const key = brk: { + switch (expr.data) { + .e_import_identifier => |ident| { + break :brk p.e(E.String{ .utf8 = p.loadNameFromRef(ident.ref) }, expr.loc); + }, + .e_identifier => |ident| { + break :brk p.e(E.String{ .utf8 = p.loadNameFromRef(ident.ref) }, expr.loc); + }, + .e_dot => |dot| { + break :brk p.e(E.String{ .utf8 = dot.name }, dot.name_loc); + }, + .e_index => |index| { + if (index.index.data == .e_string) { + break :brk index.index; + } + }, + else => {}, + } + + // If we get here, it's invalid + try p.log.addError(p.source, expr.loc, "Invalid JSX prop shorthand, must be identifier, dot or string"); + return error.SyntaxError; + }; - try props.append(G.Property{ .value = value, .key = key, .kind = .normal }); + try props.append(G.Property{ .value = expr, .key = key, .kind = .normal }); }, // This implements // <div {"foo"} /> |