IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

[Projet "domulo"] Réaliser une lib VDOM


Sujet :

JavaScript

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2018
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2018
    Messages : 41
    Points : 33
    Points
    33
    Par défaut [Projet "domulo"] Réaliser une lib VDOM
    [EDIT: question subtilement retocquée pour plus de lisibilité...]

    Bonjour,

    je travaille sur la réalisation d'une lib JS qui stocke des graphes (arbres VDOM et automates par exemple) de façon linéaire (tableaux + hash index) pour facilter leur sérialisation, transfert filtrage et requête.

    J'ai abordé le sujet dans plusieurs posts sur développez.com et ailleurs en anglais.. Les lien développez sont présents en bas de ce post.

    La question du jour porte sur l'organisation optimale des fichiers de l'application utilisant la lib.

    Les données sont organisées dans un Block Memory Pool, qui peut être initialisé au moins une fois par l'utilisateur AVANT toute utilisation, avec u,e clé alphanumérique (graine pour le générateur de nombres pseudo aléatoires sous jacent)

    Dans le cas d'un virtual DOM avec une fonction "h" de création d'éléments:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
        import { createBlocksMemoryPool} from '@src/core/blocks-memory/pool'
     
        const bmp = createBlocksMemoryPool({ seed: '8_DiG1t$' })
     
        // ATTENTION closure javascript:
        //  bmp ne doit surtout pas etre visible à l'exterier
        export const h = (name, attrsd, ...children) => {
          return createElement(bmp, name, attrs, children)
        }
    Les appels successifs à "h" vont toujours écrire sur la même structure de données (blocks-memory-pool), les opérations de diff/patch l'utiliseront également (on appelle cela virtuial DOM "in-place")

    On peut envisager d'utiliser du JSX.

    La question porte sur l'application qui va utiliser la lib, supposons une structure de projet basique:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
     
       + root-folder/
         + dist/
           + app.bundle.js
           + test.bundle.js
         + node_modules/     
         + src/
           + index.js
           + seed.js
           + todo.item.js
           + todo.list.js
         + index.html
         + package.json
         + rollup.config.js
    Un exemple de ficiher index.js avec deux composants serait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
     
        // src/index.js
        import { mount, compo, dom } from 'domulo' // la lib
        import { TodoListCompo } from '@src/todo-list'
        import { TodoItemCompo } from '@src/todo-item'
     
        // amorçage de la lib:
        //
        // idéalement à placer ici :
        //
        // const bmp = createBlocksMemoryPool({ seed: '900dCafe' })
     
        const TodoAppCompo = (props) => compo(
          h('section', 
            { /* attrs  */},
            TodoListCompo,
            TOdoItemCommpo
          )  
        )
     
       mount(ToodCompo, doxument.getElementById('#container')
    La difficulté vient de la mécanique des imports: ceux ci étant executés en premier, avant le fichier appelant (index.js) comment s'assurrer que la lib, donc la fonction "h" a bien été amorcée avant toute utilisation dans les fichiers de components ?

    * soit par l'import, en top position de index.js, du fichier seeds.js

    * soit par l'inclusion en tête de chaque composant, et du index.js, s'il y a un composant dedans également, de seeds.js

    Le hic étant que seeds.js, qui est défini par l'utilisateur, ne doive re-exporter toutes les fonctions de la lib { h, compo, mount, init ...} dans autant d'exports, et que c'est de la responsabilité de l'utilisateur de lib lib, pour que cela fonctionne correectement !!!


    TL;DR {BEGIN}

    Deux très longs posts et échanges sur le sujet...

    La structure de données est développée ici:

    https://www.developpez.net/forums/d1...bjets-memoire/

    La structure de données est prête également : Object Memory Pool recyclables pour eviter les cycles intempestifs du Garbage Collector --> OK

    Les clés nécessaires à la gestion de s blocs sont discutées ici :

    https://www.developpez.net/forums/d1...aleatoire-mwc/

    J'ai arrêteé les choix sur le générateur : clés sur 4 digitis de 64 valeurs pris sur le domaine A-Za-z + "$" + _"" + 0-9 avec générateur MWC --> OK ca marche

    TL;DR {END}

    merci de vos remarquers et suggestions.

    A + F - E

  2. #2
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2018
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2018
    Messages : 41
    Points : 33
    Points
    33
    Par défaut [Projet "domulo"] Réaliser une lib VDOM (2)
    Comment s'appelle le pattern de conception d'imbrication des fonction hyperscript "h" d'une lib de DOM virtuel ? Est-ce une forme de récursion ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
      import { domulo } from 'src/domulo/app/wrap.js'
      import { TodoItem } from 'src/domulo/app/todo-item.js'
     
      const TodoList = (props) => {
        return domulo.h('section', {}, 
          domulo.h('h1', {}, 'Here are some todos:'),
          domulo.h('ul', { className: 'todo-list' }, 
            props.todos.map((todo, idx) => TodoItem(todo, idx))      
          )
        )
      }
    Avez vous examiné l'ordre d'invocation de ces fonctions "h" ? Avez vous remarqué que les fonctions les plus internes sont invoquées en premier ? Peut être cela semble il évident de le dire mais bon, testez quand même ...

    Je souhaite assembler ma propre lib de VDOM. Elle s'appelle "domulo" devrait stocker mles arbres de noeuds VDOM ainsi que leur patches dans une unique structure de données inspirée des jeux vidéo le Blocks Memory Pool : l'idée est d'associer une liste de blocs préamoloués (utilisés ou disponibles) dans un tableau, et de référencer ces neouds via un objet hash (UID => adresse du bloc dans la liste) afin de bénéficier des temps d'accès constant aux blocs.

    Le gain escompté se situe en termes de la préalloccation : peu de cycles ramasse-mettes mémoire (GC) sont nécessaires pendant l'exécution du programme, ce qui devrait limiter les "sauts" et autres ralentissements... De plus il devrait être possible de conserver l'historique des patches pour autoriser le time-travelling, ou alors non, et dans ce cas fonctionner en double buffering (diff puis patch) ce qui devrait être rapide !

    Les blocs sont chaînés via leur UID. Cet UID justement est produit à partir d'un générateur Multiply-Wit-Carry... modulaire de la forme x[n + 1] = (a * x[n] + carry[n]) modulo M. D'où le nom de la bibliothèque "domulo". Avec M = 64, et des clés sur 4 digits (x64) on peut adresser environ 16.7M blocks ce qui me semble suffisant pour ce type d'applicationn !

    Pour l'instant c'estr Work In Progress : juste la structure de données fonctionnerlle, la fonction "h" qui envoie ses résumtats dans le pool et une fonction "render" basique sont implémentées, il manque encore "mount", "diff" et "patch" pour aboutir à un vrai PoC...

    Cependant quelqu'un pourrait il jeter un coup d'oeil au dépot : https://github.com/hefeust/domulo.git et me donner son avis ?

    D'avance, merci, Salut, A + F - E !

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2018
    Messages
    41
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Nord (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2018
    Messages : 41
    Points : 33
    Points
    33
    Par défaut [Projet "domulo"] Réaliser une lib VDOM (3)
    Bonjour,

    je travaille actuellement sur une lib JS de gestion de DOM virtuel. Le code est sotcké sur le dépôt: https://github.com/hefeust/domulo.git

    Le nom "domulo" provient du fait que la lib utilise en interne un générateur pseudo aléatoire modulaire (MWC = Multiply-With-Carry) pour attribuer des clés uniques à des blocs de mémoire et constituer ainsi un Block Memory Pool (BMP) dans lequel les arbres VDOM successifs, ainsi que les patches sont linéarisés.

    Objectifs :

    - requêter et filtrer rapidemùent sur le VDOM (exemple changer style: { color: "blue" } enstyle: { color: "red" } pour tous les noeuds à la volée) ;
    - permettre de streamer des VDOM et des patches envue peut être d'un rendu côté serveur ;
    - éviter lezs cycles intempestifs du rammasse miettes de JS, en ne libérant pas directement la mémoire, mais en marquant les blocs inutilisés comme libres ;
    - permettre l'application/annulation des patches et leur historisation (time travelling possible)
    - et enfin, en utilisant les closures JS, des clés pseudo aléatoires pour identifier et chaîner les blocs mémoire, assurrer une forme d'encapsulation et d'incorruptibilité (sécurité) de la structure de données

    Ce qui est déjà fait :

    - la fonction hyperscript qui projette ses résultats dans le Block Memort Pool
    -le montage et le rendu text/html d'un arbre VDOM stocké dans le BMP
    - le mécanisme basique de diff

    Ce qui reste à terminer:
    - la gestion fine des attributs className et style
    - la gestion des event listeners
    - le gros morceau: le patching
    - le mécanisme de rollback des patches (time travelling)

    Pour ce qui est du diff, chaque delta du patch préparé conserve:

    - le nom de l'opération (exemple: PATCH_INSERT_NODE)
    - un lien vers le bloc dans l'arbre source
    - un lien vers le bloc dans l'arbre destination
    - le chemin de patch source|destination

    Les chemins de patch sont de la forme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        chemin/depuis/racine/source!chemin/vers/destination
     
        0!0/1/2: arbre de départ vide, 0/1/2-ème noeud en destination
        0/1/2!0: arbre de destination vide
     
        # plus compliqué, mais à clarifier sans aucun doute...
        0/1!0/2: couper la deuximème branche de l'arbre source et coller dans le nouvel arbre
    Le diff est OK pour le moment, et produit bien des patches (séquences de deltas) pour le patching c'est une autre histoire...

    - soit j'ai une boucle infinie qui empile le premier noeud ad vitam eternam p/p/p...
    - soit tous les noeuds sont listés et entassés les uns derrières les autre sous la racine sans tenir compte de l'imbrication !

    Le hic vient du fait que patcher un DOM, c'est un peui mùarcher sur des sables mouvants, ou scier la branche sur laquelle on est assis : faut il se repérer par rapport à l'ancien arbre ou par rapport au nouveau qu'on construit ?

    Par exemple si root est le noeud localement visité, root.childNodes listera tous les enfants effectifs, mais comme savoir lequel et où ajouter le nouveau ?

    La seule certitude qu'on ait, c'est que chauqe delta étant une transformation infinitésimale (comme en thermodynamique), est que l'arbre destination réel est PRESQUE LE MEME entre chauqe application de delta !

    Voilà pour le moment, j'espère que vous avez tenu jusque là, et fait bonne lecture. J(aimerai avoir quelques conseils et remarques, surtout ne vous en privez pas.

    Merci d'avance, Salut, A + F - E !
    Images attachées Images attachées  

  4. #4
    Modérateur

    Avatar de NoSmoking
    Homme Profil pro
    Inscrit en
    Janvier 2011
    Messages
    17 048
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Janvier 2011
    Messages : 17 048
    Points : 44 562
    Points
    44 562
    Par défaut
    Bonjour,
    les différentes discussions concernant la réalisation de ta lib, https://github.com/hefeust/domulo.git, ont été regroupées dans une seule et même discussion, celle-ci.

Discussions similaires

  1. Réponses: 0
    Dernier message: 08/09/2018, 20h18
  2. [Eclipse CDT] creer une lib et un executable dans le meme projet ?
    Par mamelouk dans le forum Eclipse C & C++
    Réponses: 4
    Dernier message: 28/11/2006, 15h05

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo