summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/core/loader/modulescript/module_tree_linker.h
blob: c4a664b1987501c47e6d051066d26c2dc5b2bc8a (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
// 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/loader/fetch/fetch_client_settings_object_snapshot.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 ModuleTreeLinkerRegistry;

// A ModuleTreeLinker is responsible for running and keeping intermediate states
// for top-level fetch * module script graph spec concepts and all the
// invocations of #internal-module-script-graph-fetching-procedure and
// #fetch-the-descendants-of-a-module-script.
//
// Modulator represents "a module map settings object" and
// ResourceFetcher represents "a fetch client settings object"
// by its |Context()->GetFetchClientSettingsObject()|.
class CORE_EXPORT ModuleTreeLinker final : public SingleModuleClient {
 public:
  // https://html.spec.whatwg.org/C/#fetch-a-module-script-tree
  // https://html.spec.whatwg.org/C/#fetch-a-module-worker-script-tree
  // https://html.spec.whatwg.org/C/#fetch-an-import()-module-script-graph
  static void Fetch(const KURL&,
                    ResourceFetcher* fetch_client_settings_object_fetcher,
                    mojom::RequestContextType context_type,
                    network::mojom::RequestDestination destination,
                    const ScriptFetchOptions&,
                    Modulator*,
                    ModuleScriptCustomFetchType,
                    ModuleTreeLinkerRegistry*,
                    ModuleTreeClient*);

  // https://html.spec.whatwg.org/C/#fetch-an-inline-module-script-graph
  static void FetchDescendantsForInlineScript(
      ModuleScript*,
      ResourceFetcher* fetch_client_settings_object_fetcher,
      mojom::RequestContextType context_type,
      network::mojom::RequestDestination destination,
      Modulator*,
      ModuleScriptCustomFetchType,
      ModuleTreeLinkerRegistry*,
      ModuleTreeClient*);

  ModuleTreeLinker(ResourceFetcher* fetch_client_settings_object_fetcher,
                   mojom::RequestContextType context_type,
                   network::mojom::RequestDestination destination,
                   Modulator*,
                   ModuleScriptCustomFetchType,
                   ModuleTreeLinkerRegistry*,
                   ModuleTreeClient*);
  ~ModuleTreeLinker() override = default;
  void Trace(Visitor*) override;

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

 private:
  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 ScriptFetchOptions&);
  void FetchRootInline(ModuleScript*);

  void NotifyModuleLoadFinished(ModuleScript*) override;
  void FetchDescendants(const ModuleScript*);

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

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

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

  const Member<ResourceFetcher> fetch_client_settings_object_fetcher_;

  const mojom::RequestContextType context_type_;
  const network::mojom::RequestDestination destination_;
  const Member<Modulator> modulator_;
  const ModuleScriptCustomFetchType custom_fetch_type_;
  HashSet<KURL> visited_set_;
  const Member<ModuleTreeLinkerRegistry> registry_;
  const Member<ModuleTreeClient> client_;
  State state_ = State::kInitial;

  // Correspond to _result_ in the top-level fetch * module script graph
  // algorithms.
  Member<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