Giter VIP home page Giter VIP logo

Comments (15)

koba04 avatar koba04 commented on August 19, 2024
  render(element : ReactElement<any>, container : DOMContainerElement) {
    warnAboutUnstableUse();
    if (!container._reactRootContainer) {
      container._reactRootContainer = DOMRenderer.mountContainer(element, container);
    } else {
      DOMRenderer.updateContainer(element, container._reactRootContainer);
    }
  },

In mounting phase, render uses DOMRenderer.mountContainer for mounting a component.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
var DOMRenderer = ReactFiberReconciler({

  updateContainer(container : Container, children : HostChildren<Instance>) : void {
    container.innerHTML = '';
    recursivelyAppendChildren(container, children);
  },

  createInstance(type : string, props : Props, children : HostChildren<Instance>) : Instance {
    const domElement = document.createElement(type);
    recursivelyAppendChildren(domElement, children);
    if (typeof props.children === 'string') {
      domElement.textContent = props.children;
    }
    return domElement;
  },

  prepareUpdate(
    domElement : Instance,
    oldProps : Props,
    newProps : Props,
    children : HostChildren<Instance>
  ) : boolean {
    return true;
  },

  commitUpdate(domElement : Instance, oldProps : Props, newProps : Props, children : HostChildren<Instance>) : void {
    domElement.innerHTML = '';
    recursivelyAppendChildren(domElement, children);
    if (typeof newProps.children === 'string') {
      domElement.textContent = newProps.children;
    }
  },

  deleteInstance(instance : Instance) : void {
    // Noop
  },

  scheduleAnimationCallback: window.requestAnimationFrame,

  scheduleDeferredCallback: window.requestIdleCallback,

});

DOMRenderer is created by ReactFiberReconciler, which is passed configs such as updateContainer, createInstance, prepareUpdate, commitUpdate, deleteInstance, scheduleAnimationCallback and scheduleDeferredCallback.

You can see scheduleAnimationCallback equals to window.requestAnimationFrame, scheduleDeferredCallback equals to window.requestIdleCallback.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
module.exports = function<T, P, I, C>(config : HostConfig<T, P, I, C>) : Reconciler<C> {

  var { scheduleWork, performWithPriority } = ReactFiberScheduler(config);

  return {

    mountContainer(element : ReactElement<any>, containerInfo : C) : OpaqueNode {
      const root = createFiberRoot(containerInfo);
      const container = root.current;
      // TODO: Use pending work/state instead of props.
      // TODO: This should not override the pendingWorkPriority if there is
      // higher priority work in the subtree.
      container.pendingProps = element;

      scheduleWork(root);

      // It may seem strange that we don't return the root here, but that will
      // allow us to have containers that are in the middle of the tree instead
      // of being roots.
      return container;
    },

    updateContainer(element : ReactElement<any>, container : OpaqueNode) : void {
      // TODO: If this is a nested container, this won't be the root.
      const root : FiberRoot = (container.stateNode : any);
      // TODO: Use pending work/state instead of props.
      root.current.pendingProps = element;

      scheduleWork(root);
    },

    unmountContainer(container : OpaqueNode) : void {
      // TODO: If this is a nested container, this won't be the root.
      const root : FiberRoot = (container.stateNode : any);
      // TODO: Use pending work/state instead of props.
      root.current.pendingProps = [];

      scheduleWork(root);
    },

    performWithPriority,

    getPublicRootInstance(container : OpaqueNode) : (C | null) {
      return null;
    },

  };

};

ReactFiberReconciler returns an object, which has mountContainer, updateContainer, unmountContainer, performWithPriority and getPublicRootInstance methods.

ReactDOMFiber calls mountContainer. Let's get into the mountContainer 🚀

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024

mountContainer calls createFiberRoot with containerInfo. In this case, containerInfo is a DOM Element mounting a ReactElement.

exports.createFiberRoot = function(containerInfo : any) : FiberRoot {
  // Cyclic construction. This cheats the type system right now because
  // stateNode is any.
  const uninitializedFiber = createHostContainerFiber();
  const root = {
    current: uninitializedFiber,
    containerInfo: containerInfo,
    isScheduled: false,
    nextScheduledRoot: null,
  };
  uninitializedFiber.stateNode = root;
  return root;
};

