Ausnahme gefangen: SSL certificate problem: certificate is not yet valid 📌 Adding keys to our DOM diffing algorithm

🏠 Team IT Security News

TSecurity.de ist eine Online-Plattform, die sich auf die Bereitstellung von Informationen,alle 15 Minuten neuste Nachrichten, Bildungsressourcen und Dienstleistungen rund um das Thema IT-Sicherheit spezialisiert hat.
Ob es sich um aktuelle Nachrichten, Fachartikel, Blogbeiträge, Webinare, Tutorials, oder Tipps & Tricks handelt, TSecurity.de bietet seinen Nutzern einen umfassenden Überblick über die wichtigsten Aspekte der IT-Sicherheit in einer sich ständig verändernden digitalen Welt.

16.12.2023 - TIP: Wer den Cookie Consent Banner akzeptiert, kann z.B. von Englisch nach Deutsch übersetzen, erst Englisch auswählen dann wieder Deutsch!

Google Android Playstore Download Button für Team IT Security



📚 Adding keys to our DOM diffing algorithm


💡 Newskategorie: Programmierung
🔗 Quelle: dev.to

In my previous post about DOM diffing algorithm we learned to create our own virtual DOM and got to know how DOM diffing actually works. In this post we will learn about how keys works and how we can add this feature to our virtual DOM . before we start the actual coding we must know why keys are necessary and whats the concept behind it.

Importance of using keys

Keys tell our diffing algorithm to identify which items needs to be changed, or add, or remove.
Without keys our algorithm will push update to a node even if we could achieve the same by simple moving the node. Let me explain this with an example

|-------DOM-------------|---------VDOM--------|
|-----------------------|---------------------|
| <Li val="A">          | <Li val="A">        | 
| <Li val="B">          | <Li val="B">        | 
|                       | <Li val="C">        | 
|-----------------------|---------------------|

When we compare this DOM with the VDOM our algorithm just append the last child to our DOM. That's not a problem at all . The problems occurs when we face situation like this.

|-------DOM-------------|---------VDOM--------|
|-----------------------|---------------------|
| <Li val="A">          | <Li val="c">        | 
| <Li val="B">          | <Li val="A">        | 
|                       | <Li val="B">        | 
|-----------------------|---------------------|

In this case our algorithm will append the last node to our DOM and update the first node. But we could have just simply avoided this by prepending the last node to the DOM , and this would make the update much faster. That's where the keys come in.

|---------DOM-----------|-------VDOM----------|--------------------------|
| <Li key=1 val="A">    | <Li key=3 val="C">  | Moved from bottom to top |
| <Li key=2 val="B">    | <Li key=2 val="A">  | None                     |
|                       | <Li key=1 val="B">  | None                     |
|-----------------------|---------------------|--------------------------|

With the help of keys now we can tell our algorithm that no need to change everything just add the new node to the top.

Implementation

The implementation starts by simply adding the key attributes to our nodes, however the key attributes never get passed to DOM, but stays as a property of the node object.
Let's modify our previous codes to add key props. starting with clean function.

function clean(node) {
    for (let n = 0; n < node.childNodes.length; n++) {
        let child = node.childNodes[n];
        if (child.nodeType === 8 ||(child.nodeType === 3 && !/\S/.test(child.nodeValue) && child.nodeValue.includes('\n'))) 
        {
            node.removeChild(child);
            n--;
        } else if (child.nodeType === 1) {
            if(child.hasAttribute('key')){
                let key=child.getAttribute('key');
                //adding the key property to the node object
                child.key=key;
                //removing the keys
                child.removeAttribute('key');
            }
            clean(child);
        }
    }
}

As our clean function iterates through all children we check if the node has the key attribute , if the case is true then we get the attribute value and set a key property with the value, then we remove the key attribute.

Now All of our nodes has the key property. Lets create our patchKeys function

function patchKeys(vdom,dom){
        //remove unmatched keys from dom
        for(let i=0;i<dom.children.length;i++){
            let dnode=dom.children[i];
            let key=dnode.key;
            if(key){
                if(!hasTheKey(vdom,key)){
                    dnode.remove();
                }
            }
        }
        //adding keys to dom
        for(let i=0;i<vdom.children.length;i++){
            let  vnode=vdom.children[i];
            let key=vnode.key;
            if(key){
                if(!hasTheKey(dom,key)){
                    //if key is not present in dom then add it
                    //get the index of current node
                    let nthIndex=[].indexOf.call(vnode.parentNode.children, vnode);
                    if(dom.children[nthIndex]){
                        //adding before the same indexed node of dom
                        dom.children[nthIndex].before(vnode.cloneNode(true))
                    }else{
                        dom.append(vnode.cloneNode(true))
                    }
                }
            }
        }
    }

In the patchKey function we iterate through the DOM and VDOM children. For DOM children if the key is not present in VDOM we remove the node from DOM and for VDOM children if the key is not present the DOM then we add it to the DOM, While adding a node to The DOM we need to maintain the ordering, for this we get the index of the VNODE and add it before the same indexed child of DOM, if the child is not present in DOM we just append the VNODE.

