current commit
261004.7 · deps: update V8 to 15.2.124.38
// Copyright 2026 the V8 project 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 V8_OBJECTS_JS_DATA_OBJECT_BUILDER_H_
#define V8_OBJECTS_JS_DATA_OBJECT_BUILDER_H_

#include "src/common/globals.h"
#include "src/handles/handles.h"
#include "src/objects/elements-kind.h"
#include "src/objects/map.h"

namespace v8 {
namespace internal {

// An iterator for JSDataObjectBuilder which can lazily create internalized
// strings for the keys, and otherwise presents a vector of characters. Useful
// for creating objects in parsers.
//
// ```
// struct Iterator {
//   static constexpr bool kSupportsRawKeys = true;
//
//   // Whether the iterator might return the same key multiple times.
//   static constexpr bool kMayHaveDuplicateKeys;
//
//   void Advance();
//   bool Done();
//
//   // Get the characters of the key of the current property, assuming that
//   // the heap string is not yet allocated (e.g. during parsing).
//   base::Vector<const Char> GetKeyChars();
//
//   // Get the key of the current property, optionally returning the hinted
//   // expected key if applicable, to avoid an allocation.
//   Handle<InternalizedString> GetKey(
//       Handle<InternalizedString> expected_key_hint);
//
//   // Get the value of the current property. `will_revisit_value` is true
//   // if this value will need to be revisited later via RevisitValues().
//   Handle<Object> GetValue(bool will_revisit_value);
//
//   // Return an iterator over the values that were already visited by
//   // GetValue. Might require caching those values if necessary.
//   ValueIterator RevisitValues();
// }
// ```
template <typename PropertyIterator>
concept JSDataPropertyIteratorWithRawKeys =
    std::remove_reference_t<PropertyIterator>::kSupportsRawKeys &&
    requires(PropertyIterator it, Handle<InternalizedString> key_hint) {
      it.Advance();
      it.Done();
      it.kMayHaveDuplicateKeys;
      it.GetKeyChars();
      it.GetKey(key_hint);
      it.GetValue(true);
      it.RevisitValues();
    };

// An iterator for JSDataObjectBuilder which has already eagerly created
// internalized strings for the keys, Useful for creating objects from existing
// descriptors.
//
// ```
// struct Iterator {
//   static constexpr bool kSupportsRawKeys = false;
//
//   // Whether the iterator might return the same key multiple times.
//   static constexpr bool kMayHaveDuplicateKeys;
//
//   void Advance();
//   bool Done();
//
//   // Get the key of the current property, already allocated and
//   // internalized.
//   Handle<InternalizedString> GetKey();
//
//   // Get the value of the current property. `will_revisit_value` is true
//   // if this value will need to be revisited later via RevisitValues().
//   Handle<Object> GetValue(bool will_revisit_value);
//
//   // Return an iterator over the values that were already visited by
//   // GetValue. Might require caching those values if necessary.
//   ValueIterator RevisitValues();
// }
// ```
template <typename PropertyIterator>
concept JSDataPropertyIteratorWithEagerKeys =
    !std::remove_reference_t<PropertyIterator>::kSupportsRawKeys &&
    requires(PropertyIterator it) {
      it.Advance();
      it.Done();
      it.kMayHaveDuplicateKeys;
      it.GetKey();
      it.GetValue(true);
      it.RevisitValues();
    };

class JSDataObjectBuilder {
 public:
  // HeapNumberMode determines whether incoming HeapNumber values will be
  // guaranteed to be uniquely owned by this object, and therefore can be used
  // directly as mutable HeapNumbers for double representation fields.
  enum HeapNumberMode {
    kNormalHeapNumbers,
    kHeapNumbersGuaranteedUniquelyOwned
  };
  JSDataObjectBuilder(Isolate* isolate, ElementsKind elements_kind,
                      int expected_named_properties,
                      DirectHandle<Map> expected_final_map,
                      HeapNumberMode heap_number_mode);

  // Builds and returns an object whose properties are based on a property
  // iterator.
  template <JSDataPropertyIteratorWithRawKeys PropertyIterator>
  V8_INLINE Handle<JSObject> BuildFromIterator(
      PropertyIterator&& it,
      MaybeDirectHandle<FixedArrayBase> maybe_elements = {});

  template <JSDataPropertyIteratorWithEagerKeys PropertyIterator>
  V8_INLINE Handle<JSObject> BuildFromIterator(
      PropertyIterator&& it,
      MaybeDirectHandle<FixedArrayBase> maybe_elements = {});

 private:
  template <typename ValueIterator>
  V8_INLINE void CreateAndInitialiseObject(
      ValueIterator&& value_it, DirectHandle<FixedArrayBase> elements);

  void AddSlowProperty(DirectHandle<InternalizedString> key,
                       Handle<Object> value);

  template <typename Char, typename GetKeyFunction, typename GetValueFunction>
  V8_INLINE bool TryAddFastPropertyForValue(
      base::Vector<const Char> key_chars, GetKeyFunction&& get_key,
      GetValueFunction&& get_value, DirectHandle<InternalizedString>* out_key);

  V8_INLINE void RecalculateExtraHeapNumbersNeeded();

  V8_INLINE bool TryAddFastPropertyForValue(
      DirectHandle<InternalizedString> key, DirectHandle<Object> value);

  template <typename Char, typename GetKeyFunction>
  V8_INLINE bool TryFastTransitionToPropertyKey(
      base::Vector<const Char> key_chars, GetKeyFunction&& get_key,
      DirectHandle<InternalizedString>* out_key);

  V8_INLINE bool TryFastTransitionToPropertyKey(
      DirectHandle<InternalizedString> key);

  V8_INLINE bool TryAddFastPropertyTransitionForValue(
      DirectHandle<InternalizedString> key, DirectHandle<Object> value);

  V8_INLINE bool TryGeneralizeFieldToValue(DirectHandle<Object> value);

  bool TryInitializeMapFromExpectedFinalMap();

  void InitializeMapFromZero();

  V8_INLINE bool IsOnExpectedFinalMapFastPath() const;

  void RewindExpectedFinalMapFastPathToBeforeCurrent();

  void RewindExpectedFinalMapFastPathToIncludeCurrent();

  V8_INLINE void RegisterFieldNeedsFreshHeapNumber();
  V8_INLINE void RegisterFieldNeedsFreshHeapNumber(DirectHandle<Object> value);
  V8_INLINE void AdvanceToNextProperty();

  Isolate* isolate_;
  ElementsKind elements_kind_;
  int expected_property_count_;
  HeapNumberMode heap_number_mode_;
  bool may_have_duplicate_keys_ = true;

  DirectHandle<Map> map_;
  int current_property_index_ = 0;
  uint32_t extra_heap_numbers_needed_ = 0;

  Handle<JSObject> object_;

  DirectHandle<Map> expected_final_map_ = {};
  int property_count_in_expected_final_map_ = 0;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_OBJECTS_JS_DATA_OBJECT_BUILDER_H_