createFiberRoot creates FiberRoot with HostContainerFiber.
createHostContainerFiber is

exports.createHostContainerFiber = function() {
  const fiber = createFiber(HostContainer, null);
  return fiber;
};

createHostContainerFiber creates a Fiber for HostContainer.

HostContainer is a Fiber for a root of a host tree.

module.exports = {
  IndeterminateComponent: 0, // Before we know whether it is functional or class
  FunctionalComponent: 1,
  ClassComponent: 2,
  HostContainer: 3, // Root of a host tree. Could be nested inside another node.
  HostComponent: 4,
  CoroutineComponent: 5,
  CoroutineHandlerPhase: 6,
  YieldComponent: 7,
};

createFiber creates a Fiber.

var createFiber = function(tag : TypeOfWork, key : null | string) : Fiber {
  return {

    // Instance

    tag: tag,

    key: key,

    type: null,

    stateNode: null,

    // Fiber

    return: null,

    child: null,
    sibling: null,

    ref: null,

    pendingProps: null,
    memoizedProps: null,
    updateQueue: null,
    memoizedState: null,
    callbackList: null,
    output: null,

    nextEffect: null,
    firstEffect: null,
    lastEffect: null,

    pendingWorkPriority: NoWork,
    progressedPriority: NoWork,
    progressedChild: null,

    alternate: null,

  };
};

As the result, rootFiber is like this

rootFiber = {
  current: hostContainerFiber
  containerInfo: rootOfHostTree,
  isScheduled: false,
  nextScheduledRoot: null,
};
// circular reference (what is this for?)
rootFiber.current.stateNode = rootFiber;

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024

go back mountContainer, now we've got fiberRoot, a magic of ReactFiber seems to be in scheduleWork(root)

      const root = createFiberRoot(containerInfo);
      const container = root.current;
      // TODO: Use pending work/state instead of props.
      // TODO: This should not override the pendingWorkPriority if there is
      // higher priority work in the subtree.
      container.pendingProps = element;

      scheduleWork(root);

      // It may seem strange that we don't return the root here, but that will
      // allow us to have containers that are in the middle of the tree instead
      // of being roots.
      return container;

Before scheduleWork, rootFiber is like this:

// an output from console.log(root)
    Object {
      current:
       Object {
         tag: 3,
         key: null,
         type: null,
         stateNode: [Circular],
         return: null,
         child: null,
         sibling: null,
         ref: null,
         pendingProps:
          Object {
            '$$typeof': Symbol(react.element),
            type: [Function],
            key: null,
            ref: null,
            props: [Object],
            _owner: null,
            _store: Object {} },
         memoizedProps: null,
         updateQueue: null,
         memoizedState: null,
         callbackList: null,
         output: null,
         nextEffect: null,
         firstEffect: null,
         lastEffect: null,
         pendingWorkPriority: 0,
         progressedPriority: 0,
         progressedChild: null,
         alternate: null },
      containerInfo: HTMLDivElement {},
      isScheduled: false,
      nextScheduledRoot: null }

After scheduleWork, rootFiber is like this:

