codegen: add a way to keep `</script>` as-is for tagged template
Because String.raw`</script>` === String.raw`<\/script>` returns false, I think there should be a way to keep </script> as-is or do a different transformation to avoid </script>. Note that `</script>` === `<\/script>` returns true.
If we encounter this case and the escape option is not explicitly configured,we should also emit a warning as the user has to escape on their selves.
esbuild lowers this case (https://github.com/evanw/esbuild/commit/58ac420581421b36c03649c0018286e5a8e58ffd#diff-06572a96a58dc510037d5efa622f9bec8519bc1beab13c9f251e97e657a9d4edL48-R50, esbuild try) so the user doesn't have to configure it.
See https://github.com/rolldown/rolldown/issues/6829 for context
Note: esbuild codegen behaves differently with platform
--platform=node: https://esbuild.github.io/try/#dAAwLjI1LjEyAC0tdGFyZ2V0PWVzbmV4dCAtLXBsYXRmb3JtPW5vZGUAZm9vYDwvc2NyaXB0PmA
without: https://esbuild.github.io/try/#dAAwLjI1LjEyAC0tdGFyZ2V0PWVzbmV4dABmb29gPC9zY3JpcHQ+YA
I will implement a transformation to transform TaggedTemplateExpression that contains </script>, which is controlled by an option, and let Rolldown decide whether to transform it, as it only applies when the platform is a browser.
I think we need to do 2 things:
- Implement the transform (as you said).
- Add an option to codegen to disable escaping
</script>.
If I understood correctly, we need both these things to solve the issue.
Rolldown can choose whether to apply the transformation, and whether to set the codegen option or not, depending on the target platform.
Implementing the transform would unblock the issue. Adding an option to disable escaping </script> is more a nice-to-have. The code would work fine even if it's escaped. It's just that the code is longer.
Ah yes, you're right. Because this passes:
const same = `</script>` === `<\/script>`;
assert(same);
So whether the \ is inserted in codegen makes no difference, as long as the transform for tagged template literals already ran before codegen.
It just seems wasteful to always insert extra characters in output, when they're unnecessary except in the specific case where the printed code is being put in a <script> tag in a HTML page.
One note on the transform:
The temp var _a is always inserted at top level, no matter where the template literal is in AST:
https://esbuild.github.io/try/#dAAwLjI1LjEyAC0tdGFyZ2V0PWVzbmV4dCAtLXBsYXRmb3JtPWJyb3dzZXIAZnVuY3Rpb24gZigpIHsKICBpZiAodHJ1ZSkgewogICAgcmV0dXJuIGZ1bmN0aW9uKCkgewogICAgICByZXR1cm4gZm9vYDwvc2NyaXB0PmA7CiAgICB9OwogIH0KfQ
#15664 implements the transform for tagged template expression in a separate path that the codegen. What is the expected way to use it to enable / disable the transform? Is it like below?:
- To enable:
- use the transformer with
plugins.taggedTemplateEscape - use the codegen with the escape enabled
- use the transformer with
- To disable:
- don't use the transformer with
plugins.taggedTemplateEscape - use the codegen with the escape disabled
- don't use the transformer with
I noticed that the codegen should not escape </script inside the tagged template regardless of the escape option, otherwise it will change the meaning.
I noticed that the codegen should not escape
</scriptinside the tagged template regardless of the escape option, otherwise it will change the meaning.
I agree. For now, we can enable the taggedTemplateTransform plugin to work around this problem until we disable the behavior of escaping
codegen should not escape
</scriptinside the tagged template regardless of the escape option, otherwise it will change the meaning.
That's true. But maybe it should throw an error, because the user is expecting the output to be safe to put in a <script> block in an HTML document, and it isn't. The error could say they need to enable to transform, or disable escaping in the codegen.
Partially fixed in #15664. Follow-up required to fix an edge case bug.