diff --git a/changelog_unreleased/javascript/pr-9431.md b/changelog_unreleased/javascript/pr-9431.md
new file mode 100644
index 000000000..b3233bf01
--- /dev/null
+++ b/changelog_unreleased/javascript/pr-9431.md
@@ -0,0 +1,21 @@
+#### Keep html and markdown invalid template literals as it is (#9431 by @fisker)
+
+
+```js
+// Input
+foo = html`
\u{prettier}
`;
+foo = html`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = markdown`# \u{prettier}\u{0065}`;
+
+// Prettier stable
+foo = html``;
+foo = html`null${foo}prettier`;
+foo = markdown`
+# \u{prettier}\u{0065}
+`;
+
+// Prettier master
+foo = html`\u{prettier}
`;
+foo = html`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = markdown`# \u{prettier}\u{0065}`;
+```
diff --git a/src/language-js/embed.js b/src/language-js/embed.js
index 371642fb5..eb7aba3da 100644
--- a/src/language-js/embed.js
+++ b/src/language-js/embed.js
@@ -24,6 +24,12 @@ function embed(path, print, textToDoc, options) {
switch (node.type) {
case "TemplateLiteral": {
+ // Bail out if any of the quasis have an invalid escape sequence
+ // (which would make the `cooked` value be `null`)
+ if (hasInvalidCookedValue(node)) {
+ return;
+ }
+
const isCss = [
isStyledJsx,
isStyledComponents,
@@ -69,7 +75,6 @@ function embed(path, print, textToDoc, options) {
const expressionDocs = path.map(printTemplateExpression, "expressions");
const numQuasis = node.quasis.length;
-
if (numQuasis === 1 && node.quasis[0].value.raw.trim() === "") {
return "``";
}
@@ -82,12 +87,6 @@ function embed(path, print, textToDoc, options) {
const isLast = i === numQuasis - 1;
const text = templateElement.value.cooked;
- // Bail out if any of the quasis have an invalid escape sequence
- // (which would make the `cooked` value be `null` or `undefined`)
- if (typeof text !== "string") {
- return null;
- }
-
const lines = text.split("\n");
const numLines = lines.length;
const expressionDoc = expressionDocs[i];
@@ -166,6 +165,9 @@ function embed(path, print, textToDoc, options) {
}
case "TemplateElement": {
+ if (hasInvalidCookedValue(parent)) {
+ return;
+ }
/**
* md`...`
* markdown`...`
@@ -662,4 +664,8 @@ function printHtmlTemplateLiteral(
);
}
+function hasInvalidCookedValue({ quasis }) {
+ return quasis.some(({ value: { cooked } }) => cooked === null);
+}
+
module.exports = embed;
diff --git a/tests/js/multiparser-invalid/__snapshots__/jsfmt.spec.js.snap b/tests/js/multiparser-invalid/__snapshots__/jsfmt.spec.js.snap
new file mode 100644
index 000000000..437f6e376
--- /dev/null
+++ b/tests/js/multiparser-invalid/__snapshots__/jsfmt.spec.js.snap
@@ -0,0 +1,75 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`text.js format 1`] = `
+====================================options=====================================
+parsers: ["babel", "flow", "typescript"]
+printWidth: 80
+ | printWidth
+=====================================input======================================
+foo = foo\`\\u{prettier}\\u{0065}\`;
+foo = html\`\\u{prettier}\\u{0065}\`;
+foo = graphql\`\\u{prettier}\\u{0065}\`;
+foo = markdown\`\\u{prettier}\\u{0065}\`;
+foo = css\`\\u{prettier}\\u{0065}\`;
+foo = /* HTML */\`\\u{prettier}\\u{0065}\`;
+foo = /* GraphQL */\`\\u{prettier}\\u{0065}\`;
+
+foo = foo\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = html\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = graphql\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = markdown\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = css\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = /* HTML */\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = /* GraphQL */\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+
+foo = foo\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = html\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = graphql\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = markdown\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = css\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = /* HTML */\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = /* GraphQL */\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+
+foo = foo\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = html\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = graphql\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = markdown\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = css\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = /* HTML */\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = /* GraphQL */\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+
+=====================================output=====================================
+foo = foo\`\\u{prettier}\\u{0065}\`;
+foo = html\`\\u{prettier}\\u{0065}\`;
+foo = graphql\`\\u{prettier}\\u{0065}\`;
+foo = markdown\`\\u{prettier}\\u{0065}\`;
+foo = css\`\\u{prettier}\\u{0065}\`;
+foo = /* HTML */ \`\\u{prettier}\\u{0065}\`;
+foo = /* GraphQL */ \`\\u{prettier}\\u{0065}\`;
+
+foo = foo\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = html\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = graphql\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = markdown\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = css\`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = /* HTML */ \`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+foo = /* GraphQL */ \`\\u{prettier}\${foo}pr\\u{0065}ttier\`;
+
+foo = foo\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = html\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = graphql\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = markdown\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = css\`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = /* HTML */ \`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+foo = /* GraphQL */ \`pr\\u{0065}ttier\${foo}\\u{prettier}\`;
+
+foo = foo\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = html\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = graphql\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = markdown\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = css\`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = /* HTML */ \`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+foo = /* GraphQL */ \`pr\\u{0065}ttier\${foo}\\u{prettier}\${bar}pr\\u{0065}ttier\`;
+
+================================================================================
+`;
diff --git a/tests/js/multiparser-invalid/jsfmt.spec.js b/tests/js/multiparser-invalid/jsfmt.spec.js
new file mode 100644
index 000000000..6e2b8e1a6
--- /dev/null
+++ b/tests/js/multiparser-invalid/jsfmt.spec.js
@@ -0,0 +1,3 @@
+run_spec(__dirname, ["babel", "flow", "typescript"], {
+ errors: { espree: true, flow: true, typescript: true },
+});
diff --git a/tests/js/multiparser-invalid/text.js b/tests/js/multiparser-invalid/text.js
new file mode 100644
index 000000000..37a612ed5
--- /dev/null
+++ b/tests/js/multiparser-invalid/text.js
@@ -0,0 +1,31 @@
+foo = foo`\u{prettier}\u{0065}`;
+foo = html`\u{prettier}\u{0065}`;
+foo = graphql`\u{prettier}\u{0065}`;
+foo = markdown`\u{prettier}\u{0065}`;
+foo = css`\u{prettier}\u{0065}`;
+foo = /* HTML */`\u{prettier}\u{0065}`;
+foo = /* GraphQL */`\u{prettier}\u{0065}`;
+
+foo = foo`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = html`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = graphql`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = markdown`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = css`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = /* HTML */`\u{prettier}${foo}pr\u{0065}ttier`;
+foo = /* GraphQL */`\u{prettier}${foo}pr\u{0065}ttier`;
+
+foo = foo`pr\u{0065}ttier${foo}\u{prettier}`;
+foo = html`pr\u{0065}ttier${foo}\u{prettier}`;
+foo = graphql`pr\u{0065}ttier${foo}\u{prettier}`;
+foo = markdown`pr\u{0065}ttier${foo}\u{prettier}`;
+foo = css`pr\u{0065}ttier${foo}\u{prettier}`;
+foo = /* HTML */`pr\u{0065}ttier${foo}\u{prettier}`;
+foo = /* GraphQL */`pr\u{0065}ttier${foo}\u{prettier}`;
+
+foo = foo`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;
+foo = html`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;
+foo = graphql`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;
+foo = markdown`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;
+foo = css`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;
+foo = /* HTML */`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;
+foo = /* GraphQL */`pr\u{0065}ttier${foo}\u{prettier}${bar}pr\u{0065}ttier`;