File: subscriber.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,806; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (128 lines) | stat: -rw-r--r-- 5,597 bytes parent folder | download | duplicates (3)
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
// Copyright 2023 The Chromium Authors
// 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_DOM_SUBSCRIBER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SUBSCRIBER_H_

#include "base/types/pass_key.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/forward.h"

namespace blink {

class AbortController;
class ObservableInternalObserver;
class Observable;
class ScriptState;
class SubscribeOptions;
class V8VoidFunction;

class CORE_EXPORT Subscriber final : public ScriptWrappable,
                                     public ExecutionContextClient {
  DEFINE_WRAPPERTYPEINFO();

 public:
  Subscriber(base::PassKey<Observable>,
             ScriptState*,
             ObservableInternalObserver*,
             SubscribeOptions*);

  // API methods.
  void next(ScriptValue);
  void complete(ScriptState*);
  void error(ScriptState*, ScriptValue);
  void addTeardown(V8VoidFunction*);

  // API attributes.
  bool active() const { return active_; }
  AbortSignal* signal() const;

  void RegisterNewObserver(ScriptState* script_state,
                           ObservableInternalObserver*,
                           SubscribeOptions*);

  void Trace(Visitor*) const override;

 private:
  class ConsumerAbortSubscriptionAlgorithm;

  // Called when the `AbortSignal` associated with one of the
  // `internal_observers_` aborts its subscription. When the producer closes the
  // subscription first, this method does nothing because it is guarded by an
  // `active_` check.
  void ConsumerUnsubscribe(ScriptState* script_state,
                           ObservableInternalObserver* associated_observer,
                           std::optional<ScriptValue> abort_reason);

  // This method is idempotent; it may be called more than once, re-entrantly,
  // which is safe, because it is guarded by an `active_` check. See the
  // implementation's documentation.
  //
  // The `abort_reason` parameter is an error value that serves as the abort
  // reason for when this method aborts `subscription_controller_`. It is
  // populated in two cases:
  //   1. Consumer-initiated unsubscription: when `ConsumerUnsubscribe()` is
  //      called by the *last* consumer `AbortSignal`, then
  //      `CloseSubscription()` is called with its abort reason.
  //   2. Producer-initiated unsubscription: when `Subscriber::error()` is
  //      called, `abort_reason` takes on the provided error value, so that the
  //      producer error is communicated through to `this`'s signal and any
  //      upstream signals.
  void CloseSubscription(ScriptState* script_state,
                         std::optional<ScriptValue> abort_reason);

  // The list of `ObservableInternalObserver`s which encapsulate algorithms to
  // call when `this` produces values or actions that need to be pushed to the
  // subscriber handlers.
  //
  // https://wicg.github.io/observable/#subscriber-next-algorithm:
  // "Each Subscriber has a next algorithm, which is a next steps-or-null."
  //
  // https://wicg.github.io/observable/#subscriber-error-algorithm:
  // "Each Subscriber has a error algorithm, which is an error steps-or-null."

  // https://wicg.github.io/observable/#subscriber-complete-algorithm:
  // "Each Subscriber has a complete algorithm, which is a complete
  // steps-or-null."
  HeapVector<Member<ObservableInternalObserver>> internal_observers_;
  // This is a subset of `internal_observers_`; specifically, for each internal
  // observer that has an associated `AbortSignal`, we own the `AbortSignal`'s
  // algorithm handle in `consumer_abort_algorithms_` to keep the algorithm
  // alive. Then when the abort algorithm finally runs, the algorithm tells
  // `ConsumerAbortSubscription()` which observer it was associated, and we can
  // clear the algorithm's handle from `consumer_abort_algorithms_`, since it no
  // longer needs to be kept alive.
  HeapHashMap<Member<ObservableInternalObserver>,
              Member<AbortSignal::AlgorithmHandle>>
      consumer_abort_algorithms_;

  // This starts out true, and becomes false only once `Subscriber::{complete(),
  // error()}` are called (just before the corresponding `Observer` callbacks
  // are invoked) or once the subscriber unsubscribes by aborting the
  // `AbortSignal` that it passed into `Observable::subscribe()`.
  bool active_ = true;

  // `subscription_controller_` is aborted in two cases:
  //   1. Producer-initiated unsubscription: when `error()`/`complete()` are
  //      called, they invoke `CloseSubscription()` directly, which aborts this
  //      controller.
  //   2. Consumer-initiated unsubscription: when the downstream `AbortSignal`
  //      is aborted, the `ConsumerAbortSubscriptionAlgorithm` runs, invoking
  //      `CloseSubscription()`, which aborts this controller.
  //
  // This controller's signal is what `this` exposes as the `signal` WebIDL
  // attribute.
  Member<AbortController> subscription_controller_;

  HeapVector<Member<V8VoidFunction>> teardown_callbacks_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_DOM_SUBSCRIBER_H_