{"action":"created","comment":{"url":"https://api.github.com/repos/hyperapp/hyperapp/pulls/comments/201479314","pull_request_review_id":135991189,"id":201479314,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwMTQ3OTMxNA==","diff_hunk":"@@ -1,390 +1,586 @@\n-export function h(name, attributes) {\n-  var rest = []\n-  var children = []\n-  var length = arguments.length\n+var DEFAULT = 0\n+var RECYCLED_NODE = 1\n+var TEXT_NODE = 2\n \n-  while (length-- > 2) rest.push(arguments[length])\n+var XLINK_NS = \"http://www.w3.org/1999/xlink\"\n+var SVG_NS = \"http://www.w3.org/2000/svg\"\n \n-  while (rest.length) {\n-    var node = rest.pop()\n-    if (node && node.pop) {\n-      for (length = node.length; length--; ) {\n-        rest.push(node[length])\n+var EMPTY_OBJECT = {}\n+var EMPTY_ARRAY = []\n+\n+var map = EMPTY_ARRAY.map\n+var isArray = Array.isArray\n+\n+var merge = function(a, b) {\n+  var target = {}\n+\n+  for (var i in a) target[i] = a[i]\n+  for (var i in b) target[i] = b[i]\n+\n+  return target\n+}\n+\n+var resolved = typeof Promise === \"function\" && Promise.resolve()\n+\n+var defer = !resolved\n+  ? setTimeout\n+  : function(cb) {\n+      return resolved.then(cb)\n+    }\n+\n+var updateProperty = function(\n+  element,\n+  name,\n+  lastValue,\n+  nextValue,\n+  eventProxy,\n+  isSvg\n+) {\n+  if (name === \"key\") {\n+  } else if (name === \"style\") {\n+    for (var i in merge(lastValue, nextValue)) {\n+      var style = nextValue == null || nextValue[i] == null ? \"\" : nextValue[i]\n+      if (i[0] === \"-\") {\n+        element[name].setProperty(i, style)\n+      } else {\n+        element[name][i] = style\n       }\n-    } else if (node != null && node !== true && node !== false) {\n-      children.push(node)\n     }\n-  }\n+  } else {\n+    if (name[0] === \"o\" && name[1] === \"n\") {\n+      name = name.slice(2).toLowerCase()\n \n-  return typeof name === \"function\"\n-    ? name(attributes || {}, children)\n-    : {\n-        nodeName: name,\n-        attributes: attributes || {},\n-        children: children,\n-        key: attributes && attributes.key\n+      if (!element.events) element.events = {}\n+\n+      element.events[name] = nextValue\n+\n+      if (nextValue == null) {\n+        element.removeEventListener(name, eventProxy)\n+      } else if (lastValue == null) {\n+        element.addEventListener(name, eventProxy)\n       }\n-}\n+    } else {\n+      var nullOrFalse = nextValue == null || nextValue === false\n \n-export function app(state, actions, view, container) {\n-  var map = [].map\n-  var rootElement = (container && container.children[0]) || null\n-  var oldNode = rootElement && recycleElement(rootElement)\n-  var lifecycle = []\n-  var skipRender\n-  var isRecycling = true\n-  var globalState = clone(state)\n-  var wiredActions = wireStateToActions([], globalState, clone(actions))\n-\n-  scheduleRender()\n-\n-  return wiredActions\n-\n-  function recycleElement(element) {\n-    return {\n-      nodeName: element.nodeName.toLowerCase(),\n-      attributes: {},\n-      children: map.call(element.childNodes, function(element) {\n-        return element.nodeType === 3 // Node.TEXT_NODE\n-          ? element.nodeValue\n-          : recycleElement(element)\n-      })\n+      if (\n+        name in element &&\n+        name !== \"list\" &&\n+        name !== \"draggable\" &&\n+        name !== \"spellcheck\" &&\n+        name !== \"translate\" &&\n+        !isSvg\n+      ) {\n+        element[name] = nextValue == null ? \"\" : nextValue\n+        if (nullOrFalse) {\n+          element.removeAttribute(name)\n+        }\n+      } else {\n+        var ns = isSvg && name !== (name = name.replace(/^xlink:?/, \"\"))\n+        if (ns) {\n+          if (nullOrFalse) {\n+            element.removeAttributeNS(XLINK_NS, name)\n+          } else {\n+            element.setAttributeNS(XLINK_NS, name, nextValue)\n+          }\n+        } else {\n+          if (nullOrFalse) {\n+            element.removeAttribute(name)\n+          } else {\n+            element.setAttribute(name, nextValue)\n+          }\n+        }\n+      }\n     }\n   }\n+}\n \n-  function resolveNode(node) {\n-    return typeof node === \"function\"\n-      ? resolveNode(node(globalState, wiredActions))\n-      : node != null\n-        ? node\n-        : \"\"\n+var createElement = function(node, lifecycle, eventProxy, isSvg) {\n+  var element =\n+    node.type === TEXT_NODE\n+      ? document.createTextNode(node.name)\n+      : (isSvg = isSvg || node.name === \"svg\")\n+        ? document.createElementNS(SVG_NS, node.name)\n+        : document.createElement(node.name)\n+\n+  var props = node.props\n+  if (props.onCreate) {\n+    lifecycle.push(function() {\n+      props.onCreate(element)\n+    })\n   }\n \n-  function render() {\n-    skipRender = !skipRender\n+  for (var i = 0, length = node.children.length; i < length; i++) {\n+    element.appendChild(\n+      createElement(node.children[i], lifecycle, eventProxy, isSvg)\n+    )\n+  }\n \n-    var node = resolveNode(view)\n+  for (var name in props) {\n+    updateProperty(element, name, null, props[name], eventProxy, isSvg)\n+  }\n+\n+  return (node.element = element)\n+}\n \n-    if (container && !skipRender) {\n-      rootElement = patch(container, rootElement, oldNode, (oldNode = node))\n+var updateElement = function(\n+  element,\n+  lastProps,\n+  nextProps,\n+  lifecycle,\n+  eventProxy,\n+  isSvg,\n+  isRecycled\n+) {\n+  for (var name in merge(lastProps, nextProps)) {\n+    if (\n+      (name === \"value\" || name === \"checked\"\n+        ? element[name]\n+        : lastProps[name]) !== nextProps[name]\n+    ) {\n+      updateProperty(\n+        element,\n+        name,\n+        lastProps[name],\n+        nextProps[name],\n+        eventProxy,\n+        isSvg\n+      )\n     }\n+  }\n \n-    isRecycling = false\n+  var cb = isRecycled ? nextProps.onCreate : nextProps.onUpdate\n+  if (cb != null) {\n+    lifecycle.push(function() {\n+      cb(element, lastProps)\n+    })\n+  }\n+}\n \n-    while (lifecycle.length) lifecycle.pop()()\n+var removeChildren = function(node) {\n+  for (var i = 0, length = node.children.length; i < length; i++) {\n+    removeChildren(node.children[i])\n   }\n \n-  function scheduleRender() {\n-    if (!skipRender) {\n-      skipRender = true\n-      setTimeout(render)\n-    }\n+  var cb = node.props.onDestroy\n+  if (cb != null) {\n+    cb(node.element)\n   }\n \n-  function clone(target, source) {\n-    var out = {}\n+  return node.element\n+}\n \n-    for (var i in target) out[i] = target[i]\n-    for (var i in source) out[i] = source[i]\n+var removeElement = function(parent, node) {\n+  var remove = function() {\n+    parent.removeChild(removeChildren(node))\n+  }\n \n-    return out\n+  var cb = node.props && node.props.onRemove\n+  if (cb != null) {\n+    cb(node.element, remove)\n+  } else {\n+    remove()\n   }\n+}\n+\n+var getKey = function(node) {\n+  return node == null ? null : node.key\n+}\n+\n+var createKeyMap = function(children, start, end) {\n+  var out = {}\n+  var key\n+  var node\n \n-  function setPartialState(path, value, source) {\n-    var target = {}\n-    if (path.length) {\n-      target[path[0]] =\n-        path.length > 1\n-          ? setPartialState(path.slice(1), value, source[path[0]])\n-          : value\n-      return clone(source, target)\n+  for (; start <= end; start++) {\n+    if ((key = (node = children[start]).key) != null) {\n+      out[key] = node\n     }\n-    return value\n   }\n \n-  function getPartialState(path, source) {\n-    var i = 0\n-    while (i < path.length) {\n-      source = source[path[i++]]\n+  return out\n+}\n+\n+var patchElement = function(\n+  parent,\n+  element,\n+  lastNode,\n+  nextNode,\n+  lifecycle,\n+  eventProxy,\n+  isSvg\n+) {\n+  if (nextNode === lastNode) {\n+  } else if (\n+    lastNode != null &&\n+    lastNode.type === TEXT_NODE &&\n+    nextNode.type === TEXT_NODE\n+  ) {\n+    if (lastNode.name !== nextNode.name) {\n+      element.nodeValue = nextNode.name\n     }\n-    return source\n-  }\n+  } else if (lastNode == null || lastNode.name !== nextNode.name) {\n+    var newElement = parent.insertBefore(\n+      createElement(nextNode, lifecycle, eventProxy, isSvg),\n+      element\n+    )\n+\n+    if (lastNode != null) removeElement(parent, lastNode)\n+\n+    element = newElement\n+  } else {\n+    updateElement(\n+      element,\n+      lastNode.props,\n+      nextNode.props,\n+      lifecycle,\n+      eventProxy,\n+      (isSvg = isSvg || nextNode.name === \"svg\"),\n+      lastNode.type === RECYCLED_NODE\n+    )\n+\n+    var savedNode\n+    var childNode\n+\n+    var lastKey\n+    var lastChildren = lastNode.children\n+    var lastChStart = 0\n+    var lastChEnd = lastChildren.length - 1\n+\n+    var nextKey\n+    var nextChildren = nextNode.children\n+    var nextChStart = 0\n+    var nextChEnd = nextChildren.length - 1\n+\n+    while (nextChStart <= nextChEnd && lastChStart <= lastChEnd) {\n+      lastKey = getKey(lastChildren[lastChStart])\n+      nextKey = getKey(nextChildren[nextChStart])\n+\n+      if (lastKey == null || lastKey !== nextKey) break\n+\n+      patchElement(\n+        element,\n+        lastChildren[lastChStart].element,\n+        lastChildren[lastChStart],\n+        nextChildren[nextChStart],\n+        lifecycle,\n+        eventProxy,\n+        isSvg\n+      )\n \n-  function wireStateToActions(path, state, actions) {\n-    for (var key in actions) {\n-      typeof actions[key] === \"function\"\n-        ? (function(key, action) {\n-            actions[key] = function(data) {\n-              var result = action(data)\n-\n-              if (typeof result === \"function\") {\n-                result = result(getPartialState(path, globalState), actions)\n-              }\n-\n-              if (\n-                result &&\n-                result !== (state = getPartialState(path, globalState)) &&\n-                !result.then // !isPromise\n-              ) {\n-                scheduleRender(\n-                  (globalState = setPartialState(\n-                    path,\n-                    clone(state, result),\n-                    globalState\n-                  ))\n-                )\n-              }\n-\n-              return result\n-            }\n-          })(key, actions[key])\n-        : wireStateToActions(\n-            path.concat(key),\n-            (state[key] = clone(state[key])),\n-            (actions[key] = clone(actions[key]))\n-          )\n+      lastChStart++\n+      nextChStart++\n     }\n \n-    return actions\n-  }\n+    while (nextChStart <= nextChEnd && lastChStart <= lastChEnd) {\n+      lastKey = getKey(lastChildren[lastChEnd])\n+      nextKey = getKey(nextChildren[nextChEnd])\n \n-  function getKey(node) {\n-    return node ? node.key : null\n-  }\n+      if (lastKey == null || lastKey !== nextKey) break\n \n-  function eventListener(event) {\n-    return event.currentTarget.events[event.type](event)\n-  }\n+      patchElement(\n+        element,\n+        lastChildren[lastChEnd].element,\n+        lastChildren[lastChEnd],\n+        nextChildren[nextChEnd],\n+        lifecycle,\n+        eventProxy,\n+        isSvg\n+      )\n \n-  function updateAttribute(element, name, value, oldValue, isSvg) {\n-    if (name === \"key\") {\n-    } else if (name === \"style\") {\n-      for (var i in clone(oldValue, value)) {\n-        var style = value == null || value[i] == null ? \"\" : value[i]\n-        if (i[0] === \"-\") {\n-          element[name].setProperty(i, style)\n-        } else {\n-          element[name][i] = style\n-        }\n+      lastChEnd--\n+      nextChEnd--\n+    }\n+\n+    if (lastChStart > lastChEnd) {\n+      while (nextChStart <= nextChEnd) {\n+        element.insertBefore(\n+          createElement(\n+            nextChildren[nextChStart++],\n+            lifecycle,\n+            eventProxy,\n+            isSvg\n+          ),\n+          (childNode = lastChildren[lastChStart]) && childNode.element\n+        )\n+      }\n+    } else if (nextChStart > nextChEnd) {\n+      while (lastChStart <= lastChEnd) {\n+        removeElement(element, lastChildren[lastChStart++])\n       }\n     } else {\n-      if (name[0] === \"o\" && name[1] === \"n\") {\n-        name = name.slice(2)\n-\n-        if (element.events) {\n-          if (!oldValue) oldValue = element.events[name]\n-        } else {\n-          element.events = {}\n+      var lastKeyed = createKeyMap(lastChildren, lastChStart, lastChEnd)\n+      var nextKeyed = {}\n+\n+      while (nextChStart <= nextChEnd) {\n+        lastKey = getKey((childNode = lastChildren[lastChStart]))\n+        nextKey = getKey(nextChildren[nextChStart])\n+\n+        if (\n+          nextKeyed[lastKey] ||\n+          (nextKey != null && nextKey === getKey(lastChildren[lastChStart + 1]))\n+        ) {\n+          if (lastKey == null) {\n+            removeElement(element, childNode)\n+          }\n+          lastChStart++\n+          continue\n         }\n \n-        element.events[name] = value\n-\n-        if (value) {\n-          if (!oldValue) {\n-            element.addEventListener(name, eventListener)\n+        if (nextKey == null || lastNode.type === RECYCLED_NODE) {\n+          if (lastKey == null) {\n+            patchElement(\n+              element,\n+              childNode && childNode.element,\n+              childNode,\n+              nextChildren[nextChStart],\n+              lifecycle,\n+              eventProxy,\n+              isSvg\n+            )\n+            nextChStart++\n           }\n+          lastChStart++\n         } else {\n-          element.removeEventListener(name, eventListener)\n+          if (lastKey === nextKey) {\n+            patchElement(\n+              element,\n+              childNode.element,\n+              childNode,\n+              nextChildren[nextChStart],\n+              lifecycle,\n+              eventProxy,\n+              isSvg\n+            )\n+            nextKeyed[nextKey] = true\n+            lastChStart++\n+          } else {\n+            if ((savedNode = lastKeyed[nextKey]) != null) {\n+              patchElement(\n+                element,\n+                element.insertBefore(\n+                  savedNode.element,\n+                  childNode && childNode.element\n+                ),\n+                savedNode,\n+                nextChildren[nextChStart],\n+                lifecycle,\n+                eventProxy,\n+                isSvg\n+              )\n+              nextKeyed[nextKey] = true\n+            } else {\n+              patchElement(\n+                element,\n+                childNode && childNode.element,\n+                null,\n+                nextChildren[nextChStart],\n+                lifecycle,\n+                eventProxy,\n+                isSvg\n+              )\n+            }\n+          }\n+          nextChStart++\n         }\n-      } else if (name in element && name !== \"list\" && !isSvg) {\n-        element[name] = value == null ? \"\" : value\n-      } else if (value != null && value !== false) {\n-        element.setAttribute(name, value)\n       }\n \n-      if (value == null || value === false) {\n-        element.removeAttribute(name)\n+      while (lastChStart <= lastChEnd) {\n+        if (getKey((childNode = lastChildren[lastChStart++])) == null) {\n+          removeElement(element, childNode)\n+        }\n+      }\n+\n+      for (var key in lastKeyed) {\n+        if (nextKeyed[key] == null) {\n+          removeElement(element, lastKeyed[key])\n+        }\n       }\n     }\n   }\n \n-  function createElement(node, isSvg) {\n-    var element =\n-      typeof node === \"string\" || typeof node === \"number\"\n-        ? document.createTextNode(node)\n-        : (isSvg = isSvg || node.nodeName === \"svg\")\n-          ? document.createElementNS(\n-              \"http://www.w3.org/2000/svg\",\n-              node.nodeName\n-            )\n-          : document.createElement(node.nodeName)\n-\n-    var attributes = node.attributes\n-    if (attributes) {\n-      if (attributes.oncreate) {\n-        lifecycle.push(function() {\n-          attributes.oncreate(element)\n-        })\n-      }\n+  return (nextNode.element = element)\n+}\n \n-      for (var i = 0; i < node.children.length; i++) {\n-        element.appendChild(\n-          createElement(\n-            (node.children[i] = resolveNode(node.children[i])),\n-            isSvg\n-          )\n-        )\n-      }\n+var createVNode = function(name, props, children, element, key, type) {\n+  return {\n+    name: name,\n+    props: props,\n+    children: children,\n+    element: element,\n+    key: key,\n+    type: type\n+  }\n+}\n \n-      for (var name in attributes) {\n-        updateAttribute(element, name, attributes[name], null, isSvg)\n-      }\n-    }\n+var createTextVNode = function(text, element) {\n+  return createVNode(text, EMPTY_OBJECT, EMPTY_ARRAY, element, null, TEXT_NODE)\n+}\n \n-    return element\n-  }\n+var recycleChild = function(element) {\n+  return element.nodeType === 3 // Node.TEXT_NODE\n+    ? createTextVNode(element.nodeValue, element)\n+    : recycleElement(element)\n+}\n \n-  function updateElement(element, oldAttributes, attributes, isSvg) {\n-    for (var name in clone(oldAttributes, attributes)) {\n-      if (\n-        attributes[name] !==\n-        (name === \"value\" || name === \"checked\"\n-          ? element[name]\n-          : oldAttributes[name])\n-      ) {\n-        updateAttribute(\n-          element,\n-          name,\n-          attributes[name],\n-          oldAttributes[name],\n-          isSvg\n-        )\n-      }\n-    }\n+var recycleElement = function(element) {\n+  return createVNode(\n+    element.nodeName.toLowerCase(),\n+    EMPTY_OBJECT,\n+    map.call(element.childNodes, recycleChild),\n+    element,\n+    null,\n+    RECYCLED_NODE\n+  )\n+}\n \n-    var cb = isRecycling ? attributes.oncreate : attributes.onupdate\n-    if (cb) {\n-      lifecycle.push(function() {\n-        cb(element, oldAttributes)\n-      })\n-    }\n-  }\n+var patch = function(container, element, lastNode, nextNode, eventProxy) {\n+  var lifecycle = []\n \n-  function removeChildren(element, node) {\n-    var attributes = node.attributes\n-    if (attributes) {\n-      for (var i = 0; i < node.children.length; i++) {\n-        removeChildren(element.childNodes[i], node.children[i])\n-      }\n+  patchElement(container, element, lastNode, nextNode, lifecycle, eventProxy)\n \n-      if (attributes.ondestroy) {\n-        attributes.ondestroy(element)\n-      }\n-    }\n-    return element\n-  }\n+  while (lifecycle.length > 0) lifecycle.pop()()\n \n-  function removeElement(parent, element, node) {\n-    function done() {\n-      parent.removeChild(removeChildren(element, node))\n-    }\n+  return nextNode\n+}\n \n-    var cb = node.attributes && node.attributes.onremove\n-    if (cb) {\n-      cb(element, done)\n-    } else {\n-      done()\n+export var h = function(name, props) {\n+  var node\n+  var rest = []\n+  var children = []\n+  var length = arguments.length\n+\n+  while (length-- > 2) rest.push(arguments[length])\n+\n+  if ((props = props == null ? {} : props).children != null) {\n+    if (rest.length <= 0) {\n+      rest.push(props.children)\n     }\n+    delete props.children\n   }\n \n-  function patch(parent, element, oldNode, node, isSvg) {\n-    if (node === oldNode) {\n-    } else if (oldNode == null || oldNode.nodeName !== node.nodeName) {\n-      var newElement = createElement(node, isSvg)\n-      parent.insertBefore(newElement, element)\n-\n-      if (oldNode != null) {\n-        removeElement(parent, element, oldNode)\n+  while (rest.length > 0) {\n+    if (isArray((node = rest.pop()))) {\n+      for (length = node.length; length-- > 0; ) {\n+        rest.push(node[length])\n       }\n-\n-      element = newElement\n-    } else if (oldNode.nodeName == null) {\n-      element.nodeValue = node\n+    } else if (node === false || node === true || node == null) {\n     } else {\n-      updateElement(\n-        element,\n-        oldNode.attributes,\n-        node.attributes,\n-        (isSvg = isSvg || node.nodeName === \"svg\")\n-      )\n+      children.push(typeof node === \"object\" ? node : createTextVNode(node))\n+    }\n+  }\n \n-      var oldKeyed = {}\n-      var newKeyed = {}\n-      var oldElements = []\n-      var oldChildren = oldNode.children\n-      var children = node.children\n+  return typeof name === \"function\"\n+    ? name(props, (props.children = children))","path":"src/index.js","position":725,"original_position":725,"commit_id":"2b3d85625321038ed2369ddb4ecc320a9e20984e","original_commit_id":"2b3d85625321038ed2369ddb4ecc320a9e20984e","user":{"login":"frenzzy","id":640669,"node_id":"MDQ6VXNlcjY0MDY2OQ==","avatar_url":"https://avatars2.githubusercontent.com/u/640669?v=4","gravatar_id":"","url":"https://api.github.com/users/frenzzy","html_url":"https://github.com/frenzzy","followers_url":"https://api.github.com/users/frenzzy/followers","following_url":"https://api.github.com/users/frenzzy/following{/other_user}","gists_url":"https://api.github.com/users/frenzzy/gists{/gist_id}","starred_url":"https://api.github.com/users/frenzzy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/frenzzy/subscriptions","organizations_url":"https://api.github.com/users/frenzzy/orgs","repos_url":"https://api.github.com/users/frenzzy/repos","events_url":"https://api.github.com/users/frenzzy/events{/privacy}","received_events_url":"https://api.github.com/users/frenzzy/received_events","type":"User","site_admin":false},"body":"`props.children` definitely cooler then the second argument, see pros and cons here: https://github.com/hyperapp/hyperapp/issues/569\r\nI am worried only about performance and memoization:\r\nhttps://github.com/hyperapp/hyperapp/blob/2b3d85625321038ed2369ddb4ecc320a9e20984e/src/index.js#L458\r\n\r\nIf everything is ok with `props.children` would be nice to remove `children` from the second argument IMO.","created_at":"2018-07-10T20:16:35Z","updated_at":"2018-07-10T20:16:35Z","html_url":"https://github.com/hyperapp/hyperapp/pull/726#discussion_r201479314","pull_request_url":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726","author_association":"MEMBER","_links":{"self":{"href":"https://api.github.com/repos/hyperapp/hyperapp/pulls/comments/201479314"},"html":{"href":"https://github.com/hyperapp/hyperapp/pull/726#discussion_r201479314"},"pull_request":{"href":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726"}},"in_reply_to_id":201326488},"pull_request":{"url":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726","id":199988077,"node_id":"MDExOlB1bGxSZXF1ZXN0MTk5OTg4MDc3","html_url":"https://github.com/hyperapp/hyperapp/pull/726","diff_url":"https://github.com/hyperapp/hyperapp/pull/726.diff","patch_url":"https://github.com/hyperapp/hyperapp/pull/726.patch","issue_url":"https://api.github.com/repos/hyperapp/hyperapp/issues/726","number":726,"state":"open","locked":false,"title":"V2","user":{"login":"jorgebucaran","id":56996,"node_id":"MDQ6VXNlcjU2OTk2","avatar_url":"https://avatars1.githubusercontent.com/u/56996?v=4","gravatar_id":"","url":"https://api.github.com/users/jorgebucaran","html_url":"https://github.com/jorgebucaran","followers_url":"https://api.github.com/users/jorgebucaran/followers","following_url":"https://api.github.com/users/jorgebucaran/following{/other_user}","gists_url":"https://api.github.com/users/jorgebucaran/gists{/gist_id}","starred_url":"https://api.github.com/users/jorgebucaran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jorgebucaran/subscriptions","organizations_url":"https://api.github.com/users/jorgebucaran/orgs","repos_url":"https://api.github.com/users/jorgebucaran/repos","events_url":"https://api.github.com/users/jorgebucaran/events{/privacy}","received_events_url":"https://api.github.com/users/jorgebucaran/received_events","type":"User","site_admin":false},"body":"Here's V2. I'll be updating this issue as we go. \r\n\r\n---\r\n\r\n### How state update works?\r\nThe new state update strategy is by replacing the current value with the new value. Before we would merge the return value of your action with the current state. Now, we replace it. Therefore, you always need the current state in order to calculate the next state.\r\n","created_at":"2018-07-09T04:20:37Z","updated_at":"2018-07-10T20:16:35Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ae17b594aed6d5edd6a8a9e9092184ae7f140c8b","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[{"id":745517151,"node_id":"MDU6TGFiZWw3NDU1MTcxNTE=","url":"https://api.github.com/repos/hyperapp/hyperapp/labels/BREAKING","name":"BREAKING","color":"ee0000","default":false}],"milestone":{"url":"https://api.github.com/repos/hyperapp/hyperapp/milestones/7","html_url":"https://github.com/hyperapp/hyperapp/milestone/7","labels_url":"https://api.github.com/repos/hyperapp/hyperapp/milestones/7/labels","id":3370575,"node_id":"MDk6TWlsZXN0b25lMzM3MDU3NQ==","number":7,"title":"2.0.0","description":"","creator":{"login":"jorgebucaran","id":56996,"node_id":"MDQ6VXNlcjU2OTk2","avatar_url":"https://avatars1.githubusercontent.com/u/56996?v=4","gravatar_id":"","url":"https://api.github.com/users/jorgebucaran","html_url":"https://github.com/jorgebucaran","followers_url":"https://api.github.com/users/jorgebucaran/followers","following_url":"https://api.github.com/users/jorgebucaran/following{/other_user}","gists_url":"https://api.github.com/users/jorgebucaran/gists{/gist_id}","starred_url":"https://api.github.com/users/jorgebucaran/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jorgebucaran/subscriptions","organizations_url":"https://api.github.com/users/jorgebucaran/orgs","repos_url":"https://api.github.com/users/jorgebucaran/repos","events_url":"https://api.github.com/users/jorgebucaran/events{/privacy}","received_events_url":"https://api.github.com/users/jorgebucaran/received_events","type":"User","site_admin":false},"open_issues":2,"closed_issues":0,"state":"open","created_at":"2018-05-24T01:53:15Z","updated_at":"2018-07-09T04:20:37Z","due_on":"2018-07-09T07:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726/commits","review_comments_url":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726/comments","review_comment_url":"https://api.github.com/repos/hyperapp/hyperapp/pulls/comments{/number}","comments_url":"https://api.github.com/repos/hyperapp/hyperapp/issues/726/comments","statuses_url":"https://api.github.com/repos/hyperapp/hyperapp/statuses/2b3d85625321038ed2369ddb4ecc320a9e20984e","head":{"label":"hyperapp:V2","ref":"V2","sha":"2b3d85625321038ed2369ddb4ecc320a9e20984e","user":{"login":"hyperapp","id":25238911,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI1MjM4OTEx","avatar_url":"https://avatars2.githubusercontent.com/u/25238911?v=4","gravatar_id":"","url":"https://api.github.com/users/hyperapp","html_url":"https://github.com/hyperapp","followers_url":"https://api.github.com/users/hyperapp/followers","following_url":"https://api.github.com/users/hyperapp/following{/other_user}","gists_url":"https://api.github.com/users/hyperapp/gists{/gist_id}","starred_url":"https://api.github.com/users/hyperapp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hyperapp/subscriptions","organizations_url":"https://api.github.com/users/hyperapp/orgs","repos_url":"https://api.github.com/users/hyperapp/repos","events_url":"https://api.github.com/users/hyperapp/events{/privacy}","received_events_url":"https://api.github.com/users/hyperapp/received_events","type":"Organization","site_admin":false},"repo":{"id":79527893,"node_id":"MDEwOlJlcG9zaXRvcnk3OTUyNzg5Mw==","name":"hyperapp","full_name":"hyperapp/hyperapp","owner":{"login":"hyperapp","id":25238911,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI1MjM4OTEx","avatar_url":"https://avatars2.githubusercontent.com/u/25238911?v=4","gravatar_id":"","url":"https://api.github.com/users/hyperapp","html_url":"https://github.com/hyperapp","followers_url":"https://api.github.com/users/hyperapp/followers","following_url":"https://api.github.com/users/hyperapp/following{/other_user}","gists_url":"https://api.github.com/users/hyperapp/gists{/gist_id}","starred_url":"https://api.github.com/users/hyperapp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hyperapp/subscriptions","organizations_url":"https://api.github.com/users/hyperapp/orgs","repos_url":"https://api.github.com/users/hyperapp/repos","events_url":"https://api.github.com/users/hyperapp/events{/privacy}","received_events_url":"https://api.github.com/users/hyperapp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hyperapp/hyperapp","description":"1 kB JavaScript framework for building web applications.","fork":false,"url":"https://api.github.com/repos/hyperapp/hyperapp","forks_url":"https://api.github.com/repos/hyperapp/hyperapp/forks","keys_url":"https://api.github.com/repos/hyperapp/hyperapp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hyperapp/hyperapp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hyperapp/hyperapp/teams","hooks_url":"https://api.github.com/repos/hyperapp/hyperapp/hooks","issue_events_url":"https://api.github.com/repos/hyperapp/hyperapp/issues/events{/number}","events_url":"https://api.github.com/repos/hyperapp/hyperapp/events","assignees_url":"https://api.github.com/repos/hyperapp/hyperapp/assignees{/user}","branches_url":"https://api.github.com/repos/hyperapp/hyperapp/branches{/branch}","tags_url":"https://api.github.com/repos/hyperapp/hyperapp/tags","blobs_url":"https://api.github.com/repos/hyperapp/hyperapp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hyperapp/hyperapp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hyperapp/hyperapp/git/refs{/sha}","trees_url":"https://api.github.com/repos/hyperapp/hyperapp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hyperapp/hyperapp/statuses/{sha}","languages_url":"https://api.github.com/repos/hyperapp/hyperapp/languages","stargazers_url":"https://api.github.com/repos/hyperapp/hyperapp/stargazers","contributors_url":"https://api.github.com/repos/hyperapp/hyperapp/contributors","subscribers_url":"https://api.github.com/repos/hyperapp/hyperapp/subscribers","subscription_url":"https://api.github.com/repos/hyperapp/hyperapp/subscription","commits_url":"https://api.github.com/repos/hyperapp/hyperapp/commits{/sha}","git_commits_url":"https://api.github.com/repos/hyperapp/hyperapp/git/commits{/sha}","comments_url":"https://api.github.com/repos/hyperapp/hyperapp/comments{/number}","issue_comment_url":"https://api.github.com/repos/hyperapp/hyperapp/issues/comments{/number}","contents_url":"https://api.github.com/repos/hyperapp/hyperapp/contents/{+path}","compare_url":"https://api.github.com/repos/hyperapp/hyperapp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hyperapp/hyperapp/merges","archive_url":"https://api.github.com/repos/hyperapp/hyperapp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hyperapp/hyperapp/downloads","issues_url":"https://api.github.com/repos/hyperapp/hyperapp/issues{/number}","pulls_url":"https://api.github.com/repos/hyperapp/hyperapp/pulls{/number}","milestones_url":"https://api.github.com/repos/hyperapp/hyperapp/milestones{/number}","notifications_url":"https://api.github.com/repos/hyperapp/hyperapp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hyperapp/hyperapp/labels{/name}","releases_url":"https://api.github.com/repos/hyperapp/hyperapp/releases{/id}","deployments_url":"https://api.github.com/repos/hyperapp/hyperapp/deployments","created_at":"2017-01-20T05:20:21Z","updated_at":"2018-07-10T17:23:36Z","pushed_at":"2018-07-09T20:36:42Z","git_url":"git://github.com/hyperapp/hyperapp.git","ssh_url":"git@github.com:hyperapp/hyperapp.git","clone_url":"https://github.com/hyperapp/hyperapp.git","svn_url":"https://github.com/hyperapp/hyperapp","homepage":"https://hyperapp.js.org","size":1517,"stargazers_count":14485,"watchers_count":14485,"language":"JavaScript","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":655,"mirror_url":null,"archived":false,"open_issues_count":37,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":655,"open_issues":37,"watchers":14485,"default_branch":"master"}},"base":{"label":"hyperapp:master","ref":"master","sha":"ebe173af6e11812e4abce9ad95b15a9092c3ef86","user":{"login":"hyperapp","id":25238911,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI1MjM4OTEx","avatar_url":"https://avatars2.githubusercontent.com/u/25238911?v=4","gravatar_id":"","url":"https://api.github.com/users/hyperapp","html_url":"https://github.com/hyperapp","followers_url":"https://api.github.com/users/hyperapp/followers","following_url":"https://api.github.com/users/hyperapp/following{/other_user}","gists_url":"https://api.github.com/users/hyperapp/gists{/gist_id}","starred_url":"https://api.github.com/users/hyperapp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hyperapp/subscriptions","organizations_url":"https://api.github.com/users/hyperapp/orgs","repos_url":"https://api.github.com/users/hyperapp/repos","events_url":"https://api.github.com/users/hyperapp/events{/privacy}","received_events_url":"https://api.github.com/users/hyperapp/received_events","type":"Organization","site_admin":false},"repo":{"id":79527893,"node_id":"MDEwOlJlcG9zaXRvcnk3OTUyNzg5Mw==","name":"hyperapp","full_name":"hyperapp/hyperapp","owner":{"login":"hyperapp","id":25238911,"node_id":"MDEyOk9yZ2FuaXphdGlvbjI1MjM4OTEx","avatar_url":"https://avatars2.githubusercontent.com/u/25238911?v=4","gravatar_id":"","url":"https://api.github.com/users/hyperapp","html_url":"https://github.com/hyperapp","followers_url":"https://api.github.com/users/hyperapp/followers","following_url":"https://api.github.com/users/hyperapp/following{/other_user}","gists_url":"https://api.github.com/users/hyperapp/gists{/gist_id}","starred_url":"https://api.github.com/users/hyperapp/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hyperapp/subscriptions","organizations_url":"https://api.github.com/users/hyperapp/orgs","repos_url":"https://api.github.com/users/hyperapp/repos","events_url":"https://api.github.com/users/hyperapp/events{/privacy}","received_events_url":"https://api.github.com/users/hyperapp/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/hyperapp/hyperapp","description":"1 kB JavaScript framework for building web applications.","fork":false,"url":"https://api.github.com/repos/hyperapp/hyperapp","forks_url":"https://api.github.com/repos/hyperapp/hyperapp/forks","keys_url":"https://api.github.com/repos/hyperapp/hyperapp/keys{/key_id}","collaborators_url":"https://api.github.com/repos/hyperapp/hyperapp/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/hyperapp/hyperapp/teams","hooks_url":"https://api.github.com/repos/hyperapp/hyperapp/hooks","issue_events_url":"https://api.github.com/repos/hyperapp/hyperapp/issues/events{/number}","events_url":"https://api.github.com/repos/hyperapp/hyperapp/events","assignees_url":"https://api.github.com/repos/hyperapp/hyperapp/assignees{/user}","branches_url":"https://api.github.com/repos/hyperapp/hyperapp/branches{/branch}","tags_url":"https://api.github.com/repos/hyperapp/hyperapp/tags","blobs_url":"https://api.github.com/repos/hyperapp/hyperapp/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/hyperapp/hyperapp/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/hyperapp/hyperapp/git/refs{/sha}","trees_url":"https://api.github.com/repos/hyperapp/hyperapp/git/trees{/sha}","statuses_url":"https://api.github.com/repos/hyperapp/hyperapp/statuses/{sha}","languages_url":"https://api.github.com/repos/hyperapp/hyperapp/languages","stargazers_url":"https://api.github.com/repos/hyperapp/hyperapp/stargazers","contributors_url":"https://api.github.com/repos/hyperapp/hyperapp/contributors","subscribers_url":"https://api.github.com/repos/hyperapp/hyperapp/subscribers","subscription_url":"https://api.github.com/repos/hyperapp/hyperapp/subscription","commits_url":"https://api.github.com/repos/hyperapp/hyperapp/commits{/sha}","git_commits_url":"https://api.github.com/repos/hyperapp/hyperapp/git/commits{/sha}","comments_url":"https://api.github.com/repos/hyperapp/hyperapp/comments{/number}","issue_comment_url":"https://api.github.com/repos/hyperapp/hyperapp/issues/comments{/number}","contents_url":"https://api.github.com/repos/hyperapp/hyperapp/contents/{+path}","compare_url":"https://api.github.com/repos/hyperapp/hyperapp/compare/{base}...{head}","merges_url":"https://api.github.com/repos/hyperapp/hyperapp/merges","archive_url":"https://api.github.com/repos/hyperapp/hyperapp/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/hyperapp/hyperapp/downloads","issues_url":"https://api.github.com/repos/hyperapp/hyperapp/issues{/number}","pulls_url":"https://api.github.com/repos/hyperapp/hyperapp/pulls{/number}","milestones_url":"https://api.github.com/repos/hyperapp/hyperapp/milestones{/number}","notifications_url":"https://api.github.com/repos/hyperapp/hyperapp/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/hyperapp/hyperapp/labels{/name}","releases_url":"https://api.github.com/repos/hyperapp/hyperapp/releases{/id}","deployments_url":"https://api.github.com/repos/hyperapp/hyperapp/deployments","created_at":"2017-01-20T05:20:21Z","updated_at":"2018-07-10T17:23:36Z","pushed_at":"2018-07-09T20:36:42Z","git_url":"git://github.com/hyperapp/hyperapp.git","ssh_url":"git@github.com:hyperapp/hyperapp.git","clone_url":"https://github.com/hyperapp/hyperapp.git","svn_url":"https://github.com/hyperapp/hyperapp","homepage":"https://hyperapp.js.org","size":1517,"stargazers_count":14485,"watchers_count":14485,"language":"JavaScript","has_issues":true,"has_projects":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":655,"mirror_url":null,"archived":false,"open_issues_count":37,"license":{"key":"mit","name":"MIT License","spdx_id":"MIT","url":"https://api.github.com/licenses/mit","node_id":"MDc6TGljZW5zZTEz"},"forks":655,"open_issues":37,"watchers":14485,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726"},"html":{"href":"https://github.com/hyperapp/hyperapp/pull/726"},"issue":{"href":"https://api.github.com/repos/hyperapp/hyperapp/issues/726"},"comments":{"href":"https://api.github.com/repos/hyperapp/hyperapp/issues/726/comments"},"review_comments":{"href":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726/comments"},"review_comment":{"href":"https://api.github.com/repos/hyperapp/hyperapp/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/hyperapp/hyperapp/pulls/726/commits"},"statuses":{"href":"https://api.github.com/repos/hyperapp/hyperapp/statuses/2b3d85625321038ed2369ddb4ecc320a9e20984e"}},"author_association":"MEMBER"}}
{"actor":{"display_login":"frenzzy"}}