Repository navigation
Parse $'' and $"" as redirect targets, and process substitutions after <<< - #19
Conversation
webpro
left a comment
There was a problem hiding this comment.
Thanks, both fixes are right and the tests cover both cases.
Bash 3.2 and 5.3 accept every input in the description. Against main, all fixtures parse to byte-identical ASTs and printer output, and a 149-input corpus covering every redirect operator, $'...' and $"..." in command, argument, assignment, case, test, loop and array positions, nested substitutions, heredoc bodies, fd prefixes and compound-command redirects changes only for the intended inputs. A welcome side effect: an unterminated $', $" or <( target now reports one error instead of two.
Trade-offs weighed before approving:
- The quoted lookahead costs one
charCodeAtand two compares per$in a slow-path word, the same checkreadHereDocDelimiteralready makes. Measured withbench/worker.tsover separate builds of main and this branch, every fixture group stays within 1% of main, inside the 1.3 to 4% run-to-run spread; a synthetic input that is 24%$by bytes runs 1.4% slower, about 0.8 ns per$. The large fixtures are 1.2 to 2.3%$by bytes, so the expected cost on real scripts is about 0.1%. Evaluating the lookahead only when the processed word text is empty, the only case the flag is read for a$word, would take it off the hot path, but the explicit form reads better and 0.1% does not justify the special case. - The
<<<branch still repeats the generic redirect tail (skip blanks, process-substitution check, read the target, build the token) apart from the operator string. Settingop = "<<<"and falling through to that tail removes the duplication and the helper, with identical output on the same corpus and fixtures. Not required for this PR. cat <<< <(f)xis one word in Bash but lexes as a target plus an argument, exactly ascat < <(f)xdoes on main. Out of scope here.
Two optional test notes: literal [source, target] pairs would be more direct than deriving the target from the input, and echo <<< $"" and cat <<<>(f) would complete the lists; both parse.
commit: |
|
🚀 This pull request is included in v6.0.3. See Release 6.0.3 for release notes. |
Bash accepts all of these (
bash -npasses), but unbash reports "expected redirect target":cat > $'',cat > $"",cat <<< $'': an empty ANSI-C or locale string didn't mark the word as quoted, so it looked like no target. The heredoc delimiter scanner already does this check.cat <<< <(f),cat <<< >(f),cat <<<<(f): the here-string branch returned before the process-substitution check the other redirects use. It's now a shared helper.Tests added to
test/error-recovery.test.ts.