Upgrade to Pro — share decks privately, control downloads, hide ads and more …

document.write再考

 document.write再考

English Abstract
This document revisits the document.write method, exploring its functionality, application, and relevance in contemporary web development. Authored by Taketoshi Aono, a Development Lead at AI Shift Corporation and a contributor to the V8 JavaScript Engine, it provides a comprehensive analysis of how document.write inserts HTML fragments into the document, supports broken HTML fragments, and its unique capability to intervene in the browser's rendering process. The document outlines the advantages of using document.write, such as its ability to guarantee completion of processes before page display, making it suitable for measurement tags and essential pre-rendering processes. However, it also addresses significant drawbacks, including the synchronous loading requirement of external scripts and the potential to disrupt page rendering. The discussion extends to browser interventions in document.write usage under specific conditions and explores alternative approaches to asynchronous script loading. The document concludes by examining the challenges in utilizing document.write effectively without compromising web performance and security.

日本語の抄録
この文書では、document.write メソッドを再考察し、その機能、応用、および現代のWeb開発における関連性について探求します。AI Shift Corporationの開発リードであり、V8 JavaScript Engineのコントリビューターである青野健利によって執筆されたこの文書は、document.writeがドキュメントにHTMLフラグメントを挿入する方法、壊れたHTMLフラグメントをサポートする能力、そしてブラウザのレンダリングプロセスに介入する独自の能力について包括的な分析を提供します。document.writeの使用に関する利点、例えばページ表示前にプロセスの完了を保証する能力について説明し、これが計測タグやレンダリング前の必須プロセスに適している理由を概説しています。しかし、外部スクリプトの同期的なロードが必要であり、ページのレンダリングを妨げる可能性があるなど、重要な欠点も取り上げています。特定の条件下でのブラウザによるdocument.writeの使用への介入や、非同期スクリプトローディングへの代替アプローチについての議論も展開されています。この文書は、Webパフォーマンスとセキュリティを損なうことなくdocument.writeを効果的に利用することの課題を検討することで締めくくられます。

More Decks by Taketoshi Aono(青野健利 a.k.a brn)

Other Decks in Programming

Transcript

  1. Who Name 青野健利 GitHub @brn Twitter @brn227 What Dev Lead

    at 株式会社AI Shift Contributor of V8 Javascript Engine
  2. document.writeのspec Cons of document.write 1.If document is an XML document,

    then throw an "InvalidStateError" DOMException. 2.If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException. 3.If document's active parser was aborted is true, then return. 4.If the insertion point is unde fi ned, then: 1.If document's unload counter is greater than 0 or document's ignore-destructive-writes counter is greater than 0, then return. 2.Run the document open steps with document. 5.Insert input into the input stream just before the insertion point. 6.If document's pending parsing-blocking script is null, then have the HTML parser process input, one code point at a time, processing resulting tokens as they are emitted, and stopping when the tokenizer reaches the insertion point or when the processing of the tokenizer is aborted by the tree construction stage (this can happen if a script end tag token is emitted by the tokenizer).
  3. document.writeのspec Cons of document.write If the insertion point is unde

    fi ned, then: 1.If document's unload counter is greater than 0 or document's ignore- destructive-writes counter is greater than 0, then return. 2.Run the document open steps with document.
  4. Spec of document.open document.open 1. If document is an XML

    document, then throw an "InvalidStateError" DOMException exception. 2. If document's throw-on-dynamic-markup-insertion counter is greater than 0, then throw an "InvalidStateError" DOMException. 3. Let entryDocument be the entry global object's associated Document. 4. If document's origin is not same origin to entryDocument's origin, then throw a "SecurityError" DOMException. 5. If document has an active parser whose script nesting level is greater than 0, then return document.
 This basically causes document.open() to be ignored when it's called in an inline script found during parsing, while still letting it have an e ff ect when called from a non-parser task such as a timer callback or event handler. 6. Similarly, if document's unload counter is greater than 0, then return document.
 This basically causes document.open() to be ignored when it's called from a beforeunload, pagehide, or unload event handler while the Document is being unloaded. 7. If document's active parser was aborted is true, then return document.
 This notably causes document.open() to be ignored if it is called after a navigation has started, but only during the initial parse. See issue #4723 for more background. 8. If document's node navigable is non-null and document's node navigable's ongoing navigation is a navigation ID, then stop loading document's node navigable. 9. For each shadow-including inclusive descendant node of document, erase all event listeners and handlers given node. 10. If document is the associated Document of document's relevant global object, then erase all event listeners and handlers given document's relevant global object. 11. Let oldFlag be the value of document's fi re mutation events fl ag. 12. Set document's fi re mutation events fl ag to false. 13. Replace all with null within document. 14. Set document's fi re mutation events fl ag to oldFlag. 15. If document is fully active, then: 1. Let newURL be a copy of entryDocument's URL. 2. If entryDocument is not document, then set newURL's fragment to null. 3. Run the URL and history update steps with document and newURL. 16. Set document's is initial about:blank to false. 17. If document's iframe load in progress fl ag is set, then set document's mute iframe load fl ag. 18. Set document to no-quirks mode. 19. Create a new HTML parser and associate it with document. This is a script-created parser (meaning that it can be closed by the document.open() and document.close() methods, and that the tokenizer will wait for an explicit call to document.close() before emitting an end-of- fi le token). The encoding con fi dence is irrelevant. 20. Set the insertion point to point at just before the end of the input stream (which at this point will be empty). 21. Update the current document readiness of document to "loading".
 This causes a readystatechange event to fi re, but the event is actually unobservable to author code, because of the previous step which erased all event listeners and handlers that could observe it. 22. Return document.
  5. document.writeへの介入しない条件 document.write alternate • ユーザーの接続速度に問題がない • iframe 内の document.write スクリプトの場合

    • async 属性または defer 属性が指定されたscript • eTLD+1 が一致するスクリプト(www.example.org に挿入された js.example.org でホストされているスクリプトなど) • スクリプトがブラウザの HTTP キャッシュに存在する • 再読み込みの場合
  6. <html blocking="render"> <script> // The set of element IDs that

    should block rendering. let blockingElementIds = new Set(); function maybeUnblockRendering() { if (blockingElementIds.size == 0) { document.documentElement.blocking=""; } } // The value returned by getState() is set by the old Document. // For example, using IntersectionObserver. // // It tracks whether the old Document added a `view-transition-name` // to the header based on its visibility. if (navigation.initialLoad.from().getState().morphHeader) { blockingElementIds.add("header-id"); } maybeUnblockRendering(); </script> <body> … <div id="header-id"> ... </div> <script> // When an element is parsed, remove it from the blocking set and // unblock rendering if all blocking elements have been parsed. blockingElementIds.delete("header-id"); maybeUnblockRendering(); </script> </body> </html>