chromium/third_party/blink/renderer/platform/bindings/observable_array.h

// Copyright 2021 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_PLATFORM_BINDINGS_OBSERVABLE_ARRAY_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_OBSERVABLE_ARRAY_H_

#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/heap_traits.h"
#include "third_party/blink/renderer/platform/heap/member.h"
#include "v8/include/v8-forward.h"

// Overview of Blink implementation of Web IDL observable arrays
//
// Observable arrays are implemented with two objects:
// 1) backing list object
// https://webidl.spec.whatwg.org/#observable-array-attribute-backing-list
// and 2) exotic object.
// https://webidl.spec.whatwg.org/#backing-observable-array-exotic-object
// As DOM objects are implemented with a ScriptWrappable and its V8 wrappers,
// there are a ScriptWrappable of a backing list object and its V8 wrappers,
// also a ScriptWrappable of a exotic object and its (pseudo) V8 wrappers.
//
// By definition, observable array exotic object is a JS Proxy in ECMAScript
// binding.
//
//   let exotic_object = new Proxy(backing_list_object, handler_object);
//
// For web developers, the JS Proxy object is the only visible object.  Web
// developers cannot access the backing list object directly.
//
// For Blink developers, the backing list object looks the primary object.
// However, when exposing an observable array to web developers, the exotic
// object must be exposed instead of the backing list object.  This is done in
// auto-generated bindings (generated bindings automatically call
// GetExoticObject()).
//
//   class MyIdlInterface : public ScriptWrappable {
//    public:
//     V8ObservableArrayNode* myAttr() const {
//       return my_observable_array_;
//     }
//    private:
//     // my_observable_array_ is a backing list object.
//     Member<V8ObservableArrayNode> my_observable_array_;
//   };
//
// Class hierarchy and relationship:
//   bindings::ObservableArrayBase -- the base class of backing list objects
//   +-- bindings::ObservableArrayImplHelper<T> -- just a helper
//       +-- V8ObservableArrayNode -- generated implementation of IDL
//               ObservableArray<Node>.  Bindings code generator produces this
//               class from *.idl files.
//   ObservableArrayExoticObject -- the implementation of exotic objects
//
//   v8_exotic_object (= JS Proxy)
//       --(proxy target)--> v8_array (= JS Array)
//       --(private property)--> v8_backing_list_object
//       --(internal field)--> blink_backing_list_object
//       --(data member)--> blink_exotic_object
//       --(ToV8Traits)--> v8_exotic_object

namespace blink {

class ObservableArrayExoticObject;

namespace bindings {

// ObservableArrayBase is the common base class of all the observable array
// classes, and represents the backing list for an IDL attribute of an
// observable array type (but the actual implementation lives in
// bindings/core/v8/).
// https://webidl.spec.whatwg.org/#observable-array-attribute-backing-list
class PLATFORM_EXPORT ObservableArrayBase : public ScriptWrappable {};

template <typename ElementType>
class ObservableArrayImplHelper : public bindings::ObservableArrayBase {};

}  // namespace bindings

// Represents a backing observable array exotic object.
// https://webidl.spec.whatwg.org/#backing-observable-array-exotic-object
class PLATFORM_EXPORT ObservableArrayExoticObject final
    : public ScriptWrappable {};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_BINDINGS_OBSERVABLE_ARRAY_H_