<commit_before>import Cascade from './Cascade';
import Computed from '../graph/Computed';
import VirtualNode from './VirtualNode';
import {IVirtualNode, IVirtualNodeProperties} from './IVirtualNode';

var componentContexts: Component<any>[][] = [];
var context: Component<any>[] = undefined;

export default class Component<T extends IVirtualNodeProperties> implements IVirtualNode<T> {
    uniqueId: number;
    properties: T;
    children: Array<IVirtualNode<any> | string | number>;
    root: IVirtualNode<any> | string | number;
    element: Node;
    context: Component<any>[];

    constructor(properties?: T, ...children: Array<IVirtualNode<any> | string | number>) {
        this.uniqueId = Math.floor(Math.random() * 1000000);
        this.properties = properties || ({} as any);
        this.children = children || [];
        // This should subscribe to all observables used by render.
        Cascade.createComputed(this, 'root', () => {
            // Dispose of old context
            if (this.context) {
                for (var index = 0, length = this.context.length; index < length; index++) {
                    var computed = Cascade.getObservable(this.context[index], 'root') as Computed<any>;
                    computed.dispose();
                }
            }

            // Push this to the current context
            if (context) {
                context.push(this);
            }

            // Create a new context
            Component.pushContext();

            // Render
            var root = this.render();

            // Store the new context
            this.context = Component.popContext();
            return root;
        });
        Cascade.createComputed(this, 'element', (oldElement: Node) => {
            // Subscribe to root
            var root = this.root;
            var element: Node;
            if (typeof root === 'string') {
                element = document.createTextNode(root);
            } else if (typeof root === 'number') {
                element = document.createTextNode(root.toString());
            } else {
                if (root instanceof Component) {
                    // Do not subscribe to root element
                    element = Cascade.peek(root, 'element');
                } else {
                    element = root.toNode(oldElement);
                }
            }
            if (this.properties && this.properties.ref) {
                this.properties.ref(element);
            }
            return element;
        });
        // Only update parent node if the element has changed
        Cascade.subscribe(this, 'element', (element: Node, oldElement: Node) => {
            if (oldElement) {
                var parentNode = oldElement.parentNode;
                if (parentNode) {
                    if (element) {
                        parentNode.replaceChild(element, oldElement);
                    } else {
                        parentNode.removeChild(element);
                    }
                }
            }
        });
    }

    render(): IVirtualNode<any> | string | number {
        return this;
    }

    toNode() {
        var root = this.root;
        var element: Node;
        if (typeof root === 'string') {
            element = document.createTextNode(root);
        } else if (typeof root === 'number') {
            element = document.createTextNode(root.toString());
        } else {
            if (root instanceof Component) {
                element = Cascade.peek(root, 'element');
            } else {
                element = root.toNode();
            }
        }
        if (this.properties && this.properties.ref) {
            this.properties.ref(element);
        }
        return element;
    }

    static getContext() {
        return context;
    }

    static pushContext() {
        context = [];
        componentContexts.unshift(context);
        return context;
    }

    static popContext() {
        var oldContext = componentContexts.shift();
        context = componentContexts[0];
        return oldContext;
    }
}<commit_msg>Updated Component rendering to support Diff logicl<commit_after>import Cascade from './Cascade';
import Computed from '../graph/Computed';
import VirtualNode from './VirtualNode';
import {IVirtualNode, IVirtualNodeProperties} from './IVirtualNode';

var componentContexts: Component<any>[][] = [];
var context: Component<any>[] = undefined;

export default class Component<T extends IVirtualNodeProperties> implements IVirtualNode<T> {
    uniqueId: number;
    properties: T;
    children: Array<IVirtualNode<any> | string | number>;
    root: IVirtualNode<any> | string | number;
    element: Node;
    context: Component<any>[];

    constructor(properties?: T, ...children: Array<IVirtualNode<any> | string | number>) {
        this.uniqueId = Math.floor(Math.random() * 1000000);
        this.properties = properties || ({} as any);
        this.children = children || [];
        // This should subscribe to all observables used by render.
        Cascade.createComputed(this, 'root', () => {
            // Dispose of old context
            if (this.context) {
                for (var index = 0, length = this.context.length; index < length; index++) {
                    var computed = Cascade.getObservable(this.context[index], 'root') as Computed<any>;
                    computed.dispose();
                }
            }

            // Push this to the current context
            if (context) {
                context.push(this);
            }

            // Create a new context
            Component.pushContext();

            // Render
            var root = this.render();

            // Store the new context
            this.context = Component.popContext();
            return root;
        });
        var oldRoot = undefined;
        Cascade.createComputed(this, 'element', (oldElement: Node) => {
            // Subscribe to root
            var root = this.root;
            var element: Node;
            if (typeof root === 'string') {
                element = document.createTextNode(root);
            } else if (typeof root === 'number') {
                element = document.createTextNode(root.toString());
            } else {
                if (root instanceof Component) {
                    // Do not subscribe to root element
                    element = Cascade.peek(root, 'element');
                } else {
                    if (!oldElement) {
                        element = root.toNode();
                    } else {
                        // Diff this case
                        element = this.diff(root, oldRoot, oldElement);
                    }
                }
            }
            if (element !== oldElement) {
                if (this.properties && this.properties.ref) {
                    this.properties.ref(element);
                }
            }
            oldRoot = root;
            return element;
        });
        // Only update parent node if the element has changed
        Cascade.subscribe(this, 'element', (element: Node, oldElement: Node) => {
            if (oldElement) {
                var parentNode = oldElement.parentNode;
                if (parentNode) {
                    if (element) {
                        parentNode.replaceChild(element, oldElement);
                    } else {
                        parentNode.removeChild(element);
                    }
                }
            }
        });
    }

    render(): IVirtualNode<any> | string | number {
        return this;
    }

    toNode() {
        var root = this.root;
        var element: Node;
        if (typeof root === 'string') {
            element = document.createTextNode(root);
        } else if (typeof root === 'number') {
            element = document.createTextNode(root.toString());
        } else {
            if (root instanceof Component) {
                element = Cascade.peek(root, 'element');
            } else {
                element = root.toNode();
            }
        }
        if (this.properties && this.properties.ref) {
            this.properties.ref(element);
        }
        return element;
    }

    diff(newRoot: IVirtualNode<any>, oldRoot: IVirtualNode<any>, oldElement: Node) {
        return newRoot.toNode(oldElement);
    }

    static getContext() {
        return context;
    }

    static pushContext() {
        context = [];
        componentContexts.unshift(context);
        return context;
    }

    static popContext() {
        var oldContext = componentContexts.shift();
        context = componentContexts[0];
        return oldContext;
    }
}
{'fraction_non_alphanumeric': 0.11143087371935076, 'fraction_numerical': 0.002072061701392886, 'mean_word_length': 1.578806767586821, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 35, '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': '3082222', 'n_tokens_mistral': 2192, 'n_tokens_neox': 2098, 'n_words': 554}