oxc icon indicating copy to clipboard operation
oxc copied to clipboard

codegen: add a way to keep `</script>` as-is for tagged template

Open sapphi-red opened this issue 1 month ago • 9 comments

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

sapphi-red avatar Nov 05 '25 10:11 sapphi-red

Note: esbuild codegen behaves differently with platform

--platform=node: https://esbuild.github.io/try/#dAAwLjI1LjEyAC0tdGFyZ2V0PWVzbmV4dCAtLXBsYXRmb3JtPW5vZGUAZm9vYDwvc2NyaXB0PmA

without: https://esbuild.github.io/try/#dAAwLjI1LjEyAC0tdGFyZ2V0PWVzbmV4dABmb29gPC9zY3JpcHQ+YA

Boshen avatar Nov 12 '25 09:11 Boshen

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.

Dunqing avatar Nov 12 '25 09:11 Dunqing

I think we need to do 2 things:

  1. Implement the transform (as you said).
  2. 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.

overlookmotel avatar Nov 12 '25 10:11 overlookmotel

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.

sapphi-red avatar Nov 12 '25 10:11 sapphi-red

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.

overlookmotel avatar Nov 12 '25 10:11 overlookmotel

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

overlookmotel avatar Nov 12 '25 10:11 overlookmotel

#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
  • To disable:
    • don't use the transformer with plugins.taggedTemplateEscape
    • use the codegen with the escape disabled

I noticed that the codegen should not escape </script inside the tagged template regardless of the escape option, otherwise it will change the meaning.

sapphi-red avatar Nov 14 '25 03:11 sapphi-red

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 agree. For now, we can enable the taggedTemplateTransform plugin to work around this problem until we disable the behavior of escaping

Dunqing avatar Nov 14 '25 07:11 Dunqing

codegen should not escape </script inside 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.

overlookmotel avatar Nov 14 '25 16:11 overlookmotel

Partially fixed in #15664. Follow-up required to fix an edge case bug.

overlookmotel avatar Nov 17 '25 11:11 overlookmotel