{"action":"created","comment":{"url":"https://api.github.com/repos/scala-js/scala-js/pulls/comments/49863190","id":49863190,"diff_hunk":"@@ -0,0 +1,66 @@\n+/*                     __                                               *\\\n+**     ________ ___   / /  ___      __ ____  Scala.js tools             **\n+**    / __/ __// _ | / /  / _ | __ / // __/  (c) 2013-2014, LAMP/EPFL   **\n+**  __\\ \\/ /__/ __ |/ /__/ __ |/_// /_\\ \\    http://scala-js.org/       **\n+** /____/\\___/_/ |_/____/_/ | |__/ /____/                               **\n+**                          |/____/                                     **\n+\\*                                                                      */\n+\n+\n+package org.scalajs.core.tools.linker\n+\n+import org.scalajs.core.tools.logging.Logger\n+import org.scalajs.core.tools.io._\n+\n+import org.scalajs.core.tools.sem.Semantics\n+import org.scalajs.core.tools.javascript.OutputMode\n+import org.scalajs.core.tools.linker.analyzer.SymbolRequirement\n+import org.scalajs.core.tools.linker.frontend.LinkerFrontend\n+import org.scalajs.core.tools.linker.frontend.optimizer.IncOptimizer\n+import org.scalajs.core.tools.linker.backend.{LinkerBackend, BasicLinkerBackend}\n+\n+/** The Scala.js linker */\n+final class Linker(frontend: LinkerFrontend, backend: LinkerBackend)\n+    extends GenLinker {\n+\n+  require(!backend.withSourceMap || frontend.withSourceMap,\n+      \"Frontend must have source maps enabled if backend has them enabled\")\n+  require(frontend.semantics == backend.semantics,\n+      \"Frontend and backend must agree on semantics\")\n+  require(frontend.esLevel == backend.outputMode.esLevel,\n+      \"Frontend and backend must agree on ESLevel\")\n+\n+  val semantics: Semantics = frontend.semantics\n+  val outputMode: OutputMode = backend.outputMode\n+\n+  private[this] var _valid = true\n+\n+  def linkUnit(irFiles: Seq[VirtualScalaJSIRFile],\n+      symbolRequirements: SymbolRequirement, logger: Logger): LinkingUnit =\n+    guard(frontend.link(irFiles, symbolRequirements, logger))\n+\n+  def link(irFiles: Seq[VirtualScalaJSIRFile],\n+      output: WritableVirtualJSFile, logger: Logger): Unit = {\n+    guard {\n+      val unit = frontend.link(irFiles, backend.symbolRequirements, logger)\n+      backend.emit(unit, output, logger)\n+    }\n+  }\n+\n+  @inline\n+  private[this] def guard[T](body: => T): T = {\n+    if (!_valid) {\n+      throw new IllegalStateException(\n+          \"Linker is invalid due to a previous exception in a component\")\n+    }\n+\n+    try body\n+    catch {","path":"tools/shared/src/main/scala/org/scalajs/core/tools/linker/Linker.scala","position":58,"original_position":58,"commit_id":"443e86150914c735f3f9bfede3b7e70d507b1cda","original_commit_id":"443e86150914c735f3f9bfede3b7e70d507b1cda","user":{"login":"gzm0","id":1140323,"avatar_url":"https://avatars.githubusercontent.com/u/1140323?v=3","gravatar_id":"","url":"https://api.github.com/users/gzm0","html_url":"https://github.com/gzm0","followers_url":"https://api.github.com/users/gzm0/followers","following_url":"https://api.github.com/users/gzm0/following{/other_user}","gists_url":"https://api.github.com/users/gzm0/gists{/gist_id}","starred_url":"https://api.github.com/users/gzm0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gzm0/subscriptions","organizations_url":"https://api.github.com/users/gzm0/orgs","repos_url":"https://api.github.com/users/gzm0/repos","events_url":"https://api.github.com/users/gzm0/events{/privacy}","received_events_url":"https://api.github.com/users/gzm0/received_events","type":"User","site_admin":false},"body":"Done.","created_at":"2016-01-15T15:12:41Z","updated_at":"2016-01-15T15:12:41Z","html_url":"https://github.com/scala-js/scala-js/pull/2122#discussion_r49863190","pull_request_url":"https://api.github.com/repos/scala-js/scala-js/pulls/2122","_links":{"self":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/comments/49863190"},"html":{"href":"https://github.com/scala-js/scala-js/pull/2122#discussion_r49863190"},"pull_request":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2122"}}},"pull_request":{"url":"https://api.github.com/repos/scala-js/scala-js/pulls/2122","id":53996684,"html_url":"https://github.com/scala-js/scala-js/pull/2122","diff_url":"https://github.com/scala-js/scala-js/pull/2122.diff","patch_url":"https://github.com/scala-js/scala-js/pull/2122.patch","issue_url":"https://api.github.com/repos/scala-js/scala-js/issues/2122","number":2122,"state":"open","locked":false,"title":"Tools Refactoring","user":{"login":"gzm0","id":1140323,"avatar_url":"https://avatars.githubusercontent.com/u/1140323?v=3","gravatar_id":"","url":"https://api.github.com/users/gzm0","html_url":"https://github.com/gzm0","followers_url":"https://api.github.com/users/gzm0/followers","following_url":"https://api.github.com/users/gzm0/following{/other_user}","gists_url":"https://api.github.com/users/gzm0/gists{/gist_id}","starred_url":"https://api.github.com/users/gzm0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gzm0/subscriptions","organizations_url":"https://api.github.com/users/gzm0/orgs","repos_url":"https://api.github.com/users/gzm0/repos","events_url":"https://api.github.com/users/gzm0/events{/privacy}","received_events_url":"https://api.github.com/users/gzm0/received_events","type":"User","site_admin":false},"body":"This commit substantially refactors Scala.js' linker. Notably:\r\n\r\n# Linker pipeline\r\nThe linker pipeline is divided into a frontend and a backend.\r\n\r\nThe frontend links and optimizes IR files into a `LinkingUnit`. It paves the path for linker plugins in the future.\r\n\r\nThe backend emits a linking unit into a JavaScript file. Currently there are two backends:\r\n* BasicLinkerBackend (basic JavaScript generation, aka fastOptJS)\r\n* ClosureBackend (optimization pass with the Google Closure compiler, aka fullOptJS)\r\n\r\nAs a side effect of this change, Rhino now runs optimized code (unless this is explicitly disabled). This further has the side effect, that the `PreLinkStage` was entirely removed.\r\n\r\n# Classpath traversal\r\nClasspath traversal and abstraction is fully pushed to the build system. As a consequence, the whole `org.scalajs.core.tools.classpath` package is removed. Functionally is mostly replaced by a couple of lines of sbt code.\r\n\r\nThis also fixes #1635.\r\n\r\n# IR caching\r\nIn the past, each linker cached its own IR. This caused a lot of IR to be in memory multiple times. This commit replaces caching with a global IR cache. There are two main advantages:\r\n\r\n* IR for each class is only cached once in memory.\r\n* Linking other projects or configurations (e.g. compile v.s. test) can reuse the already cached IR.\r\n\r\n# JSEnvs\r\nSince classpaths have been removed, we need a way to re-enable lazy loading in Rhino. We therefore introduce the `LinkingUnitJSEnv` that can directly accept a `LinkingUnit`. Further, we enrich the `JSEnv`s with an API to load libraries. This allows for much nicer interfaces in a couple of spots, where you essentially just pass a `JSEnv` and then run your code in it, with all dependencies already present (e.g. FrameworkDetector).\r\n\r\nThere are a couple of advantages:\r\n- Symbol requirements are made explicit\r\n- No duplicate code for linking in RhinoJSEnv\r\n- Rhino can now run with optimized code","created_at":"2015-12-17T16:16:37Z","updated_at":"2016-01-15T15:12:41Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e2757a6028aaac6ef3174e9266b00857ef2f5648","assignee":{"login":"sjrd","id":535934,"avatar_url":"https://avatars.githubusercontent.com/u/535934?v=3","gravatar_id":"","url":"https://api.github.com/users/sjrd","html_url":"https://github.com/sjrd","followers_url":"https://api.github.com/users/sjrd/followers","following_url":"https://api.github.com/users/sjrd/following{/other_user}","gists_url":"https://api.github.com/users/sjrd/gists{/gist_id}","starred_url":"https://api.github.com/users/sjrd/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sjrd/subscriptions","organizations_url":"https://api.github.com/users/sjrd/orgs","repos_url":"https://api.github.com/users/sjrd/repos","events_url":"https://api.github.com/users/sjrd/events{/privacy}","received_events_url":"https://api.github.com/users/sjrd/received_events","type":"User","site_admin":false},"milestone":null,"commits_url":"https://api.github.com/repos/scala-js/scala-js/pulls/2122/commits","review_comments_url":"https://api.github.com/repos/scala-js/scala-js/pulls/2122/comments","review_comment_url":"https://api.github.com/repos/scala-js/scala-js/pulls/comments{/number}","comments_url":"https://api.github.com/repos/scala-js/scala-js/issues/2122/comments","statuses_url":"https://api.github.com/repos/scala-js/scala-js/statuses/443e86150914c735f3f9bfede3b7e70d507b1cda","head":{"label":"gzm0:refactor-tools","ref":"refactor-tools","sha":"443e86150914c735f3f9bfede3b7e70d507b1cda","user":{"login":"gzm0","id":1140323,"avatar_url":"https://avatars.githubusercontent.com/u/1140323?v=3","gravatar_id":"","url":"https://api.github.com/users/gzm0","html_url":"https://github.com/gzm0","followers_url":"https://api.github.com/users/gzm0/followers","following_url":"https://api.github.com/users/gzm0/following{/other_user}","gists_url":"https://api.github.com/users/gzm0/gists{/gist_id}","starred_url":"https://api.github.com/users/gzm0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gzm0/subscriptions","organizations_url":"https://api.github.com/users/gzm0/orgs","repos_url":"https://api.github.com/users/gzm0/repos","events_url":"https://api.github.com/users/gzm0/events{/privacy}","received_events_url":"https://api.github.com/users/gzm0/received_events","type":"User","site_admin":false},"repo":{"id":14925025,"name":"scala-js","full_name":"gzm0/scala-js","owner":{"login":"gzm0","id":1140323,"avatar_url":"https://avatars.githubusercontent.com/u/1140323?v=3","gravatar_id":"","url":"https://api.github.com/users/gzm0","html_url":"https://github.com/gzm0","followers_url":"https://api.github.com/users/gzm0/followers","following_url":"https://api.github.com/users/gzm0/following{/other_user}","gists_url":"https://api.github.com/users/gzm0/gists{/gist_id}","starred_url":"https://api.github.com/users/gzm0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gzm0/subscriptions","organizations_url":"https://api.github.com/users/gzm0/orgs","repos_url":"https://api.github.com/users/gzm0/repos","events_url":"https://api.github.com/users/gzm0/events{/privacy}","received_events_url":"https://api.github.com/users/gzm0/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/gzm0/scala-js","description":"Scala.js, a Scala to JavaScript compiler","fork":true,"url":"https://api.github.com/repos/gzm0/scala-js","forks_url":"https://api.github.com/repos/gzm0/scala-js/forks","keys_url":"https://api.github.com/repos/gzm0/scala-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/gzm0/scala-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/gzm0/scala-js/teams","hooks_url":"https://api.github.com/repos/gzm0/scala-js/hooks","issue_events_url":"https://api.github.com/repos/gzm0/scala-js/issues/events{/number}","events_url":"https://api.github.com/repos/gzm0/scala-js/events","assignees_url":"https://api.github.com/repos/gzm0/scala-js/assignees{/user}","branches_url":"https://api.github.com/repos/gzm0/scala-js/branches{/branch}","tags_url":"https://api.github.com/repos/gzm0/scala-js/tags","blobs_url":"https://api.github.com/repos/gzm0/scala-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/gzm0/scala-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/gzm0/scala-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/gzm0/scala-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/gzm0/scala-js/statuses/{sha}","languages_url":"https://api.github.com/repos/gzm0/scala-js/languages","stargazers_url":"https://api.github.com/repos/gzm0/scala-js/stargazers","contributors_url":"https://api.github.com/repos/gzm0/scala-js/contributors","subscribers_url":"https://api.github.com/repos/gzm0/scala-js/subscribers","subscription_url":"https://api.github.com/repos/gzm0/scala-js/subscription","commits_url":"https://api.github.com/repos/gzm0/scala-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/gzm0/scala-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/gzm0/scala-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/gzm0/scala-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/gzm0/scala-js/contents/{+path}","compare_url":"https://api.github.com/repos/gzm0/scala-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/gzm0/scala-js/merges","archive_url":"https://api.github.com/repos/gzm0/scala-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/gzm0/scala-js/downloads","issues_url":"https://api.github.com/repos/gzm0/scala-js/issues{/number}","pulls_url":"https://api.github.com/repos/gzm0/scala-js/pulls{/number}","milestones_url":"https://api.github.com/repos/gzm0/scala-js/milestones{/number}","notifications_url":"https://api.github.com/repos/gzm0/scala-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/gzm0/scala-js/labels{/name}","releases_url":"https://api.github.com/repos/gzm0/scala-js/releases{/id}","created_at":"2013-12-04T13:51:38Z","updated_at":"2015-05-01T16:01:20Z","pushed_at":"2016-01-15T12:47:43Z","git_url":"git://github.com/gzm0/scala-js.git","ssh_url":"git@github.com:gzm0/scala-js.git","clone_url":"https://github.com/gzm0/scala-js.git","svn_url":"https://github.com/gzm0/scala-js","homepage":"http://www.scala-js.org/","size":10990,"stargazers_count":0,"watchers_count":0,"language":"Scala","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":2,"mirror_url":null,"open_issues_count":0,"forks":2,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"scala-js:master","ref":"master","sha":"007eb46f905c2e2f522ca86f4a1d535a0746a915","user":{"login":"scala-js","id":6039724,"avatar_url":"https://avatars.githubusercontent.com/u/6039724?v=3","gravatar_id":"","url":"https://api.github.com/users/scala-js","html_url":"https://github.com/scala-js","followers_url":"https://api.github.com/users/scala-js/followers","following_url":"https://api.github.com/users/scala-js/following{/other_user}","gists_url":"https://api.github.com/users/scala-js/gists{/gist_id}","starred_url":"https://api.github.com/users/scala-js/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scala-js/subscriptions","organizations_url":"https://api.github.com/users/scala-js/orgs","repos_url":"https://api.github.com/users/scala-js/repos","events_url":"https://api.github.com/users/scala-js/events{/privacy}","received_events_url":"https://api.github.com/users/scala-js/received_events","type":"Organization","site_admin":false},"repo":{"id":8272315,"name":"scala-js","full_name":"scala-js/scala-js","owner":{"login":"scala-js","id":6039724,"avatar_url":"https://avatars.githubusercontent.com/u/6039724?v=3","gravatar_id":"","url":"https://api.github.com/users/scala-js","html_url":"https://github.com/scala-js","followers_url":"https://api.github.com/users/scala-js/followers","following_url":"https://api.github.com/users/scala-js/following{/other_user}","gists_url":"https://api.github.com/users/scala-js/gists{/gist_id}","starred_url":"https://api.github.com/users/scala-js/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/scala-js/subscriptions","organizations_url":"https://api.github.com/users/scala-js/orgs","repos_url":"https://api.github.com/users/scala-js/repos","events_url":"https://api.github.com/users/scala-js/events{/privacy}","received_events_url":"https://api.github.com/users/scala-js/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/scala-js/scala-js","description":"Scala.js, the Scala to JavaScript compiler","fork":false,"url":"https://api.github.com/repos/scala-js/scala-js","forks_url":"https://api.github.com/repos/scala-js/scala-js/forks","keys_url":"https://api.github.com/repos/scala-js/scala-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/scala-js/scala-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/scala-js/scala-js/teams","hooks_url":"https://api.github.com/repos/scala-js/scala-js/hooks","issue_events_url":"https://api.github.com/repos/scala-js/scala-js/issues/events{/number}","events_url":"https://api.github.com/repos/scala-js/scala-js/events","assignees_url":"https://api.github.com/repos/scala-js/scala-js/assignees{/user}","branches_url":"https://api.github.com/repos/scala-js/scala-js/branches{/branch}","tags_url":"https://api.github.com/repos/scala-js/scala-js/tags","blobs_url":"https://api.github.com/repos/scala-js/scala-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/scala-js/scala-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/scala-js/scala-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/scala-js/scala-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/scala-js/scala-js/statuses/{sha}","languages_url":"https://api.github.com/repos/scala-js/scala-js/languages","stargazers_url":"https://api.github.com/repos/scala-js/scala-js/stargazers","contributors_url":"https://api.github.com/repos/scala-js/scala-js/contributors","subscribers_url":"https://api.github.com/repos/scala-js/scala-js/subscribers","subscription_url":"https://api.github.com/repos/scala-js/scala-js/subscription","commits_url":"https://api.github.com/repos/scala-js/scala-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/scala-js/scala-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/scala-js/scala-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/scala-js/scala-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/scala-js/scala-js/contents/{+path}","compare_url":"https://api.github.com/repos/scala-js/scala-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/scala-js/scala-js/merges","archive_url":"https://api.github.com/repos/scala-js/scala-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/scala-js/scala-js/downloads","issues_url":"https://api.github.com/repos/scala-js/scala-js/issues{/number}","pulls_url":"https://api.github.com/repos/scala-js/scala-js/pulls{/number}","milestones_url":"https://api.github.com/repos/scala-js/scala-js/milestones{/number}","notifications_url":"https://api.github.com/repos/scala-js/scala-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/scala-js/scala-js/labels{/name}","releases_url":"https://api.github.com/repos/scala-js/scala-js/releases{/id}","created_at":"2013-02-18T16:33:55Z","updated_at":"2016-01-15T08:39:58Z","pushed_at":"2016-01-15T12:47:43Z","git_url":"git://github.com/scala-js/scala-js.git","ssh_url":"git@github.com:scala-js/scala-js.git","clone_url":"https://github.com/scala-js/scala-js.git","svn_url":"https://github.com/scala-js/scala-js","homepage":"http://www.scala-js.org/","size":12393,"stargazers_count":2074,"watchers_count":2074,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":189,"mirror_url":null,"open_issues_count":91,"forks":189,"open_issues":91,"watchers":2074,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2122"},"html":{"href":"https://github.com/scala-js/scala-js/pull/2122"},"issue":{"href":"https://api.github.com/repos/scala-js/scala-js/issues/2122"},"comments":{"href":"https://api.github.com/repos/scala-js/scala-js/issues/2122/comments"},"review_comments":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2122/comments"},"review_comment":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2122/commits"},"statuses":{"href":"https://api.github.com/repos/scala-js/scala-js/statuses/443e86150914c735f3f9bfede3b7e70d507b1cda"}}}}