// an output from console.log(root)
    Object {
      current:
       Object {
         tag: 3,
         key: null,
         type: null,
         stateNode: [Circular],
         return: null,
         child:
          Object {
            tag: 1,
            key: null,
            type: [Function],
            stateNode: null,
            return: [Circular],
            child: [Object],
            sibling: null,
            ref: null,
            pendingProps: null,
            memoizedProps: [Object],
            updateQueue: null,
            memoizedState: null,
            callbackList: null,
            output: HTMLDivElement {},
            nextEffect: null,
            firstEffect: null,
            lastEffect: null,
            pendingWorkPriority: 0,
            progressedPriority: 4,
            progressedChild: [Object],
            alternate: null },
         sibling: null,
         ref: null,
         pendingProps: null,
         memoizedProps:
          Object {
            '$$typeof': Symbol(react.element),
            type: [Function],
            key: null,
            ref: null,
            props: [Object],
            _owner: null,
            _store: Object {} },
         updateQueue: null,
         memoizedState: null,
         callbackList: null,
         output: HTMLDivElement {},
         nextEffect: null,
         firstEffect: [Circular],
         lastEffect: [Circular],
         pendingWorkPriority: 0,
         progressedPriority: 4,
         progressedChild:
          Object {
            tag: 1,
            key: null,
            type: [Function],
            stateNode: null,
            return: [Circular],
            child: [Object],
            sibling: null,
            ref: null,
            pendingProps: null,
            memoizedProps: [Object],
            updateQueue: null,
            memoizedState: null,
            callbackList: null,
            output: HTMLDivElement {},
            nextEffect: null,
            firstEffect: null,
            lastEffect: null,
            pendingWorkPriority: 0,
            progressedPriority: 4,
            progressedChild: [Object],
            alternate: null },
         alternate:
          Object {
            tag: 3,
            key: null,
            type: null,
            stateNode: [Circular],
            return: null,
            child: null,
            sibling: null,
            ref: null,
            pendingProps: [Object],
            memoizedProps: null,
            updateQueue: null,
            memoizedState: null,
            callbackList: null,
            output: null,
            nextEffect: null,
            firstEffect: null,
            lastEffect: null,
            pendingWorkPriority: 4,
            progressedPriority: 4,
            progressedChild: [Object],
            alternate: [Circular] } },
      containerInfo: HTMLDivElement {},
      isScheduled: false,
      nextScheduledRoot: null }

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024

scheduleWork is in ReactFiberScheduler.

  function scheduleWork(root : FiberRoot) {
    if (defaultPriority === SynchronousPriority) {
      throw new Error('Not implemented yet');
    }

    if (defaultPriority === NoWork) {
      return;
    }
    if (defaultPriority > AnimationPriority) {
      scheduleDeferredWork(root, defaultPriority);
      return;
    }
    scheduleAnimationWork(root, defaultPriority);
  }

In this case, defaultPriority is LowPriority

What is Priority?

module.exports = {
  NoWork: 0, // No work is pending.
  SynchronousPriority: 1, // For controlled text inputs. Synchronous side-effects.
  AnimationPriority: 2, // Needs to complete before the next frame.
  HighPriority: 3, // Interaction that needs to complete pretty soon to feel responsive.
  LowPriority: 4, // Data fetching, or result from updating stores.
  OffscreenPriority: 5, // Won't be visible but do the work in case it becomes visible.
};

So scheduleWork calls scheduleDeferredWork because LowPriority is greater than AnimationPriority.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024

scheduleDeferredWork is like this

  function scheduleDeferredWork(root : FiberRoot, priority : PriorityLevel) {
    // We must reset the current unit of work pointer so that we restart the
    // search from the root during the next tick, in case there is now higher
    // priority work somewhere earlier than before.
    if (priority <= nextPriorityLevel) {
      nextUnitOfWork = null;
    }

    // Set the priority on the root, without deprioritizing
    if (root.current.pendingWorkPriority === NoWork ||
        priority <= root.current.pendingWorkPriority) {
      root.current.pendingWorkPriority = priority;
    }

    if (root.isScheduled) {
      // If we're already scheduled, we can bail out.
      return;
    }
    root.isScheduled = true;
    if (lastScheduledRoot) {
      // Schedule ourselves to the end.
      lastScheduledRoot.nextScheduledRoot = root;
      lastScheduledRoot = root;
    } else {
      // We're the only work scheduled.
      nextScheduledRoot = root;
      lastScheduledRoot = root;
      scheduleDeferredCallback(performDeferredWork);
    }
  }

priority is LowPriority, nextPriorityLevel is NoWork, root.current.pendingWorkPriority is 0, then root.current.pendingWorkPriority becomes LowPriority.

