whatwg / html

HTML Standard
https://html.spec.whatwg.org/multipage/
Other
8.09k stars 2.66k forks source link

Mark `document.write()` as obsolete #7977

Open zcorpan opened 2 years ago

zcorpan commented 2 years ago

The document.write() API blocks the HTML parser (or rather, <script> blocks the HTML parser because the script might use document.write()) and can cause significant slowness for users (in particular when writing a <script src> which also calls document.write(), and again multiple levels deep). It's also responsible for significant implementation complexity to support (nested invocations of the parser, the need for speculative parsing...).

The spec has this warning:

This method has very idiosyncratic behavior. In some cases, this method can affect the state of the HTML parser while the parser is running, resulting in a DOM that does not correspond to the source of the document (e.g. if the string written is the string "<plaintext>" or "<!--"). In other cases, the call can clear the current page first, as if document.open() had been called. In yet more cases, the method is simply ignored, or throws an exception. Users agents are explicitly allowed to avoid executing script elements inserted via this method. And to make matters even worse, the exact behavior of this method can in some cases be dependent on network latency, which can lead to failures that are very hard to debug. For all these reasons, use of this method is strongly discouraged.

https://html.spec.whatwg.org/multipage/dynamic-markup-insertion.html#document.write()

Yet, this API is not marked as an obsolete feature. Why not?

MDN doesn't specifically discourage the use of document.write(): https://developer.mozilla.org/en-US/docs/Web/API/Document/write

I'm aware of the following issue that could be argued should block obsoleting document.write():

Are there any other reasons?

