<commit_before>import { dep, OptimisticDependencyFunction } from 'optimism';
import { isReference } from '../../utilities/graphql/storeUtils';
import { NormalizedCache, NormalizedCacheObject, StoreObject } from './types';

const hasOwn = Object.prototype.hasOwnProperty;

type DependType = OptimisticDependencyFunction<string> | null;

export abstract class EntityCache implements NormalizedCache {
  protected data: NormalizedCacheObject = Object.create(null);

  // It seems like this property ought to be protected rather than public,
  // but TypeScript doesn't realize it's inherited from a shared base
  // class by both Root and Layer classes, so Layer methods are forbidden
  // from accessing the .depend property of an arbitrary EntityCache
  // instance, because it might be a Root instance (and vice-versa).
  public readonly depend: DependType = null;

  public abstract addLayer(
    layerId: string,
    replay: (layer: EntityCache) => any,
  ): EntityCache;

  public abstract removeLayer(layerId: string): EntityCache;

  // Although the EntityCache class is abstract, it contains concrete
  // implementations of the various NormalizedCache interface methods that
  // are inherited by the Root and Layer subclasses.

  public toObject(): NormalizedCacheObject {
    return { ...this.data };
  }

  public has(dataId: string): boolean {
    return hasOwn.call(this.data, dataId);
  }

  public get(dataId: string): StoreObject {
    if (this.depend) this.depend(dataId);
    return this.data[dataId]!;
  }

  public set(dataId: string, value: StoreObject): void {
    if (!hasOwn.call(this.data, dataId) || value !== this.data[dataId]) {
      this.data[dataId] = value;
      delete this.refs[dataId];
      if (this.depend) this.depend.dirty(dataId);
    }
  }

  public delete(dataId: string): void {
    delete this.data[dataId];
    delete this.refs[dataId];
    if (this.depend) this.depend.dirty(dataId);
  }

  public clear(): void {
    this.replace(null);
  }

  public replace(newData: NormalizedCacheObject | null): void {
    Object.keys(this.data).forEach(dataId => {
      if (!(newData && hasOwn.call(newData, dataId))) {
        this.delete(dataId);
      }
    });
    if (newData) {
      Object.keys(newData).forEach(dataId => {
        this.set(dataId, newData[dataId]);<commit_msg>Comment about why retainment counts are not reset by deletion.<commit_after>import { dep, OptimisticDependencyFunction } from 'optimism';
import { isReference } from '../../utilities/graphql/storeUtils';
import { NormalizedCache, NormalizedCacheObject, StoreObject } from './types';

const hasOwn = Object.prototype.hasOwnProperty;

type DependType = OptimisticDependencyFunction<string> | null;

export abstract class EntityCache implements NormalizedCache {
  protected data: NormalizedCacheObject = Object.create(null);

  // It seems like this property ought to be protected rather than public,
  // but TypeScript doesn't realize it's inherited from a shared base
  // class by both Root and Layer classes, so Layer methods are forbidden
  // from accessing the .depend property of an arbitrary EntityCache
  // instance, because it might be a Root instance (and vice-versa).
  public readonly depend: DependType = null;

  public abstract addLayer(
    layerId: string,
    replay: (layer: EntityCache) => any,
  ): EntityCache;

  public abstract removeLayer(layerId: string): EntityCache;

  // Although the EntityCache class is abstract, it contains concrete
  // implementations of the various NormalizedCache interface methods that
  // are inherited by the Root and Layer subclasses.

  public toObject(): NormalizedCacheObject {
    return { ...this.data };
  }

  public has(dataId: string): boolean {
    return hasOwn.call(this.data, dataId);
  }

  public get(dataId: string): StoreObject {
    if (this.depend) this.depend(dataId);
    return this.data[dataId]!;
  }

  public set(dataId: string, value: StoreObject): void {
    if (!hasOwn.call(this.data, dataId) || value !== this.data[dataId]) {
      this.data[dataId] = value;
      delete this.refs[dataId];
      if (this.depend) this.depend.dirty(dataId);
    }
  }

  public delete(dataId: string): void {
    delete this.data[dataId];
    delete this.refs[dataId];
    // Note that we do not delete the this.rootIds[dataId] retainment
    // count for this ID, since an object with the same ID could appear in
    // the cache again, and should not have to be retained again.
    // delete this.rootIds[dataId];
    if (this.depend) this.depend.dirty(dataId);
  }

  public clear(): void {
    this.replace(null);
  }

  public replace(newData: NormalizedCacheObject | null): void {
    Object.keys(this.data).forEach(dataId => {
      if (!(newData && hasOwn.call(newData, dataId))) {
        this.delete(dataId);
      }
    });
    if (newData) {
      Object.keys(newData).forEach(dataId => {
        this.set(dataId, newData[dataId]);
{'fraction_non_alphanumeric': 0.11117861482381532, 'fraction_numerical': 0.0, 'mean_word_length': 3.6419172932330826, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6592742', 'n_tokens_mistral': 1436, 'n_tokens_neox': 1392, 'n_words': 444}