root.isScheduled becomes true and lastScheduledRoot is false, So nextScheduledRoot and lastScheduledRoot become rootFiber and calls scheduleDeferredCallback with performDeferredWork.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
  function performDeferredWork(deadline) {
    if (!nextUnitOfWork) {
      nextUnitOfWork = findNextUnitOfWork();
    }
    while (nextUnitOfWork) {
      if (deadline.timeRemaining() > timeHeuristicForUnitOfWork) {
        nextUnitOfWork = performUnitOfWork(nextUnitOfWork);
        if (!nextUnitOfWork) {
          // Find more work. We might have time to complete some more.
          nextUnitOfWork = findNextUnitOfWork();
        }
      } else {
        scheduleDeferredCallback(performDeferredWork);
        return;
      }
    }
  }

nextUnitOfWork is null, so findNextUnitOfWork is called to get a nextUnitOfWork.
before while loop, let's get into findNextUnitOfWork.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
  function findNextUnitOfWork() {
    // Clear out roots with no more work on them.
    while (nextScheduledRoot && nextScheduledRoot.current.pendingWorkPriority === NoWork) {
      nextScheduledRoot.isScheduled = false;
      if (nextScheduledRoot === lastScheduledRoot) {
        nextScheduledRoot = null;
        lastScheduledRoot = null;
        nextPriorityLevel = NoWork;
        return null;
      }
      nextScheduledRoot = nextScheduledRoot.nextScheduledRoot;
    }
    // TODO: This is scanning one root at a time. It should be scanning all
    // roots for high priority work before moving on to lower priorities.
    let root = nextScheduledRoot;
    let highestPriorityRoot = null;
    let highestPriorityLevel = NoWork;
    while (root) {
      if (highestPriorityLevel === NoWork ||
          highestPriorityLevel > root.current.pendingWorkPriority) {
        highestPriorityLevel = root.current.pendingWorkPriority;
        highestPriorityRoot = root;
      }
      // We didn't find anything to do in this root, so let's try the next one.
      root = root.nextScheduledRoot;
    }
    if (highestPriorityRoot) {
      nextPriorityLevel = highestPriorityLevel;
      return cloneFiber(
        highestPriorityRoot.current,
        highestPriorityLevel
      );
    }

    nextPriorityLevel = NoWork;
    return null;
  }

findNextUnitOfWork returns nextUnitOfWork, which is a Fiber ReactFiber should work on.
In this case, it returns a cloned Fiber from nextScheduledRoot.current.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024

the returned Fiber is passed to performUnitOfWork, which is to process the Fiber.

  function performUnitOfWork(workInProgress : Fiber) : ?Fiber {
    // The current, flushed, state of this fiber is the alternate.
    // Ideally nothing should rely on this, but relying on it here
    // means that we don't need an additional field on the work in
    // progress.
    const current = workInProgress.alternate;
    const next = beginWork(current, workInProgress, nextPriorityLevel);

    if (next) {
      // If this spawns new work, do that next.
      return next;
    } else {
      // Otherwise, complete the current work.
      return completeUnitOfWork(workInProgress);
    }
  }

performUnitOfWork calls beginWork. If Fiber hasn't a next work, it calls completeUnitOfWork to complete the current work.

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024

