{"action":"created","issue":{"url":"https://api.github.com/repos/corpusculejs/corpuscule/issues/19","repository_url":"https://api.github.com/repos/corpusculejs/corpuscule","labels_url":"https://api.github.com/repos/corpusculejs/corpuscule/issues/19/labels{/name}","comments_url":"https://api.github.com/repos/corpusculejs/corpuscule/issues/19/comments","events_url":"https://api.github.com/repos/corpusculejs/corpuscule/issues/19/events","html_url":"https://github.com/corpusculejs/corpuscule/pull/19","id":379464364,"node_id":"MDExOlB1bGxSZXF1ZXN0MjI5OTE1MTU4","number":19,"title":"New architecture","user":{"login":"Lodin","id":8037479,"node_id":"MDQ6VXNlcjgwMzc0Nzk=","avatar_url":"https://avatars0.githubusercontent.com/u/8037479?v=4","gravatar_id":"","url":"https://api.github.com/users/Lodin","html_url":"https://github.com/Lodin","followers_url":"https://api.github.com/users/Lodin/followers","following_url":"https://api.github.com/users/Lodin/following{/other_user}","gists_url":"https://api.github.com/users/Lodin/gists{/gist_id}","starred_url":"https://api.github.com/users/Lodin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Lodin/subscriptions","organizations_url":"https://api.github.com/users/Lodin/orgs","repos_url":"https://api.github.com/users/Lodin/repos","events_url":"https://api.github.com/users/Lodin/events{/privacy}","received_events_url":"https://api.github.com/users/Lodin/received_events","type":"User","site_admin":false},"labels":[{"id":912272393,"node_id":"MDU6TGFiZWw5MTIyNzIzOTM=","url":"https://api.github.com/repos/corpusculejs/corpuscule/labels/enhancement","name":"enhancement","color":"a2eeef","default":true}],"state":"open","locked":false,"assignee":{"login":"Lodin","id":8037479,"node_id":"MDQ6VXNlcjgwMzc0Nzk=","avatar_url":"https://avatars0.githubusercontent.com/u/8037479?v=4","gravatar_id":"","url":"https://api.github.com/users/Lodin","html_url":"https://github.com/Lodin","followers_url":"https://api.github.com/users/Lodin/followers","following_url":"https://api.github.com/users/Lodin/following{/other_user}","gists_url":"https://api.github.com/users/Lodin/gists{/gist_id}","starred_url":"https://api.github.com/users/Lodin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Lodin/subscriptions","organizations_url":"https://api.github.com/users/Lodin/orgs","repos_url":"https://api.github.com/users/Lodin/repos","events_url":"https://api.github.com/users/Lodin/events{/privacy}","received_events_url":"https://api.github.com/users/Lodin/received_events","type":"User","site_admin":false},"assignees":[{"login":"Lodin","id":8037479,"node_id":"MDQ6VXNlcjgwMzc0Nzk=","avatar_url":"https://avatars0.githubusercontent.com/u/8037479?v=4","gravatar_id":"","url":"https://api.github.com/users/Lodin","html_url":"https://github.com/Lodin","followers_url":"https://api.github.com/users/Lodin/followers","following_url":"https://api.github.com/users/Lodin/following{/other_user}","gists_url":"https://api.github.com/users/Lodin/gists{/gist_id}","starred_url":"https://api.github.com/users/Lodin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Lodin/subscriptions","organizations_url":"https://api.github.com/users/Lodin/orgs","repos_url":"https://api.github.com/users/Lodin/repos","events_url":"https://api.github.com/users/Lodin/events{/privacy}","received_events_url":"https://api.github.com/users/Lodin/received_events","type":"User","site_admin":false}],"milestone":null,"comments":0,"created_at":"2018-11-10T21:44:44Z","updated_at":"2018-11-10T21:58:48Z","closed_at":null,"author_association":"MEMBER","pull_request":{"url":"https://api.github.com/repos/corpusculejs/corpuscule/pulls/19","html_url":"https://github.com/corpusculejs/corpuscule/pull/19","diff_url":"https://github.com/corpusculejs/corpuscule/pull/19.diff","patch_url":"https://github.com/corpusculejs/corpuscule/pull/19.patch"},"body":"## Introduction\r\nThis PR reveals new architecture for a framework which does not follow React any more. Unfortunately, it becomes clear that React architecture is best for the React, but implementing it for web components looks like a mixing of two different approaches. Also, coming Private Properties proposal makes it even more harder. Also React now becomes more functional, especially with Hooks which does not an option for Corpuscule yet. \r\n\r\nSo, from now Corpuscule has different architecture and stops following React way. By the way, new architecture is closer to Vue which sounds ironically because I know almost nothing about it and never used it. \r\n\r\n## Details\r\nNew architecture tries to follow web components style as much as possible. It brings new opportunities along with new limitations. Let's take a look at them.\r\n\r\n### Terminology\r\nCorpuscule element has following types of class properties:\r\n* `attributes` - all properties marked with an `@attribute` decorator. They are nothing but a gateway for attributes, so each time you gets an attribute it takes a string value from element's attribute, converts it to the proper type and returns it to you. Setting attribute does the opposite work. Here the first limitation comes. To make attributes work as fast as possible they can be only `number`, `boolean` or `string`. Any other type could possible make requesting attributes very slow due to cost of conversion. Changing an attribute triggers the re-rendering of the element, but only if value of the attribute does not equal with the previous one.\r\n* `properties` - all properties marked with a `@property` decorator. All what makes it different from a usual class property is that they trigger re-rendering of the element. As attributes, all properties are pure: they can trigger re-rendering only if new and old values are different.\r\n* `states` - internal properties of the element that trigger re-rendering. They are not pure: each change of the state triggers re-rendering even if new and old value are the same. States should be used with caution: there is no protection for setting these properties from the top, so they are planned to be symbolic of private values to avoid unspecified usage. \r\n\r\n### Lifecycle\r\nNew list of lifecycle hooks, including hooks of web components, is following:\r\n* `constructor()` - usual class constructor.\r\n* `attributeChangedCallback(attributeName, oldValue, newValue)` - fires each time any attribute is changed with `setAttribute` or `removeAttribute`.\r\n* `connectedCallback()` - fires when element is connected to a DOM tree.\r\n* `disconnectedCallback()` - fires when element is disconnected from a DOM tree.\r\n* `[propertyChangedCallback](propertyKey, oldValue, newValue)` - fires each time any property marked with `@property` is changed.\r\n* `[stateChangedCallback](propertyKey, oldValue, newValue)` - fires each time any property marked with `@state` is changed.\r\n* `[updatedCallback]()` - fires when element rendering is over.\r\n\r\n### Decorators\r\n`CorpusculeElement` class is gone. It is common approach to inherit an HTMLElement and provide own class to be inherited to get all inner work. However, for Corpuscule it brought a lot of disadvantaged.\r\n\r\nThe main disadvantage comes from desire to use native callbacks instead of custom ones like `LitElement` does. But it brings a burden for users to call `super.connectedCallback()` each time they implement `connectedCallback`. And if they forgot or intentionally skip this step, CorpusculeElement will break. Also reimplementation of `attributeChangedCallback` or `[propertyChangedCallback]` would allow to avoid pureness check, and if for `[propertyChangedCallback]` it can be moved to a decorator implementation, `attributeChangedCallback` is called each time anyone calls `setAttribute` or `removeAttribtue` from the outside of the element's class. It is a potential vulnerability. But if the working function is defined __after__ the user's, it can call user's function at any time it wants. Decorators gave me this opportunity.\r\n\r\nNow all the work is being done by `@element` decorator. It redefines all lifecycle methods and calls user-defined methods at the time it want."},"comment":{"url":"https://api.github.com/repos/corpusculejs/corpuscule/issues/comments/437624545","html_url":"https://github.com/corpusculejs/corpuscule/pull/19#issuecomment-437624545","issue_url":"https://api.github.com/repos/corpusculejs/corpuscule/issues/19","id":437624545,"node_id":"MDEyOklzc3VlQ29tbWVudDQzNzYyNDU0NQ==","user":{"login":"codecov-io","id":8655789,"node_id":"MDQ6VXNlcjg2NTU3ODk=","avatar_url":"https://avatars0.githubusercontent.com/u/8655789?v=4","gravatar_id":"","url":"https://api.github.com/users/codecov-io","html_url":"https://github.com/codecov-io","followers_url":"https://api.github.com/users/codecov-io/followers","following_url":"https://api.github.com/users/codecov-io/following{/other_user}","gists_url":"https://api.github.com/users/codecov-io/gists{/gist_id}","starred_url":"https://api.github.com/users/codecov-io/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/codecov-io/subscriptions","organizations_url":"https://api.github.com/users/codecov-io/orgs","repos_url":"https://api.github.com/users/codecov-io/repos","events_url":"https://api.github.com/users/codecov-io/events{/privacy}","received_events_url":"https://api.github.com/users/codecov-io/received_events","type":"User","site_admin":false},"created_at":"2018-11-10T21:58:48Z","updated_at":"2018-11-10T21:58:48Z","author_association":"NONE","body":"# [Codecov](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=h1) Report\n> Merging [#19](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=desc) into [master](https://codecov.io/gh/corpusculejs/corpuscule/commit/e4b67e48e36c500870f7b1cd8219568d3541b3bd?src=pr&el=desc) will **decrease** coverage by `0.33%`.\n> The diff coverage is `99.56%`.\n\n[![Impacted file tree graph](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/graphs/tree.svg?width=650&token=KpgJ2F9wPW&height=150&src=pr)](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=tree)\n\n```diff\n@@            Coverage Diff             @@\n##           master      #19      +/-   ##\n==========================================\n- Coverage   98.84%   98.51%   -0.34%     \n==========================================\n  Files          26       28       +2     \n  Lines         434      404      -30     \n==========================================\n- Hits          429      398      -31     \n- Misses          5        6       +1\n```\n\n\n| [Impacted Files](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=tree) | Coverage Δ | |\n|---|---|---|\n| [packages/utils/src/descriptors.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvdXRpbHMvc3JjL2Rlc2NyaXB0b3JzLmpz) | `100% <100%> (ø)` | |\n| [packages/element/src/decorators/property.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvZWxlbWVudC9zcmMvZGVjb3JhdG9ycy9wcm9wZXJ0eS5qcw==) | `100% <100%> (ø)` | |\n| [packages/element/src/decorators/attribute.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvZWxlbWVudC9zcmMvZGVjb3JhdG9ycy9hdHRyaWJ1dGUuanM=) | `100% <100%> (ø)` | |\n| [packages/redux/src/index.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvcmVkdXgvc3JjL2luZGV4Lmpz) | `96.15% <100%> (ø)` | :arrow_up: |\n| [packages/styles/src/index.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvc3R5bGVzL3NyYy9pbmRleC5qcw==) | `100% <100%> (ø)` | :arrow_up: |\n| [packages/element/src/decorators/element.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvZWxlbWVudC9zcmMvZGVjb3JhdG9ycy9lbGVtZW50Lmpz) | `100% <100%> (ø)` | |\n| [packages/element/src/tokens/lifecycle.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvZWxlbWVudC9zcmMvdG9rZW5zL2xpZmVjeWNsZS5qcw==) | `100% <100%> (ø)` | :arrow_up: |\n| [packages/context/src/index.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvY29udGV4dC9zcmMvaW5kZXguanM=) | `96.49% <100%> (-0.12%)` | :arrow_down: |\n| [packages/router/src/outlet.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvcm91dGVyL3NyYy9vdXRsZXQuanM=) | `96% <100%> (-0.16%)` | :arrow_down: |\n| [packages/utils/src/addToRegistry.js](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree#diff-cGFja2FnZXMvdXRpbHMvc3JjL2FkZFRvUmVnaXN0cnkuanM=) | `100% <100%> (ø)` | :arrow_up: |\n| ... and [19 more](https://codecov.io/gh/corpusculejs/corpuscule/pull/19/diff?src=pr&el=tree-more) | |\n\n------\n\n[Continue to review full report at Codecov](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=continue).\n> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)\n> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`\n> Powered by [Codecov](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=footer). Last update [e4b67e4...6a5fb99](https://codecov.io/gh/corpusculejs/corpuscule/pull/19?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).\n"}}
{"actor":{"display_login":"codecov-io"}}