summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h
blob: 811d843ada72465d09d420d47c5dda9a441b3720 (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
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_TREE_LINKER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_LOADER_MODULESCRIPT_MODULE_TREE_LINKER_H_

#include "third_party/blink/public/platform/web_url_request.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/script/modulator.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_member.h"
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
#include "third_party/blink/renderer/platform/weborigin/kurl_hash.h"
#include "third_party/blink/renderer/platform/wtf/hash_set.h"

namespace blink {

class ModuleScriptFetchRequest;
class ModuleTreeLinkerRegistry;

// A ModuleTreeLinker is responsible for running and keeping intermediate states
// for a top-level [IMSGF] "internal module script graph fetching procedure" or
// a top-level [FDaI] "fetch the descendants of and instantiate", and all the
// invocations of [IMSGF] and [FD] "fetch the descendants" under that.
//
// Spec links:
// [IMSGF]
// https://html.spec.whatwg.org/#internal-module-script-graph-fetching-procedure
// [FD]
// https://html.spec.whatwg.org/#fetch-the-descendants-of-a-module-script
// [FDaI]
// https://html.spec.whatwg.org/#fetch-the-descendants-of-and-instantiate-a-module-script
// [FFPE]
// https://html.spec.whatwg.org/#finding-the-first-parse-error
class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
 public:
  // https://html.spec.whatwg.org/#fetch-a-module-script-tree
  //
  // TODO(hiroshige): |base_url| is used only for Layered APIs and will be
  // removed soon once an upcoming spec change lands.
  static ModuleTreeLinker* Fetch(const KURL&,
                                 const KURL& base_url,
                                 WebURLRequest::RequestContext destination,
                                 const ScriptFetchOptions&,
                                 Modulator*,
                                 ModuleTreeLinkerRegistry*,
                                 ModuleTreeClient*);

  // [FDaI] for an inline script.
  static ModuleTreeLinker* FetchDescendantsForInlineScript(
      ModuleScript*,
      WebURLRequest::RequestContext destination,
      Modulator*,
      ModuleTreeLinkerRegistry*,
      ModuleTreeClient*);

  ~ModuleTreeLinker() override = default;
  void Trace(blink::Visitor*) override;
  void TraceWrappers(ScriptWrappableVisitor*) const override;

  bool IsFetching() const {
    return State::kFetchingSelf <= state_ && state_ < State::kFinished;
  }
  bool HasFinished() const { return state_ == State::kFinished; }

 private:
  ModuleTreeLinker(WebURLRequest::RequestContext destination,
                   Modulator*,
                   ModuleTreeLinkerRegistry*,
                   ModuleTreeClient*);

  enum class State {
    kInitial,
    // Running fetch of the module script corresponding to the target node.
    kFetchingSelf,
    // Running fetch of descendants of the target node.
    kFetchingDependencies,
    // Instantiating module_script_ and the node descendants.
    kInstantiating,
    kFinished,
  };
#if DCHECK_IS_ON()
  static const char* StateToString(State);
#endif
  void AdvanceState(State);

  void FetchRoot(const KURL&, const KURL& base_url, const ScriptFetchOptions&);
  void FetchRootInline(ModuleScript*);

  // Steps 1--2 of [IMSGF].
  void InitiateInternalModuleScriptGraphFetching(
      const ModuleScriptFetchRequest&,
      ModuleGraphLevel);

  // Steps 3--7 of [IMSGF], and [FD]/[FDaI] called from [IMSGF].
  // TODO(hiroshige): Currently
  void NotifyModuleLoadFinished(ModuleScript*) override;
  void FetchDescendants(ModuleScript*);

  // Completion of [FD].
  void FinalizeFetchDescendantsForOneModuleScript();

  // [FDaI] Steps 4--8.
  void Instantiate();

  // [FFPE]
  ScriptValue FindFirstParseError(ModuleScript*,
                                  HeapHashSet<Member<ModuleScript>>*) const;

  const WebURLRequest::RequestContext destination_;
  const Member<Modulator> modulator_;
  HashSet<KURL> visited_set_;
  const Member<ModuleTreeLinkerRegistry> registry_;
  const Member<ModuleTreeClient> client_;
  State state_ = State::kInitial;

  // Correspond to _result_ in
  // https://html.spec.whatwg.org/multipage/webappapis.html#internal-module-script-graph-fetching-procedure
  TraceWrapperMember<ModuleScript> result_;

  bool found_parse_error_ = false;

  size_t num_incomplete_fetches_ = 0;

#if DCHECK_IS_ON()
  KURL original_url_;
  KURL url_;
  bool root_is_inline_;

  friend CORE_EXPORT std::ostream& operator<<(std::ostream&,
                                              const ModuleTreeLinker&);
#endif
};

#if DCHECK_IS_ON()
CORE_EXPORT std::ostream& operator<<(std::ostream&, const ModuleTreeLinker&);
#endif

}  // namespace blink

#endif