beginWork is in ReactFiberBeginWork.js.

  function beginWork(current : ?Fiber, workInProgress : Fiber, priorityLevel : PriorityLevel) : ?Fiber {
    if (workInProgress.pendingWorkPriority === NoWork ||
        workInProgress.pendingWorkPriority > priorityLevel) {
      return bailoutOnLowPriority(current, workInProgress);
    }

    if (workInProgress.progressedPriority === priorityLevel) {
      // If we have progressed work on this priority level already, we can
      // proceed this that as the child.
      workInProgress.child = workInProgress.progressedChild;
    }

    if ((workInProgress.pendingProps === null || (
      workInProgress.memoizedProps !== null &&
      workInProgress.pendingProps === workInProgress.memoizedProps
      )) &&
      workInProgress.updateQueue === null) {
      return bailoutOnAlreadyFinishedWork(current, workInProgress);
    }

    switch (workInProgress.tag) {
      case IndeterminateComponent:
        return mountIndeterminateComponent(current, workInProgress);
      case FunctionalComponent:
        return updateFunctionalComponent(current, workInProgress);
      case ClassComponent:
        return updateClassComponent(current, workInProgress);
      case HostContainer:
        reconcileChildren(current, workInProgress, workInProgress.pendingProps);
        // A yield component is just a placeholder, we can just run through the
        // next one immediately.
        if (workInProgress.child) {
          return beginWork(
            workInProgress.child.alternate,
            workInProgress.child,
            priorityLevel
          );
        }
        return null;
      case HostComponent:
        if (workInProgress.stateNode && config.beginUpdate) {
          config.beginUpdate(workInProgress.stateNode);
        }
        return updateHostComponent(current, workInProgress);
      case CoroutineHandlerPhase:
        // This is a restart. Reset the tag to the initial phase.
        workInProgress.tag = CoroutineComponent;
        // Intentionally fall through since this is now the same.
      case CoroutineComponent:
        updateCoroutineComponent(current, workInProgress);
        // This doesn't take arbitrary time so we could synchronously just begin
        // eagerly do the work of workInProgress.child as an optimization.
        if (workInProgress.child) {
          return beginWork(
            workInProgress.child.alternate,
            workInProgress.child,
            priorityLevel
          );
        }
        return workInProgress.child;
      case YieldComponent:
        // A yield component is just a placeholder, we can just run through the
        // next one immediately.
        if (workInProgress.sibling) {
          return beginWork(
            workInProgress.sibling.alternate,
            workInProgress.sibling,
            priorityLevel
          );
        }
        return null;
      default:
        throw new Error('Unknown unit of work tag');
    }
  }

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
  function completeUnitOfWork(workInProgress : Fiber) : ?Fiber {
    while (true) {
      // The current, flushed, state of this fiber is the alternate.
      // Ideally nothing should rely on this, but relying on it here
      // means that we don't need an additional field on the work in
      // progress.
      const current = workInProgress.alternate;
      const next = completeWork(current, workInProgress);

      resetWorkPriority(workInProgress);

      // The work is now done. We don't need this anymore. This flags
      // to the system not to redo any work here.
      workInProgress.pendingProps = null;
      workInProgress.updateQueue = null;

      const returnFiber = workInProgress.return;

      if (returnFiber) {
        // Ensure that the first and last effect of the parent corresponds
        // to the children's first and last effect. This probably relies on
        // children completing in order.
        if (!returnFiber.firstEffect) {
          returnFiber.firstEffect = workInProgress.firstEffect;
        }
        if (workInProgress.lastEffect) {
          if (returnFiber.lastEffect) {
            returnFiber.lastEffect.nextEffect = workInProgress.firstEffect;
          }
          returnFiber.lastEffect = workInProgress.lastEffect;
        }
      }

      if (next) {
        // If completing this work spawned new work, do that next.
        return next;
      } else if (workInProgress.sibling) {
        // If there is more work to do in this returnFiber, do that next.
        return workInProgress.sibling;
      } else if (returnFiber) {
        // If there's no more work in this returnFiber. Complete the returnFiber.
        workInProgress = returnFiber;
        continue;
      } else {
        // If we're at the root, there's no more work to do. We can flush it.
        const root : FiberRoot = (workInProgress.stateNode : any);
        if (root.current === workInProgress) {
          throw new Error(
            'Cannot commit the same tree as before. This is probably a bug ' +
            'related to the return field.'
          );
        }
        root.current = workInProgress;
        // TODO: We can be smarter here and only look for more work in the
        // "next" scheduled work since we've already scanned passed. That
        // also ensures that work scheduled during reconciliation gets deferred.
        // const hasMoreWork = workInProgress.pendingWorkPriority !== NoWork;
        commitAllWork(workInProgress);
        const nextWork = findNextUnitOfWork();
        // if (!nextWork && hasMoreWork) {
          // TODO: This can happen when some deep work completes and we don't
          // know if this was the last one. We should be able to keep track of
          // the highest priority still in the tree for one pass. But if we
          // terminate an update we don't know.
          // throw new Error('FiberRoots should not have flagged more work if there is none.');
        // }
        return nextWork;
      }
    }
  }

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
  function commitWork(current : ?Fiber, finishedWork : Fiber) : void {
    switch (finishedWork.tag) {
      case ClassComponent: {
        // Clear updates from current fiber. This must go before the callbacks
        // are reset, in case an update is triggered from inside a callback. Is
        // this safe? Relies on the assumption that work is only committed if
        // the update queue is empty.
        if (finishedWork.alternate) {
          finishedWork.alternate.updateQueue = null;
        }
        if (finishedWork.callbackList) {
          const { callbackList } = finishedWork;
          finishedWork.callbackList = null;
          callCallbacks(callbackList, finishedWork.stateNode);
        }
        // TODO: Fire componentDidMount/componentDidUpdate, update refs
        return;
      }
      case HostContainer: {
        // TODO: Attach children to root container.
        const children = finishedWork.output;
        const root : FiberRoot = finishedWork.stateNode;
        const containerInfo : C = root.containerInfo;
        updateContainer(containerInfo, children);
        return;
      }
      case HostComponent: {
        if (finishedWork.stateNode == null || !current) {
          throw new Error('This should only be done during updates.');
        }
        // Commit the work prepared earlier.
        const child = finishedWork.child;
        const children = (child && !child.sibling) ? (child.output : ?Fiber | I) : child;
        const newProps = finishedWork.memoizedProps;
        const oldProps = current.memoizedProps;
        const instance : I = finishedWork.stateNode;
        commitUpdate(instance, oldProps, newProps, children);
        return;
      }
      default:
        throw new Error('This unit of work tag should not have side-effects.');
    }
  }

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
  function commitAllWork(finishedWork : Fiber) {
    // Commit all the side-effects within a tree.
    // TODO: Error handling.
    let effectfulFiber = finishedWork.firstEffect;
    while (effectfulFiber) {
      const current = effectfulFiber.alternate;
      commitWork(current, effectfulFiber);
      const next = effectfulFiber.nextEffect;
      // Ensure that we clean these up so that we don't accidentally keep them.
      // I'm not actually sure this matters because we can't reset firstEffect
      // and lastEffect since they're on every node, not just the effectful
      // ones. So we have to clean everything as we reuse nodes anyway.
      effectfulFiber.nextEffect = null;
      effectfulFiber = next;
    }
  }

