<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "Scheduler.h"

#include <glog/logging.h>
#include <jsi/jsi.h>

#include <react/core/LayoutContext.h>
#include <react/debug/SystraceSection.h>
#include <react/uimanager/ComponentDescriptorRegistry.h>
#include <react/uimanager/UIManager.h>
#include <react/uimanager/UIManagerBinding.h>
#include <react/uimanager/UITemplateProcessor.h>

namespace facebook {
namespace react {

Scheduler::Scheduler(
    SchedulerToolbox schedulerToolbox,
    SchedulerDelegate *delegate) {
  runtimeExecutor_ = schedulerToolbox.runtimeExecutor;

  reactNativeConfig_ =
      schedulerToolbox.contextContainer
          ->at<std::shared_ptr<const ReactNativeConfig>>("ReactNativeConfig");

  auto uiManager = std::make_shared<UIManager>();
  auto eventOwnerBox = std::make_shared<EventBeat::OwnerBox>();

  auto eventPipe = [uiManager](
                       jsi::Runtime &runtime,
                       const EventTarget *eventTarget,
                       const std::string &type,
                       const ValueFactory &payloadFactory) {
    uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) {
      uiManagerBinding.dispatchEvent(
          runtime, eventTarget, type, payloadFactory);
    });
  };

  auto statePipe = [uiManager](
                       const StateData::Shared &data,
                       const StateTarget &stateTarget) {
    uiManager->updateState(stateTarget.getShadowNode(), data);
  };

  eventDispatcher_ = std::make_shared<EventDispatcher>(
      eventPipe,
      statePipe,
      schedulerToolbox.synchronousEventBeatFactory,
      schedulerToolbox.asynchronousEventBeatFactory,
      eventOwnerBox);

  eventOwnerBox->owner = eventDispatcher_;

  componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory(
      eventDispatcher_, schedulerToolbox.contextContainer);

  rootComponentDescriptor_ =
      std::make_unique<const RootComponentDescriptor>(eventDispatcher_);

  uiManager->setDelegate(this);
  uiManager->setComponentDescriptorRegistry(componentDescriptorRegistry_);

  runtimeExecutor_([=](jsi::Runtime &runtime) {
    auto uiManagerBinding = UIManagerBinding::createAndInstallIfNeeded(runtime);
    uiManagerBinding->attach(uiManager);
  });

  schedulerToolbox.contextContainer->insert(
      "ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE",
      std::weak_ptr<ComponentDescriptorRegistry const>(
          componentDescriptorRegistry_));

  delegate_ = delegate;
  uiManager_ = uiManager;
}

Scheduler::~Scheduler() {
  uiManager_->setDelegate(nullptr);
}

void Scheduler::startSurface(
    SurfaceId surfaceId,
    const std::string &moduleName,
    const folly::dynamic &initialProps,
    const LayoutConstraints &layoutConstraints,
    const LayoutContext &layoutContext) const {
  SystraceSection s("Scheduler::startSurface");

  auto shadowTree = std::make_unique<ShadowTree>(
      surfaceId, layoutConstraints, layoutContext, *rootComponentDescriptor_);
  shadowTree->setDelegate(uiManager_.get());<commit_msg>Fabric: Asserting in ~Scheduler that there is no running Surfaces<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

#include "Scheduler.h"

#include <glog/logging.h>
#include <jsi/jsi.h>

#include <react/core/LayoutContext.h>
#include <react/debug/SystraceSection.h>
#include <react/uimanager/ComponentDescriptorRegistry.h>
#include <react/uimanager/UIManager.h>
#include <react/uimanager/UIManagerBinding.h>
#include <react/uimanager/UITemplateProcessor.h>

namespace facebook {
namespace react {

Scheduler::Scheduler(
    SchedulerToolbox schedulerToolbox,
    SchedulerDelegate *delegate) {
  runtimeExecutor_ = schedulerToolbox.runtimeExecutor;

  reactNativeConfig_ =
      schedulerToolbox.contextContainer
          ->at<std::shared_ptr<const ReactNativeConfig>>("ReactNativeConfig");

  auto uiManager = std::make_shared<UIManager>();
  auto eventOwnerBox = std::make_shared<EventBeat::OwnerBox>();

  auto eventPipe = [uiManager](
                       jsi::Runtime &runtime,
                       const EventTarget *eventTarget,
                       const std::string &type,
                       const ValueFactory &payloadFactory) {
    uiManager->visitBinding([&](UIManagerBinding const &uiManagerBinding) {
      uiManagerBinding.dispatchEvent(
          runtime, eventTarget, type, payloadFactory);
    });
  };

  auto statePipe = [uiManager](
                       const StateData::Shared &data,
                       const StateTarget &stateTarget) {
    uiManager->updateState(stateTarget.getShadowNode(), data);
  };

  eventDispatcher_ = std::make_shared<EventDispatcher>(
      eventPipe,
      statePipe,
      schedulerToolbox.synchronousEventBeatFactory,
      schedulerToolbox.asynchronousEventBeatFactory,
      eventOwnerBox);

  eventOwnerBox->owner = eventDispatcher_;

  componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory(
      eventDispatcher_, schedulerToolbox.contextContainer);

  rootComponentDescriptor_ =
      std::make_unique<const RootComponentDescriptor>(eventDispatcher_);

  uiManager->setDelegate(this);
  uiManager->setComponentDescriptorRegistry(componentDescriptorRegistry_);

  runtimeExecutor_([=](jsi::Runtime &runtime) {
    auto uiManagerBinding = UIManagerBinding::createAndInstallIfNeeded(runtime);
    uiManagerBinding->attach(uiManager);
  });

  schedulerToolbox.contextContainer->insert(
      "ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE",
      std::weak_ptr<ComponentDescriptorRegistry const>(
          componentDescriptorRegistry_));

  delegate_ = delegate;
  uiManager_ = uiManager;
}

Scheduler::~Scheduler() {
#ifndef NDEBUG
  /*
   * This requirement must be satisfied to make concurrent deallocation of
   * `Scheduler` and calling on it from `UIManager` side thread-safe.
   * Conceptually, `UIManager` is allowed to call `Scheduler` only if the
   * corresponding `ShadowTree` instance exists (which is not fully enforced
   * yet).
   */
  auto hasRunningSurfaces = false;
  uiManager_->getShadowTreeRegistry().enumerate(
      [&](ShadowTree const &shadowTree, bool &stop) {
        stop = true;
        hasRunningSurfaces = true;
      });

  assert(
      !hasRunningSurfaces &&
      "Scheduler was destroyed with sill running Surfaces.");
#endif

  uiManager_->setDelegate(nullptr);
}

void Scheduler::startSurface(
    SurfaceId surfaceId,
    const std::string &moduleName,
    const folly::dynamic &initialProps,
    const LayoutConstraints &layoutConstraints,
    const LayoutContext &layoutContext) const {
  SystraceSection s("Scheduler::startSurface");

  auto shadowTree = std::make_unique<ShadowTree>(
      surfaceId, layoutConstraints, layoutContext, *rootComponentDescriptor_);
  shadowTree->setDelegate(uiManager_.get());
{'fraction_non_alphanumeric': 0.09762273174848783, 'fraction_numerical': 0.0, 'mean_word_length': 4.185995623632385, 'pattern_counts': {'":': 0, '<': 35, '<?xml version=': 0, '>': 56, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5551866', 'n_tokens_mistral': 1965, 'n_tokens_neox': 1926, 'n_words': 400}