Subject: Re: master 15a76160bb: Don't throw errors while propertizing in sgml-mode

From: Stefan Monnier <[email-masked]>
Date: Mon, 28 Feb 2022 09:44:01 -0500

>     * lisp/textmodes/sgml-mode.el (sgml-syntax-propertize): Don't
>     throw an error when propertizing (bug#54195).
> ---
>  lisp/textmodes/sgml-mode.el | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/lisp/textmodes/sgml-mode.el b/lisp/textmodes/sgml-mode.el
> index 83631e6475..b49541f47d 100644
> --- a/lisp/textmodes/sgml-mode.el
> +++ b/lisp/textmodes/sgml-mode.el
> @@ -419,11 +419,11 @@ These have to be run via `sgml-syntax-propertize'"))
>  (defun sgml-syntax-propertize (start end &optional rules-function)
>    "Syntactic keywords for `sgml-mode'."
>    (setq sgml--syntax-propertize-ppss (cons start (syntax-ppss start)))
> -  (cl-assert (>= (cadr sgml--syntax-propertize-ppss) 0))
> -  (sgml-syntax-propertize-inside end)
> -  (funcall (or rules-function sgml--syntax-propertize) (point) end)
> -  ;; Catch any '>' after the last quote.
> -  (sgml--syntax-propertize-ppss end))
> +  (when (>= (cadr sgml--syntax-propertize-ppss) 0)
> +    (sgml-syntax-propertize-inside end)
> +    (funcall (or rules-function sgml--syntax-propertize) (point) end)
> +    ;; Catch any '>' after the last quote.
> +    (sgml--syntax-propertize-ppss end)))

Hmm... this isn't right.

The PPSS really shouldn't have a negative value here.  The problem is
that when we do as in the recipe (which does not require
`electric-pair-mode` to reproduce), mhtml calls `sgml-syntax-propertize`
on the `</script>` tag and the `syntax-ppss` call returns the state of
the JS parsing at the end of the JS code rather than the state of the
SGML parsing at the beginning of the tag.

IOW it's a bug in the interaction between `mhtml` and `syntax-ppss`.

To illustrate the problem in a way which doesn't signal an error, try
the following:

    "foo
    <script>
      foo()
    </script>
    "bar
    <foo "hello">

as you can see, the SGML part carefully ignores the " thingies outside
of quotes.  Now remove the closing paren in the JS code: suddenly the
SGML code is all confused because it thinks everything after the open
paren is inside of a tag (because the SGML mode gives paren syntax to <
and > (but not to parens) and uses the paren depth to decide whether
we're inside a tag or not).

        Stefan