from react-fiber-resources.

koba04 avatar koba04 commented on August 19, 2024
  function commitWork(current : ?Fiber, finishedWork : Fiber) : void {
    switch (finishedWork.tag) {
      case ClassComponent: {
        // Clear updates from current fiber. This must go before the callbacks
        // are reset, in case an update is triggered from inside a callback. Is
        // this safe? Relies on the assumption that work is only committed if
        // the update queue is empty.
        if (finishedWork.alternate) {
          finishedWork.alternate.updateQueue = null;
        }
        if (finishedWork.callbackList) {
          const { callbackList } = finishedWork;
          finishedWork.callbackList = null;
          callCallbacks(callbackList, finishedWork.stateNode);
        }
        // TODO: Fire componentDidMount/componentDidUpdate, update refs
        return;
      }
      case HostContainer: {
        // TODO: Attach children to root container.
        const children = finishedWork.output;
        const root : FiberRoot = finishedWork.stateNode;
        const containerInfo : C = root.containerInfo;
        updateContainer(containerInfo, children);
        return;
      }
      case HostComponent: {
        if (finishedWork.stateNode == null || !current) {
          throw new Error('This should only be done during updates.');
        }
        // Commit the work prepared earlier.
        const child = finishedWork.child;
        const children = (child && !child.sibling) ? (child.output : ?Fiber | I) : child;
        const newProps = finishedWork.memoizedProps;
        const oldProps = current.memoizedProps;
        const instance : I = finishedWork.stateNode;
        commitUpdate(instance, oldProps, newProps, children);
        return;
      }
      default:
        throw new Error('This unit of work tag should not have side-effects.');
    }
  }

from react-fiber-resources.

Related Issues (7)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.