summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/script/html_parser_script_runner.h
blob: d219180da29990fadd757f9b5e0661704dd8fc35 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
/*
 * Copyright (C) 2010 Google, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_HTML_PARSER_SCRIPT_RUNNER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_SCRIPT_HTML_PARSER_SCRIPT_RUNNER_H_

#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_reentry_permit.h"
#include "third_party/blink/renderer/core/script/pending_script.h"
#include "third_party/blink/renderer/platform/bindings/name_client.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/resource_client.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/text/text_position.h"

namespace blink {

class Document;
class Element;
class HTMLParserScriptRunnerHost;
class ScriptLoader;

// HTMLParserScriptRunner is responsible for for arranging the execution of
// script elements inserted by the parser, according to the rules for
// 'An end tag whose tag name is "script"':
// https://html.spec.whatwg.org/C/#scriptEndTag
//
// If a script blocks parsing, this class is responsible for holding it, and
// executing it when required.
//
// An HTMLParserScriptRunner is owned by its host, an HTMLDocumentParser.
class HTMLParserScriptRunner final
    : public GarbageCollected<HTMLParserScriptRunner>,
      public PendingScriptClient,
      public NameClient {
  USING_GARBAGE_COLLECTED_MIXIN(HTMLParserScriptRunner);

 public:
  static HTMLParserScriptRunner* Create(HTMLParserReentryPermit* reentry_permit,
                                        Document* document,
                                        HTMLParserScriptRunnerHost* host) {
    return MakeGarbageCollected<HTMLParserScriptRunner>(reentry_permit,
                                                        document, host);
  }

  HTMLParserScriptRunner(HTMLParserReentryPermit*,
                         Document*,
                         HTMLParserScriptRunnerHost*);
  ~HTMLParserScriptRunner() override;

  // Invoked when the parser is detached.
  //
  // We don't need to call Detach() as a prefinalizer, because PendingScripts
  // are Dispose()d in PendingScripts' prefinalizers.
  void Detach();

  // Processes the passed in script and any pending scripts if possible.
  // This does not necessarily run the script immediately. For instance,
  // execution may not happen until the script loads from the network, or after
  // the document finishes parsing.
  void ProcessScriptElement(Element*,
                            const TextPosition& script_start_position);

  // Invoked when the parsing-blocking script resource has loaded, to execute
  // parsing-blocking scripts.
  void ExecuteScriptsWaitingForLoad(PendingScript*);

  // Invoked when all script-blocking resources (e.g., stylesheets) have loaded,
  // to execute parsing-blocking scripts.
  void ExecuteScriptsWaitingForResources();

  // Invoked when parsing is stopping, to execute any deferred scripts.
  // This includes forced deferred scripts as well as developer deferred
  // scripts.
  bool ExecuteScriptsWaitingForParsing();

  bool HasParserBlockingScript() const;
  bool IsExecutingScript() const {
    return !!reentry_permit_->ScriptNestingLevel();
  }

  // Records metrics related to the parsing phase. To be called when parsing
  // is preparing to stop but before |ExecuteScriptsWaitingForParsing|.
  void RecordMetricsAtParseEnd() const;

  void Trace(Visitor*) override;
  const char* NameInHeapSnapshot() const override {
    return "HTMLParserScriptRunner";
  }

 private:
  // PendingScriptClient
  void PendingScriptFinished(PendingScript*) override;

  void ExecutePendingParserBlockingScriptAndDispatchEvent();
  void ExecutePendingDeferredScriptAndDispatchEvent(PendingScript*);
  void ExecuteParsingBlockingScripts();

  void RequestParsingBlockingScript(ScriptLoader*);
  void RequestDeferredScript(ScriptLoader*);
  void RequestForceDeferredScript(ScriptLoader*);

  // Processes the provided script element, but does not execute any
  // parsing-blocking scripts that may remain after execution.
  void ProcessScriptElementInternal(Element*,
                                    const TextPosition& script_start_position);

  const PendingScript* ParserBlockingScript() const {
    return parser_blocking_script_;
  }

  bool IsParserBlockingScriptReady();

  void PossiblyFetchBlockedDocWriteScript(PendingScript*);

  // Takes and returns the first PendingScript from |waiting_scripts| if it is
  // ready for execution. Otherwise, informs it that |this| is a
  // PendingScriptClient to be informed when it is ready.
  PendingScript* TryTakeReadyScriptWaitingForParsing(
      HeapDeque<Member<PendingScript>>* waiting_scripts);

  scoped_refptr<HTMLParserReentryPermit> reentry_permit_;
  Member<Document> document_;
  Member<HTMLParserScriptRunnerHost> host_;

  // https://html.spec.whatwg.org/C/#pending-parsing-blocking-script
  Member<PendingScript> parser_blocking_script_;

  // Scripts that were force deferred by the defer all script optimization.
  // These scripts will be executed after parsing but before
  // |scripts_to_execute_after_parsing_|.  This is an ordered list.
  // https://crbug.com/976061
  HeapDeque<Member<PendingScript>> force_deferred_scripts_;

  // Scripts that were deferred by the web developer. This is an ordered list.
  // https://html.spec.whatwg.org/C/#list-of-scripts-that-will-execute-when-the-document-has-finished-parsing
  HeapDeque<Member<PendingScript>> scripts_to_execute_after_parsing_;

  // Whether this class has suspended async script execution. This will happen
  // when |force_deferred_scripts_| is not empty in order to let the force
  // deferred scripts execute before any async scripts.
  bool suspended_async_script_execution_ = false;

  DISALLOW_COPY_AND_ASSIGN(HTMLParserScriptRunner);
};

}  // namespace blink

#endif