{"action":"closed","number":88,"pull_request":{"url":"https://api.github.com/repos/cleandart/react-dart/pulls/88","id":64673805,"html_url":"https://github.com/cleandart/react-dart/pull/88","diff_url":"https://github.com/cleandart/react-dart/pull/88.diff","patch_url":"https://github.com/cleandart/react-dart/pull/88.patch","issue_url":"https://api.github.com/repos/cleandart/react-dart/issues/88","number":88,"state":"closed","locked":false,"title":"New JS interop, performance/lifecycle improvements","user":{"login":"greglittlefield-wf","id":1713967,"avatar_url":"https://avatars.githubusercontent.com/u/1713967?v=3","gravatar_id":"","url":"https://api.github.com/users/greglittlefield-wf","html_url":"https://github.com/greglittlefield-wf","followers_url":"https://api.github.com/users/greglittlefield-wf/followers","following_url":"https://api.github.com/users/greglittlefield-wf/following{/other_user}","gists_url":"https://api.github.com/users/greglittlefield-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/greglittlefield-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/greglittlefield-wf/subscriptions","organizations_url":"https://api.github.com/users/greglittlefield-wf/orgs","repos_url":"https://api.github.com/users/greglittlefield-wf/repos","events_url":"https://api.github.com/users/greglittlefield-wf/events{/privacy}","received_events_url":"https://api.github.com/users/greglittlefield-wf/received_events","type":"User","site_admin":false},"body":"# Description\r\nDart 1.13 introduced the new [`js` package](https://pub.dartlang.org/packages/js), which provides an alternate Dart-JS interop that is faster than `dart:js` interop.\r\n\r\nreact-dart currently uses `dart:js` interop, and could benefit from performance improvements in `package:js`.\r\n\r\nThis PR upgrades react-dart to use `package:js`, and also includes other changes that improve performance and increase parity with React JS.\r\n\r\n## Performance data:\r\nPerformance tests were run on an earlier version of these changes, as well as for the current react-dart and React JS.\r\n\r\nFull results available [in this doc](https://docs.google.com/spreadsheets/d/1GB8QZZGlgFNw4gx6AuRA242Ardfei0sDAYRcHv_osLU/edit?usp=sharing\r\n). Includes data for:\r\n* \"unit\"-style rendering performance: (https://github.com/greglittlefield-wf/react-dart_perf_unit)\r\n* functional-style frame rate performance: (https://github.com/greglittlefield-wf/react-dart_perf/tree/new_react-dart_interop)\r\n\r\n_See https://github.com/greglittlefield-wf/react-dart_perf_unit/blob/master/README.md#improvement-details for more details on which performance improvements were included while testing._\r\n\r\nNote: these results also include numbers for a few potential dart2js optimizations (more details in the link above). I will follow up this PR with links to dart-lang/sdk GitHub issues regarding these potential optimizations.\r\n\r\n#### Summary of results\r\n###### react-dart Initial Rendering Time (in terms of pure JS time):\r\n* current: 14.3x\r\n* optimized: 5.7x\r\n* optimized + dart2js tweaks: 3.5x\r\n\r\n###### react-dart Frame Rate (% of pure JS React rate):\r\n* current: 21.5%\r\n* optimized: 46.5%\r\n* optimized + dart2js tweaks: 60.9%\r\n\r\n# Changes\r\n##### Performance improvements:\r\n* Use new `package:js` Dart-JS interop in `react_client` and `react_test_utils`.\r\n    * Update SDK constraint in `pubspec.yaml`.\r\n* Optimize event handler conversion by using a Map instead of if-else.\r\n* Lifecycle-related changes: the following React component lifecycle changes were made for the sake of performance as well as better parity with React JS:\r\n    * Remove `rootNode` argument from `componentDidMount`/`componentDidUpdate`.\r\n        * Prevents unnecessary calls to `findDOMNode` and creation of dart2js interceptors for Elements, which affects performance.\r\n    * Only call `getDefaultProps()` once and cache the result.\r\n    * Merge default props only once, in the component factory.\r\n    * Cache `nextProps` on the component to prevent excessive calls to `_getNextProps`.\r\n\r\n##### Other changes\r\n* Use a Dart class (`ReactDartComponentInternal`) instead of a Map for managing react-dart component internals.\r\n* Store internal object in the JS props at the `internal` key, instead of `__internal__`.\r\n    * `package:js` doesn't allow you to proxy fields starting with underscores without making them private.\r\n* Don't expose `key`/`ref` in a rendered component's props (React JS started doing this [in 0.12](https://facebook.github.io/react/blog/2014/10/16/react-v0.12-rc1.html#breaking-change-key-and-ref-removed-from-this.props)).\r\n* Add `test/lifecycle_test` to verify the lifecycle behavior of Dart components.\r\n* `shouldComponentUpdate`, `componentDidUpdate`, and `componentWillUnmount` are no longer skippable via `skipMethods`.\r\n\r\n### Breaking Changes\r\nFrom the changes mentioned above, the following are breaking:\r\n* react-dart now requires a Dart SDK of `>=1.13.0`.\r\n* `componentDidMount`/`componentDidUpdate` no longer have the `rootNode` argument. \r\n* `ReactElement`s now always have default props merged in.\r\n* `package:js` interop-related:\r\n    * React element instances are now of type `ReactElement`, not `JsObject`.\r\n        * (These are the objects returned when invoking a component factory.) \r\n    * React component instances are now of type `ReactComponent`, not `JsObject`.\r\n        * (These are the objects returned by `ref` and `react.render`.)\r\n    * React component classes are now of type `ReactClass`, not `JsFunction`\r\n    * JS props are now `package:js` interop objects, not `JsObject`.\r\n* `props['children']` is now a non-growable `List`.\r\n* Internals:\r\n    * A Dart class (`ReactDartComponentInternal`) is used instead of a Map for managing react-dart component internals.\r\n    * The react-dart \"internal\" object is stored in the JS props at the `internal` key, instead of `__internal__`.\r\n\r\n# Testing\r\n* In both Dartium and dart2js:\r\n    * Verify that all tests in `test/` pass.\r\n    * Verify that all examples in `example/test/` work as expected.\r\n\r\n---\r\n\r\n@hleumas @trentgrover-wf @evanweible-wf @maxwellpeterson-wf @timmccall-wf @todbachman-wf @aaronlademann-wf @clairesarsam-wf @jacehensley-wf @joelleibow-wf","created_at":"2016-03-30T18:24:23Z","updated_at":"2016-04-07T19:07:28Z","closed_at":"2016-04-07T19:07:28Z","merged_at":"2016-04-07T19:07:28Z","merge_commit_sha":"25ec46a62181bfaa9eb75e7e33194ed709138704","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/cleandart/react-dart/pulls/88/commits","review_comments_url":"https://api.github.com/repos/cleandart/react-dart/pulls/88/comments","review_comment_url":"https://api.github.com/repos/cleandart/react-dart/pulls/comments{/number}","comments_url":"https://api.github.com/repos/cleandart/react-dart/issues/88/comments","statuses_url":"https://api.github.com/repos/cleandart/react-dart/statuses/3fb7430f994475c2f12d946534dca8169c703840","head":{"label":"greglittlefield-wf:performance_and_lifcycle_improvements","ref":"performance_and_lifcycle_improvements","sha":"3fb7430f994475c2f12d946534dca8169c703840","user":{"login":"greglittlefield-wf","id":1713967,"avatar_url":"https://avatars.githubusercontent.com/u/1713967?v=3","gravatar_id":"","url":"https://api.github.com/users/greglittlefield-wf","html_url":"https://github.com/greglittlefield-wf","followers_url":"https://api.github.com/users/greglittlefield-wf/followers","following_url":"https://api.github.com/users/greglittlefield-wf/following{/other_user}","gists_url":"https://api.github.com/users/greglittlefield-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/greglittlefield-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/greglittlefield-wf/subscriptions","organizations_url":"https://api.github.com/users/greglittlefield-wf/orgs","repos_url":"https://api.github.com/users/greglittlefield-wf/repos","events_url":"https://api.github.com/users/greglittlefield-wf/events{/privacy}","received_events_url":"https://api.github.com/users/greglittlefield-wf/received_events","type":"User","site_admin":false},"repo":{"id":32838055,"name":"react-dart","full_name":"greglittlefield-wf/react-dart","owner":{"login":"greglittlefield-wf","id":1713967,"avatar_url":"https://avatars.githubusercontent.com/u/1713967?v=3","gravatar_id":"","url":"https://api.github.com/users/greglittlefield-wf","html_url":"https://github.com/greglittlefield-wf","followers_url":"https://api.github.com/users/greglittlefield-wf/followers","following_url":"https://api.github.com/users/greglittlefield-wf/following{/other_user}","gists_url":"https://api.github.com/users/greglittlefield-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/greglittlefield-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/greglittlefield-wf/subscriptions","organizations_url":"https://api.github.com/users/greglittlefield-wf/orgs","repos_url":"https://api.github.com/users/greglittlefield-wf/repos","events_url":"https://api.github.com/users/greglittlefield-wf/events{/privacy}","received_events_url":"https://api.github.com/users/greglittlefield-wf/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/greglittlefield-wf/react-dart","description":"Bindings for React to Dart","fork":true,"url":"https://api.github.com/repos/greglittlefield-wf/react-dart","forks_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/forks","keys_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/teams","hooks_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/hooks","issue_events_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/issues/events{/number}","events_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/events","assignees_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/assignees{/user}","branches_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/branches{/branch}","tags_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/tags","blobs_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/git/refs{/sha}","trees_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/statuses/{sha}","languages_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/languages","stargazers_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/stargazers","contributors_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/contributors","subscribers_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/subscribers","subscription_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/subscription","commits_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/commits{/sha}","git_commits_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/git/commits{/sha}","comments_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/comments{/number}","issue_comment_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/issues/comments{/number}","contents_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/contents/{+path}","compare_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/merges","archive_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/downloads","issues_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/issues{/number}","pulls_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/pulls{/number}","milestones_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/milestones{/number}","notifications_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/labels{/name}","releases_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/releases{/id}","deployments_url":"https://api.github.com/repos/greglittlefield-wf/react-dart/deployments","created_at":"2015-03-25T02:34:54Z","updated_at":"2015-03-25T02:34:54Z","pushed_at":"2016-04-07T19:03:45Z","git_url":"git://github.com/greglittlefield-wf/react-dart.git","ssh_url":"git@github.com:greglittlefield-wf/react-dart.git","clone_url":"https://github.com/greglittlefield-wf/react-dart.git","svn_url":"https://github.com/greglittlefield-wf/react-dart","homepage":null,"size":1382,"stargazers_count":0,"watchers_count":0,"language":"Dart","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"cleandart:master","ref":"master","sha":"b4b448aab6d42f874695cc8194b2022bc8638a4a","user":{"login":"cleandart","id":5911236,"avatar_url":"https://avatars.githubusercontent.com/u/5911236?v=3","gravatar_id":"","url":"https://api.github.com/users/cleandart","html_url":"https://github.com/cleandart","followers_url":"https://api.github.com/users/cleandart/followers","following_url":"https://api.github.com/users/cleandart/following{/other_user}","gists_url":"https://api.github.com/users/cleandart/gists{/gist_id}","starred_url":"https://api.github.com/users/cleandart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cleandart/subscriptions","organizations_url":"https://api.github.com/users/cleandart/orgs","repos_url":"https://api.github.com/users/cleandart/repos","events_url":"https://api.github.com/users/cleandart/events{/privacy}","received_events_url":"https://api.github.com/users/cleandart/received_events","type":"Organization","site_admin":false},"repo":{"id":13674420,"name":"react-dart","full_name":"cleandart/react-dart","owner":{"login":"cleandart","id":5911236,"avatar_url":"https://avatars.githubusercontent.com/u/5911236?v=3","gravatar_id":"","url":"https://api.github.com/users/cleandart","html_url":"https://github.com/cleandart","followers_url":"https://api.github.com/users/cleandart/followers","following_url":"https://api.github.com/users/cleandart/following{/other_user}","gists_url":"https://api.github.com/users/cleandart/gists{/gist_id}","starred_url":"https://api.github.com/users/cleandart/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cleandart/subscriptions","organizations_url":"https://api.github.com/users/cleandart/orgs","repos_url":"https://api.github.com/users/cleandart/repos","events_url":"https://api.github.com/users/cleandart/events{/privacy}","received_events_url":"https://api.github.com/users/cleandart/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/cleandart/react-dart","description":"Bindings for React to Dart","fork":false,"url":"https://api.github.com/repos/cleandart/react-dart","forks_url":"https://api.github.com/repos/cleandart/react-dart/forks","keys_url":"https://api.github.com/repos/cleandart/react-dart/keys{/key_id}","collaborators_url":"https://api.github.com/repos/cleandart/react-dart/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/cleandart/react-dart/teams","hooks_url":"https://api.github.com/repos/cleandart/react-dart/hooks","issue_events_url":"https://api.github.com/repos/cleandart/react-dart/issues/events{/number}","events_url":"https://api.github.com/repos/cleandart/react-dart/events","assignees_url":"https://api.github.com/repos/cleandart/react-dart/assignees{/user}","branches_url":"https://api.github.com/repos/cleandart/react-dart/branches{/branch}","tags_url":"https://api.github.com/repos/cleandart/react-dart/tags","blobs_url":"https://api.github.com/repos/cleandart/react-dart/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/cleandart/react-dart/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/cleandart/react-dart/git/refs{/sha}","trees_url":"https://api.github.com/repos/cleandart/react-dart/git/trees{/sha}","statuses_url":"https://api.github.com/repos/cleandart/react-dart/statuses/{sha}","languages_url":"https://api.github.com/repos/cleandart/react-dart/languages","stargazers_url":"https://api.github.com/repos/cleandart/react-dart/stargazers","contributors_url":"https://api.github.com/repos/cleandart/react-dart/contributors","subscribers_url":"https://api.github.com/repos/cleandart/react-dart/subscribers","subscription_url":"https://api.github.com/repos/cleandart/react-dart/subscription","commits_url":"https://api.github.com/repos/cleandart/react-dart/commits{/sha}","git_commits_url":"https://api.github.com/repos/cleandart/react-dart/git/commits{/sha}","comments_url":"https://api.github.com/repos/cleandart/react-dart/comments{/number}","issue_comment_url":"https://api.github.com/repos/cleandart/react-dart/issues/comments{/number}","contents_url":"https://api.github.com/repos/cleandart/react-dart/contents/{+path}","compare_url":"https://api.github.com/repos/cleandart/react-dart/compare/{base}...{head}","merges_url":"https://api.github.com/repos/cleandart/react-dart/merges","archive_url":"https://api.github.com/repos/cleandart/react-dart/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/cleandart/react-dart/downloads","issues_url":"https://api.github.com/repos/cleandart/react-dart/issues{/number}","pulls_url":"https://api.github.com/repos/cleandart/react-dart/pulls{/number}","milestones_url":"https://api.github.com/repos/cleandart/react-dart/milestones{/number}","notifications_url":"https://api.github.com/repos/cleandart/react-dart/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/cleandart/react-dart/labels{/name}","releases_url":"https://api.github.com/repos/cleandart/react-dart/releases{/id}","deployments_url":"https://api.github.com/repos/cleandart/react-dart/deployments","created_at":"2013-10-18T09:40:45Z","updated_at":"2016-04-05T15:29:06Z","pushed_at":"2016-04-07T19:07:28Z","git_url":"git://github.com/cleandart/react-dart.git","ssh_url":"git@github.com:cleandart/react-dart.git","clone_url":"https://github.com/cleandart/react-dart.git","svn_url":"https://github.com/cleandart/react-dart","homepage":null,"size":1003,"stargazers_count":112,"watchers_count":112,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":true,"forks_count":33,"mirror_url":null,"open_issues_count":10,"forks":33,"open_issues":10,"watchers":112,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/cleandart/react-dart/pulls/88"},"html":{"href":"https://github.com/cleandart/react-dart/pull/88"},"issue":{"href":"https://api.github.com/repos/cleandart/react-dart/issues/88"},"comments":{"href":"https://api.github.com/repos/cleandart/react-dart/issues/88/comments"},"review_comments":{"href":"https://api.github.com/repos/cleandart/react-dart/pulls/88/comments"},"review_comment":{"href":"https://api.github.com/repos/cleandart/react-dart/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/cleandart/react-dart/pulls/88/commits"},"statuses":{"href":"https://api.github.com/repos/cleandart/react-dart/statuses/3fb7430f994475c2f12d946534dca8169c703840"}},"merged":true,"mergeable":null,"mergeable_state":"unknown","merged_by":{"login":"trentgrover-wf","id":3778206,"avatar_url":"https://avatars.githubusercontent.com/u/3778206?v=3","gravatar_id":"","url":"https://api.github.com/users/trentgrover-wf","html_url":"https://github.com/trentgrover-wf","followers_url":"https://api.github.com/users/trentgrover-wf/followers","following_url":"https://api.github.com/users/trentgrover-wf/following{/other_user}","gists_url":"https://api.github.com/users/trentgrover-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/trentgrover-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/trentgrover-wf/subscriptions","organizations_url":"https://api.github.com/users/trentgrover-wf/orgs","repos_url":"https://api.github.com/users/trentgrover-wf/repos","events_url":"https://api.github.com/users/trentgrover-wf/events{/privacy}","received_events_url":"https://api.github.com/users/trentgrover-wf/received_events","type":"User","site_admin":false},"comments":9,"review_comments":28,"commits":24,"additions":1472,"deletions":718,"changed_files":17}}