(Note that I'm not suggesting that support should be removed. That would not be web-compatible.)

cc @whatwg/html-parser

domenic commented 2 years ago

What are you suggesting specifically by saying "marked as an obsolete feature"?

zcorpan commented 2 years ago

That the IDL

  // dynamic markup insertion
  [CEReactions] Document open(optional DOMString unused1, optional DOMString unused2); // both arguments are ignored
  WindowProxy? open(USVString url, DOMString name, DOMString features);
  [CEReactions] undefined close();
  [CEReactions] undefined write(DOMString... text);
  [CEReactions] undefined writeln(DOMString... text);

and relevant spec text are moved into the Obsolete features section (maybe a new subsection for dynamic markup insertion).

domenic commented 2 years ago

What would the goal of such a move be?

Note also that right now the "Obsolete features" section contains:

This would be the first instance of do-something methods in that section, that aren't related to a non-conforming HTML element.

zcorpan commented 2 years ago

document.all at least is a do-something obsolete API, not associated with a particular element.

The goal is to more clearly be opinionated about the API having the same obsolete status as document.all and have that fact trickle to other documentation like MDN, BCD, and similar.

zcorpan commented 2 years ago

The user-centric goal is to drive down usage and nudge developers towards alternative patterns that don't block the HTML parser, which should make the web less slow for users.

The long-term implementer-centric goal is to drive down usage over time until it's low enough that support can be removed completely. I don't expect this to happen anytime soon, if at all, though.

domenic commented 2 years ago

document.all at least is a do-something obsolete API, not associated with a particular element.

It's not in the obsolete section.

The user-centric goal is to drive down usage and nudge developers towards alternative patterns that don't block the HTML parser, which should make the web less slow for users.

I think MDN might be the best place for that? Or we could consider adding a "this feature is in the process of being removed from the web platform. (This is a long process that takes many years.)" box like we did for document.domain, but it feels a bit early for that.

zcorpan commented 2 years ago

It's not in the obsolete section.

Yes it is: https://html.spec.whatwg.org/multipage/obsolete.html#dom-document-all

The spec for HTMLAllCollection is not in the obsolete section, though, indeed.

I think MDN might be the best place for that? Or we could consider adding a "this feature is in the process of being removed from the web platform. (This is a long process that takes many years.)" box like we did for document.domain, but it feels a bit early for that.

I think we shouldn't say that it's in the process of being removed until it actually is plausible that it can be removed. It can be marked as obsolete even if it's never removed (like <font> or document.all).

meyerweb commented 2 years ago

Speaking with my Open Web Docs member/MDN contributor hat on, I don’t see a problem with marking the MDN page with warnings and obsolete banners and what-all, and offer myself as tribute to add them if that’s judged to be a good idea by the group.

zcorpan commented 2 years ago

I think the spec should be the source of truth for which APIs are obsolete or not obsolete, not MDN.

hsivonen commented 2 years ago

Has usage in newly-authored content and the availability of reasonable alternatives with similar author ergonomics been surveyed recently?

zcorpan commented 2 years ago

The blocking=render attribute is not yet shipped by anyone per https://chromestatus.com/feature/5452774595624960

The feature proposed in #7976 would also need to be shipped for developers to have an alternative for conditionally including module scripts that block rendering.

I don't see a chromium use counter for document.write/ln. Am I missing it? If not, is there interest in adding one?

annevk commented 2 years ago

This might be the wrong place to bring this up, but similar to not liking Appendix B in ECMAScript, I'm not a fan of HTML's Obsolete features. I'd prefer we figure out some consistent terminology across WHATWG standards (harmonize legacy/deprecated/obsolete; it seems historical already got removed) and settle for inline annotations. So features are still described as part of a larger whole, but it's clear when they're best not used.

sideshowbarker commented 2 years ago

I'd prefer we figure out some consistent terminology across WHATWG standards (harmonize legacy/deprecated/obsolete; it seems historical already got removed) and settle for inline annotations. So features are still described as part of a larger whole, but it's clear when they're best not used.

I’d suggest considering to harmonize on the term “discouraged”.

For MDN we’ve had a similar need, and some rough consensus around moving to “discouraged” has emerged.

If the HTML spec and MDN were to both move to using “discouraged”, that’d be some very nice harmony.

zcorpan commented 2 years ago

Would obsolete elements also be "discouraged"? Currently the spec says obsolete elements and attributes must not be used (but doesn't seem to say that APIs in that section must not be used).

sideshowbarker commented 2 years ago

Would obsolete elements also be "discouraged"? Currently the spec says obsolete elements and attributes must not be used (but doesn't seem to say that APIs in that section must not be used).

For the HTML spec it seems if something’s already marked as obsolete, it’d be redundant to also mark it as “discouraged”.

(For MDN, we no longer use “obsolete” at all, and what we’re considering is to replace “deprecated” with “discouraged”.)

zcorpan commented 2 years ago

How about a WebIDL extended attribute [Obsolete] or [Legacy] which means

annevk commented 2 years ago

I think @domenic didn't like that last time it was suggested (by @saschanaz?) as it had no normative implications, but maybe "optionally call console.warn" suffices?

(If we go with "discouraged" though the IDL attribute should match that naming.)

zcorpan commented 2 years ago

"Discouraged" is used in HTML today for intentionally non-normative discouragement. We could change that, but I think if it means "must not use" (like obsolete elements), then "discouraged" doesn't seem like an appropriate term. But maybe such APIs should be "should not use" instead?

14 instances of "discouraged" ``` % git grep -i -C 3 discouraged source source- source-

The only remaining presentational markup features in HTML are the style attribute and the style element. Use of the style attribute is somewhat discouraged in production environments, but source- it can be useful for rapid prototyping (where its rules can be directly moved into a separate source- style sheet later) and for providing specific styles in unusual cases where a separate style sheet source- would be inconvenient. Similarly, the style element can be useful in syndication or -- source- source-

source-

Some authors like to write files that can be interpreted as both XML and HTML with similar source: results. Though this practice is discouraged in general due to the myriad of subtle source- complications involved (especially when involving scripting, styling, or any kind of automated source- serialization), this specification has a few restrictions intended to at least somewhat mitigate source- the difficulties. This makes it easier for authors to use this as a transitionary step when -- source-

Extensibility

source- source-

Vendor-specific proprietary user agent extensions to this specification are strongly source: discouraged. Documents must not use such extensions, as doing so reduces interoperability and source- fragments the user base, allowing only users of specific user agents to access the content in source- question.

source- -- source- source-
source- source:

For example, while strongly discouraged from doing so, an implementation could add a new IDL source- attribute "typeTime" to a control that returned the time it took the user source- to select the current value of a control (say). On the other hand, defining a new control that source- appears in a form's elements array would be in violation -- source-

  • "From the contents of the 'simple module graph' figure..."

  • source- source-
  • "In the figure below..." (but this is source: discouraged)

  • source- source-
    source- -- source- source- source-

    Relying on the title attribute is currently source: discouraged as many user agents do not expose the attribute in an accessible manner as required by source- this specification (e.g., requiring a pointing device such as a mouse to cause a tooltip to source- appear, which excludes keyboard-only users and touch-only users, such as anyone with a modern source- phone or tablet).

    -- source- <p>...</p> source-</section> source- source:

    In such cases it is unnecessary (and indeed discouraged) to include a reference to the source- presence of the image itself in the alternative text, since such text would be redundant with source- the browser itself reporting the presence of the image. For example, if the alternative text source- was "A photo of Isaac Asimov", then a conforming user agent might read that out as "(Image) A -- source- source- source-

    Relying on the title attribute is currently source: discouraged as many user agents do not expose the attribute in an accessible manner as source- required by this specification (e.g. requiring a pointing device such as a mouse to cause a source- tooltip to appear, which excludes keyboard-only users and touch-only users, such as anyone source- with a modern phone or tablet).

    -- source- source- source-

    Unfortunately, relying on the title attribute is source: currently discouraged as many user agents do not expose the attribute in an accessible manner as source- required by this specification (e.g. requiring a pointing device such as a mouse to cause a source- tooltip to appear, which excludes keyboard-only users and touch-only users, such as anyone with a source- modern phone or tablet).

    -- source-
    element.blur()
    source- source-
    source:

    Moves the focus to the viewport. Use of this method is discouraged; if you want source- to focus the viewport, call the focus() method on source- the Document's document element.

    source- -- source- because it automatically picks the right event loop and, where appropriate, document. Older specifications often use queue a source- task combined with the implied event loop and implied document source: concepts, but this is discouraged.

    source- source-

    Putting this all together, we can provide a template for a typical algorithm that needs to do source- work asynchronously:

    -- source- source- source- -->, which can lead to failures that are very hard to debug. For all these reasons, use source: of this method is strongly discouraged.

    source- source-

    Throws an "InvalidStateError" DOMException when source- invoked on XML documents.

    -- source- data-x="concept-encoding-confidence">confidence tentative. source-

    source- source:

    User agents are generally discouraged from attempting to autodetect encodings source- for resources obtained over the network, since doing so involves inherently non-interoperable source- heuristics. Attempting to detect encodings based on an HTML document's preamble is especially source- tricky since HTML markup typically uses only ASCII characters, and HTML documents tend to begin -- source- circumstances, conformance checkers must warn the user when the following features are used in a source- document. These are generally old obsolete features that have no effect, and are allowed only to source- distinguish between likely mistakes (regular conformance errors) and mere vestigial markup or source: unusual and discouraged practices (these warnings).

    source- source-

    The following features must be categorized as described source- above:

    ```
    saschanaz commented 2 years ago

    I think @domenic didn't like that last time it was suggested (by @saschanaz?) as it had no normative implications, but maybe "optionally call console.warn" suffices?

    (Yeah, that was https://github.com/whatwg/webidl/issues/910 and https://github.com/whatwg/webidl/pull/929.)

    domenic commented 2 years ago

    So we seem to be discussing a lot of related areas, all of which are worthwhile. Let me try to give a summary of the problem statement/state of things.

    I'll use the word "discouraged" as a general word, and "HTML-discouraged" to refer to the specific sense the HTML spec uses it per @zcorpan's comment https://github.com/whatwg/html/issues/7977#issuecomment-1145922942.

    zcorpan commented 2 years ago

    HTML also has "obsolete but conforming", which are should not use instead of must not use, and cause warnings in conformance checkers instead of errors.

    zcorpan commented 2 years ago

    @jakearchibald noted in https://twitter.com/jaffathecake/status/1565289125468569601 that document.write can be used as a poor man's streaming parser API (see https://github.com/whatwg/html/issues/2142). So maybe we need to add that to the list of blockers here.