The hasKey function helps us to check if the key is present in the respective DOM.

function hasTheKey(dom,key){
    let keymatched=false;
    for(let i=0;i<dom.children.length;i++){
        //if the key is present the break theloop
        if(key==dom.children[i].key) {
        //update the keymacthed status
            keymatched=true;
            break};
    }
    return keymatched;
}

In the hasKey function we iterate thought a Parent Nodes children to check if the desired key is present, the function returns true/false accordingly.

Now all we need is to add this to our diff function

function diff(vdom, dom) {
    //if dom has no childs then append the childs from vdom
    if (dom.hasChildNodes() == false && vdom.hasChildNodes() == true) {
        //codes
    } else {
        patchKeys(vdom,dom);
        //codes
    }
}

Now this is our Whole code after adding the key feature

function getnodeType(node) {
        if(node.nodeType==1) return node.tagName.toLowerCase();
        else return node.nodeType;
    };
function clean(node) {
    for (let n = 0; n < node.childNodes.length; n++) {
        let child = node.childNodes[n];
        if (child.nodeType === 8 ||(child.nodeType === 3 && !/\S/.test(child.nodeValue) && child.nodeValue.includes('\n'))) 
        {
            node.removeChild(child);
            n--;
        } else if (child.nodeType === 1) {
            if(child.hasAttribute('key')){
                let key=child.getAttribute('key');
                child.key=key;
                child.removeAttribute('key');
            }
            clean(child);
        }
    }
}
function parseHTML(str) {
    let parser = new DOMParser();
    let doc = parser.parseFromString(str, 'text/html');
    clean(doc.body);
    return doc.body;
}

function attrbutesIndex(el) {
    var attributes = {};
    if (el.attributes == undefined) return attributes;
    for (var i = 0, atts = el.attributes, n = atts.length; i < n; i++) {
        attributes[atts[i].name] = atts[i].value;
    }
    return attributes;
}
function patchAttributes(vdom, dom) {
    let vdomAttributes = attrbutesIndex(vdom);
    let domAttributes = attrbutesIndex(dom);
    if (vdomAttributes == domAttributes) return;
    Object.keys(vdomAttributes).forEach((key, i) => {
        //if the attribute is not present in dom then add it
        if (!dom.getAttribute(key)) {
            dom.setAttribute(key, vdomAttributes[key]);
        } //if the atrtribute is present than compare it
        else if (dom.getAttribute(key)) {
            if (vdomAttributes[key] != domAttributes[key]) {
                dom.setAttribute(key, vdomAttributes[key]);
            }
        }
    });
    Object.keys(domAttributes).forEach((key, i) => {
        //if the attribute is not present in vdom than remove it
        if (!vdom.getAttribute(key)) {
            dom.removeAttribute(key);
        }
    });
}
function hasTheKey(dom,key){
    let keymatched=false;
    for(let i=0;i<dom.children.length;i++){
        if(key==dom.children[i].key) {
            keymatched=true;
            break};
    }
    return keymatched;
}
function patchKeys(vdom,dom){
        //remove unmatched keys from dom
        for(let i=0;i<dom.children.length;i++){
            let dnode=dom.children[i];
            let key=dnode.key;
            if(key){
                if(!hasTheKey(vdom,key)){
                    dnode.remove();
                }
            }
        }
        //adding keys to dom
        for(let i=0;i<vdom.children.length;i++){
            let  vnode=vdom.children[i];
            let key=vnode.key;
            if(key){
                if(!hasTheKey(dom,key)){
                    //if key is not present in dom then add it
                    let nthIndex=[].indexOf.call(vnode.parentNode.children, vnode);
                    if(dom.children[nthIndex]){
                        dom.children[nthIndex].before(vnode.cloneNode(true))
                    }else{
                        dom.append(vnode.cloneNode(true))
                    }
                }
            }
        }
    }
function diff(vdom, dom) {
    //if dom has no childs then append the childs from vdom
    if (dom.hasChildNodes() == false && vdom.hasChildNodes() == true) {
        for (var i = 0; i < vdom.childNodes.length; i++) {
            //appending
            dom.append(vdom.childNodes[i].cloneNode(true));
        }
    } else {
        patchKeys(vdom,dom);
        //if dom has extra child
        if (dom.childNodes.length > vdom.childNodes.length) {
            let count = dom.childNodes.length - vdom.childNodes.length;
            if (count > 0) {
                for (; count > 0; count--) {
                    dom.childNodes[dom.childNodes.length - count].remove();
                }
            }
        }
        //now comparing all childs
        for (var i = 0; i < vdom.childNodes.length; i++) {
            //if the node is not present in dom append it
            if (dom.childNodes[i] == undefined) {
                dom.append(vdom.childNodes[i].cloneNode(true));
                // console.log("appenidng",vdom.childNodes[i])
            } else if (getnodeType(vdom.childNodes[i]) == getnodeType(dom.childNodes[i])) {
                //if same node type
                //if the nodeType is text
                if (vdom.childNodes[i].nodeType == 3) {
                    //we check if the text content is not same
                    if (vdom.childNodes[i].textContent != dom.childNodes[i].textContent) {
                        //replace the text content
                        dom.childNodes[i].textContent = vdom.childNodes[i].textContent;
                    } 
                }else {
                        patchAttributes(vdom.childNodes[i], dom.childNodes[i])
                    }
            } else {
                //replace
                dom.childNodes[i].replaceWith(vdom.childNodes[i].cloneNode(true));
            }
            if(vdom.childNodes[i].nodeType != 3){
                diff(vdom.childNodes[i], dom.childNodes[i])
            }
        }
    }
}

