Skip to content

Instantly share code, notes, and snippets.

@Swatinem
Last active August 29, 2015 14:23
Show Gist options
  • Save Swatinem/5f868e4e152092b43dab to your computer and use it in GitHub Desktop.
Save Swatinem/5f868e4e152092b43dab to your computer and use it in GitHub Desktop.
yavd ideas

The DOM is stupid. It has appendChild and insertBefore, but no prependChild and insertAfter.

So we should just walk the DOM back to front.

We will deal with fragments. A Fragment can contain a variable number of nodes, 0 or more.

  • seq() creates a fragment with 0 or more nodes
  • match() creates a fragment with 0 or 1 node
  • children creates a fragment with 0 or more nodes

On create or update, a fragment will take a location, that is basically a (parent, nextSibling?) pair. The fragment will then just parent.insertBefore(…, nextSibling) its content. if nextSibling is null, it is the same as appendChild, just the thing we want in that case. It will then return its own first child in case it did create some nodes, or just return the previous nextSibling in case it didn’t.

We then go on and iterate all the fragments back to front.

For easy cases, we could generate code like this:

All I need to figure out is how to reference the passed in props functions properly

let jsx = (<div className={state(s => s.foo)}>{props(p => p.bar)}{props(p.foobar)}</div>)

// automatically generated:
function generated(elem, component) {
  var e0 = elem, e1
  e0.className = propsfn(component) // call `s => s.foo`
  e1 = e0.firstChild // go into hierarchy
  e1.data = propsfn(component) // call `p => p.bar`
  e1 = elem1.nextSibling // navigate from first to last
  e1.data = propsfn(component) // call `p => p.foobar`
}
  • jsx with precial props and sequences and matches
  • they get compiled into a cloneable fragment, plus a specialized function that populates that fragment.
<Component className={props(p => p.bar)}>
  {props(p => p.foo)} // props
  {props((_, s) => s.foo)} // state
  {props((_, _, c) => c)} // children (or maybe not?)
  
  // OR (even both!)
  // `props` has 2(/3) arguments, taking props, state (and children)
  // `state` takes just state as arg
  // `children` is just a special reference
  
  {props(p => p.foo || 'foo')}
  {state(s => s.bar || 'bar')}
  {children}
</Component>

sequences / each / repeat:

<Component>
  {seq(p => p.foo.map(c => <Child />))} // props
  {seq((_, s) => s.bar.map())} // state
</Component>
<Component>
  {match( // or maybe `switch`, but `if` is a reserved word :-(
    (_, s) => s.test, // if
    p => p.bar, // then
    p => b.foo, // else, defaults to null
  )}
  {switch(
    (_, s) => s.bar, // if
    p => p.bar, // then
    (_, s) => s.foo, // else if
    p => p.foo, // then
    // else defaults to null
  )}
</Component>

far future: maybe transpiler plugin to just leave away the closure, but hardcode the identifiers props, state, children ?

<Component>
  {seq(props.foo.map(c => <Child />))} // i think we still need `seq` though
  {props.bar}
  {children}
  {state.foo}
</Component>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment