diff --git a/.vscode/launch.json b/.vscode/launch.json index 9d57193837..55f7f8a343 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -28,23 +28,6 @@ // "cwd": "${workspaceFolder}", // "console": "internalConsole" // } - // { - // "type": "lldb", - // "request": "launch", - // "name": "Dev Launch", - // "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev", - // "preLaunchTask": "build", - // "args": [ - // "--resolve=disable", - // "--cwd", - // "/Users/jarredsumner/Code/esdev/src/test/fixtures/", - // "/Users/jarredsumner/Code/esdev/src/test/fixtures/symbols-bug.js", - // "-o", - // "out" - // ], - // "cwd": "${workspaceFolder}", - // "console": "internalConsole" - // } { "type": "lldb", "request": "launch", @@ -52,14 +35,12 @@ "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev", "preLaunchTask": "build", "args": [ - "--resolve=dev", + "--resolve=disable", "--cwd", - "/Users/jarredsumner/Builds/esbuild/bench/three/src/", - "./entry.js", - "-o", - "out" + "/Users/jarredsumner/Code/esdev/src/test/fixtures/", + "in-keyword.js" ], - "cwd": "/Users/jarredsumner/Builds/esbuild/bench/three/src", + "cwd": "${workspaceFolder}", "console": "internalConsole" } // { @@ -76,6 +57,23 @@ // "-o", // "out" // ], + // "cwd": "/Users/jarredsumner/Builds/esbuild/bench/three/src", + // "console": "internalConsole" + // } + // { + // "type": "lldb", + // "request": "launch", + // "name": "Dev Launch", + // "program": "${workspaceFolder}/build/debug/macos-x86_64/esdev", + // "preLaunchTask": "build", + // "args": [ + // "--resolve=dev", + // "--cwd", + // "/Users/jarredsumner/Builds/esbuild/bench/three/src/", + // "./entry.js", + // "-o", + // "out" + // ], // "cwd": "${workspaceFolder}", // "console": "internalConsole" // } diff --git a/src/js_parser/js_parser.zig b/src/js_parser/js_parser.zig index 641fa312df..e95d93bf04 100644 --- a/src/js_parser/js_parser.zig +++ b/src/js_parser/js_parser.zig @@ -3738,7 +3738,7 @@ pub const P = struct { if (p.lexer.token == .t_in) { try p.forbidInitializers(decls, "in", false); try p.lexer.next(); - const value = try p.parseExpr(.comma); + const value = try p.parseExpr(.lowest); try p.lexer.expect(.t_close_paren); var stmtOpts = ParseStatementOptions{}; const body = try p.parseStmt(&stmtOpts); @@ -4431,6 +4431,7 @@ pub const P = struct { // "in" expressions are allowed var old_allow_in = p.allow_in; p.allow_in = true; + while (p.lexer.token != .t_close_bracket) { if (p.lexer.token == .t_comma) { items.append(js_ast.ArrayBinding{ @@ -4478,6 +4479,7 @@ pub const P = struct { is_single_line = false; } } + p.allow_in = old_allow_in; if (p.lexer.has_newline_before) { @@ -6870,12 +6872,14 @@ pub const P = struct { // Arrow functions aren't allowed in the middle of expressions if (level.gt(.assign)) { + // Allow "in" inside parentheses const oldAllowIn = p.allow_in; p.allow_in = true; var value = try p.parseExpr(Level.lowest); p.markExprAsParenthesized(&value); try p.lexer.expect(.t_close_paren); + p.allow_in = oldAllowIn; return value; } @@ -6898,6 +6902,21 @@ pub const P = struct { try p.lexer.next(); return Expr{ .data = Prefill.Data.This, .loc = loc }; }, + .t_private_identifier => { + if (!p.allow_private_identifiers or !p.allow_in) { + try p.lexer.unexpected(); + } + + const name = p.lexer.identifier; + try p.lexer.next(); + + // Check for "#foo in bar" + if (p.lexer.token != .t_in) { + try p.lexer.expected(.t_in); + } + + return p.e(E.PrivateIdentifier{ .ref = try p.storeNameInRef(name) }, loc); + }, .t_identifier => { const name = p.lexer.identifier; const name_range = p.lexer.range(); @@ -7237,7 +7256,10 @@ pub const P = struct { try p.lexer.expect(.t_close_bracket); p.allow_in = old_allow_in; - if (p.willNeedBindingPattern()) {} else if (errors.isEmpty()) { + // Is this a binding pattern? + if (p.willNeedBindingPattern()) { + // noop + } else if (errors.isEmpty()) { // Is this an expression? p.logExprErrors(&self_errors); } else { @@ -11070,6 +11092,10 @@ pub const P = struct { var _parser = try allocator.create(P); _parser.* = P{ + // This must default to true or else parsing "in" won't work right. + // It will fail for the case in the "in-keyword.js" file + .allow_in = true, + .symbol_uses = SymbolUseMap.init(allocator), .call_target = nullExprData, .delete_target = nullExprData, diff --git a/src/test/fixtures/in-keyword.js b/src/test/fixtures/in-keyword.js new file mode 100644 index 0000000000..cd758463e8 --- /dev/null +++ b/src/test/fixtures/in-keyword.js @@ -0,0 +1 @@ +const foo = "name" in Function.prototype === false;