Lets see if it works.

|-------DOM-------------|--------VDOM---------|--------action------------|
| <Li key=1 val="1">    | <Li key=1 val="1">  | Node                     |
| <Li key=2 val="2">    | <Li key=3 val="3">  | Add this before key 2    |
|                       | <Li key=2 val="2">  | Node                     |
|-----------------------|---------------------|--------------------------|
<div id="node">
    <ul>
        <li key="1">1</li>
        <li key="2">2</li>
    </ul>
</div>
<button>Diff</button>
<script>
 let vdom = parseHTML(`
<ul>
<li key="1">1</li>
<li key="3">3</li>
<li key="2">2</li>
</ul>`);
let dom = document.getElementById('node');
clean(dom);
document.querySelector('button').addEventListener('click',function(){
    diff(vdom,dom);
})
</script>

The result

Image description

IF you are interested in this type of posts please check out my
blog

...



📌 Adding keys to our DOM diffing algorithm


📈 85.22 Punkte

📌 HTML Streaming and DOM Diffing Algorithm


📈 54.45 Punkte

📌 Binary diffing for beginners - Finding vulnerabilities by patch diffing ...


📈 54.09 Punkte

📌 Mozilla Firefox bis 46 DOM Element Handler mozilla::dom::Element Pufferüberlauf


📈 28.8 Punkte

📌 Mozilla Firefox bis 46 DOM Element Handler mozilla::dom::Element Pufferüberlauf


📈 28.8 Punkte

📌 Difference Between DOM and Virtual DOM


📈 28.8 Punkte

📌 Difference between a virtual DOM and a real DOM


📈 28.8 Punkte

📌 [PDF] fn_fuzzy - Fast Multiple Binary Diffing Triage - Takahiro Haruyama - HITB2019AMS


📈 27.04 Punkte

📌 DEEPBINDIFF: Learning Program-Wide Code Representations for Binary Diffing


📈 27.04 Punkte

📌 Patch Diffing a Cisco RV110W Firmware


📈 27.04 Punkte

📌 Introduction to Patch Diffing for CTFs with Ghidra


📈 27.04 Punkte

📌 [Stream:October 21 at 9:30 PM] Modern Binary/Patch Diffing!


📈 27.04 Punkte

📌 Diaphora - The Most Advanced Free And Open Source Program Diffing Tool


📈 27.04 Punkte

📌 Diffing PostgreSQL Schema Changes


📈 27.04 Punkte

📌 Tackling React's Most Loathed Interview Question - Diffing and Reconciliation Unveiled


📈 27.04 Punkte

📌 Iran is doing to our networks what it did to our spy drone, claims Uncle Sam: Now they're bombing our hard drives


📈 26.84 Punkte

📌 What is an Algorithm? Algorithm Definition for Computer Science Beginners


📈 26.01 Punkte

📌 Google blames algorithm for adding porn titles to train station search results


📈 25.06 Punkte

📌 Why do websites use their own RSA keys, but at the same time using the same SHAxxx algorithm to hash passwords?


📈 22.77 Punkte

📌 Facebook’s Algorithm Shapes Our Lives. This Hacker Wants to Find Out How.


📈 21.95 Punkte

📌 An Algorithm That Learns Through Rewards May Show How Our Brain Does Too


📈 21.95 Punkte

📌 Recon-ng - Adding API Keys, Database Commands and Advanced Scanning


📈 21.82 Punkte

📌 Recon-ng V5 - Adding API Keys (Shodan & BuiltWith)


📈 21.82 Punkte

📌 Adding a little more linux to our mostly Windows only environment


📈 21 Punkte

📌 Adding Cognito Authentication to our Serverless Dash App


📈 21 Punkte

📌 Device Can Generate Master Keys From Valid or Expired Hotel Keys


📈 19.53 Punkte

📌 Why vim uses hjkl keys as arrow keys


📈 19.53 Punkte

📌 Why vim uses hjkl keys as arrow keys


📈 19.53 Punkte

📌 Titan Security Keys – Google launches its own USB-based FIDO U2F Keys


📈 19.53 Punkte

📌 Titan Security Keys- Google announced USB-based FIDO U2F Keys


📈 19.53 Punkte

📌 Modifing XKB to disable function keys, Have yet to be successful in disabling any of the function keys at all.


📈 19.53 Punkte

📌 Some YubiKey FIPS Keys Allow Attackers to Reconstruct Private Keys


📈 19.53 Punkte

📌 keys kaspersky total security 2020 keys 360 days


📈 19.53 Punkte











matomo