-
Notifications
You must be signed in to change notification settings - Fork 13.2k
Fix template string refactoring and nodeFactory bug #44313
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
e2da2bb to
d069dcf
Compare
QuestionThis is using |
|
ping @rbuckton |
tests/cases/fourslash/refactorConvertStringOrTemplateLiteral_escapeSequences.ts
Outdated
Show resolved
Hide resolved
src/compiler/factory/nodeFactory.ts
Outdated
| // @api | ||
| function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { | ||
| const node = createBaseToken<TemplateLiteralLikeNode>(kind); | ||
| rawText ??= JSON.stringify(text).slice(1,-1).replace(/\\.|\$/g, s => |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think we should try to synthesize rawText here. Generally when rawText is undefined we intend to pull the "raw" version of the template literal from the source file during emit. rawText was added to allow API consumers to pass their own "raw" text, and in those cases it goes through createTemplateLiteralLikeNodeChecked which verifies that the "cooked" text matches the supplied "raw" text.
If someone were to pass the string "\t " (byte sequence 5c 74 09) for text, this would generate a "raw" text of "\t\t". There's no way to be 100% sure what the user intended, so its better to be explicit.
I think the issue is actually in the implementation of the refactor, which should be reading the raw source text of the string literal rather than node.text.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Its also important that rawText remains undefined for our tagged template transform to accurately get the actual raw text from the source file for non-user-created nodes:
TypeScript/src/compiler/transformers/taggedTemplate.ts
Lines 78 to 84 in eb3645f
| function getRawLiteral(node: TemplateLiteralLikeNode, currentSourceFile: SourceFile) { | |
| // Find original source text, since we need to emit the raw strings of the tagged template. | |
| // The raw strings contain the (escaped) strings of what the user wrote. | |
| // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". | |
| let text = node.rawText; | |
| if (text === undefined) { | |
| text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node); |
30d1f7c to
ee7b39d
Compare
createTemplateHead*|
|
||
| let token = rawTextScanner.scan(); | ||
| if (token === SyntaxKind.CloseBracketToken) { | ||
| if (token === SyntaxKind.CloseBraceToken) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Obvious typo I wish I'd caught sooner 😔. Good catch.
1. `getRawLiteral()`: barf if `currentSourceFile` is missing, since if it is, then the following `getSourceTextOfNodeFromSourceFile` will return a bogus `""`. 2. Some `||` -> `??`. 3. `backtickQuoteEscapedCharsRegExp`: escape the usual control characters except for a simple LF. This code does get used to generate backtick strings when `rawText` is not given, and not escaping things like TAB characters can get mangled by editor settings. Worse, not escaping a CRLF and putting it verbatim in sthe string source will interpret it as LF, so add a special case for escaping these as `\r\n`. Related to microsoft#44313 and microsoft#40625.
1. `getRawLiteral()`: barf if `currentSourceFile` is missing, since if it is, then the following `getSourceTextOfNodeFromSourceFile` will return a bogus `""`. 2. Some `||` -> `??`. 3. `backtickQuoteEscapedCharsRegExp`: escape the usual control characters except for a simple LF. This code does get used to generate backtick strings when `rawText` is not given, and not escaping things like TAB characters can get mangled by editor settings. Worse, not escaping a CRLF and putting it verbatim in sthe string source will interpret it as LF, so add a special case for escaping these as `\r\n`. Related to microsoft#44313 and microsoft#40625.
rbuckton
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few minor nits but this looks good.
93acbe8 to
8e01e23
Compare
1. `getRawLiteral()`: barf if `currentSourceFile` is missing, since if it is, then the following `getSourceTextOfNodeFromSourceFile` will return a bogus `""`. 2. One `||` -> `??` change. 3. `backtickQuoteEscapedCharsRegExp`: escape the usual control characters except for a simple LF. This code does get used to generate backtick strings when `rawText` is not given, and not escaping things like TAB characters can get mangled by editor settings. Worse, not escaping a CRLF and putting it verbatim in sthe string source will interpret it as LF, so add a special case for escaping these as `\r\n`. Related to microsoft#44313 and microsoft#40625.
Instead of letting `createTemplate*` generate a broken raw string from
the cooked one, grab the source code for it.
Also, add a missing bit to `\`-quote `$`s. As the comment in the code
says, it could just `\`-quote `${` since other `$`s are valid, but I
think that it's less confusing to always quote $s (but the change is in
the comment if minimalism is preferred).
Also, a small-but-confusing bug in `getCookedText()`.
Many tests for all of this.
Fixes microsoft#40625
1. `getRawLiteral()`: barf if `currentSourceFile` is missing, since if it is, then the following `getSourceTextOfNodeFromSourceFile` will return a bogus `""`. 2. One `||` -> `??` change. 3. `backtickQuoteEscapedCharsRegExp`: escape the usual control characters except for a simple LF. This code does get used to generate backtick strings when `rawText` is not given, and not escaping things like TAB characters can get mangled by editor settings. Worse, not escaping a CRLF and putting it verbatim in sthe string source will interpret it as LF, so add a special case for escaping these as `\r\n`. Added test. Related to microsoft#44313 and microsoft#40625.
1. `getRawLiteral()`: barf if `currentSourceFile` is missing, since if it is, then the following `getSourceTextOfNodeFromSourceFile` will return a bogus `""`. 2. One `||` -> `??` change. 3. `backtickQuoteEscapedCharsRegExp`: escape the usual control characters except for a simple LF. This code does get used to generate backtick strings when `rawText` is not given, and not escaping things like TAB characters can get mangled by editor settings. Worse, not escaping a CRLF and putting it verbatim in sthe string source will interpret it as LF, so add a special case for escaping these as `\r\n`. Added test. Related to microsoft#44313 and microsoft#40625.
1. `getRawLiteral()`: barf if `currentSourceFile` is missing, since if it is, then the following `getSourceTextOfNodeFromSourceFile` will return a bogus `""`. 2. One `||` -> `??` change. 3. `backtickQuoteEscapedCharsRegExp`: escape the usual control characters except for a simple LF. This code does get used to generate backtick strings when `rawText` is not given, and not escaping things like TAB characters can get mangled by editor settings. Worse, not escaping a CRLF and putting it verbatim in sthe string source will interpret it as LF, so add a special case for escaping these as `\r\n`. Added test. Related to #44313 and #40625.
Fix template string refactoring and nodeFactory bug
Instead of letting
createTemplate*generate a broken raw string fromthe cooked one, grab the source code for it.
Also, add a missing bit to
\-quote$s. As the comment in the codesays, it could just
\-quote${since other$s are valid, but Ithink that it's less confusing to always quote $s (but the change is in
the comment if minimalism is preferred).
Also, a small-but-confusing bug in
getCookedText().Many tests for all of this.
Fixes #40625