{"action":"created","comment":{"url":"https://api.github.com/repos/scala-js/scala-js/pulls/comments/55512006","id":55512006,"diff_hunk":"@@ -0,0 +1,110 @@\n+package org.scalajs.testsuite.jsinterop\n+\n+import scala.annotation.tailrec\n+import scala.collection.immutable.TreeMap\n+import scala.scalajs.js\n+import scala.scalajs.js.annotation.ScalaJSDefined\n+\n+object TimeoutMock {\n+\n+  import js.Dynamic.global\n+\n+  private val realSetTimeout =\n+    global.setTimeout.asInstanceOf[js.Function]\n+\n+  private val realClearTimeout =\n+    global.clearTimeout.asInstanceOf[js.Function]\n+\n+  private val mockSetTimeout: js.Function =\n+    (fun: js.Function, delay: Int) => MockTimeouts.setTimeout(fun, delay)\n+\n+  private val mockClearTimeout: js.Function =\n+    (timeout: MockTimeout) => MockTimeouts.clearTimeout(timeout)\n+\n+  private var installed = false\n+\n+  @noinline\n+  def withMockedTimeout[A](body: (Int => Unit) => A): A = {\n+    install()\n+    try {\n+      body(MockTimeouts.tick)\n+    } finally {\n+      uninstall()\n+    }\n+  }\n+\n+  private def install(): Unit = {\n+    assert(!installed, \"Mock timeout already installed.\")\n+    global.setTimeout = mockSetTimeout\n+    global.clearTimeout = mockClearTimeout\n+    installed = true\n+  }\n+\n+  private def uninstall(): Unit = {\n+    assert(installed, \"Mock timeout is not installed.\")\n+    MockTimeouts.reinitialize()\n+    global.setTimeout = realSetTimeout\n+    global.clearTimeout = realClearTimeout\n+    installed = false\n+  }\n+\n+  private object MockTimeouts {\n+    private var timeouts: TreeMap[Int, List[MockTimeout]] = _\n+    private var currentTime: Int = _\n+    reinitialize()\n+\n+    def reinitialize(): Unit = {\n+      timeouts = TreeMap.empty\n+      currentTime = 0\n+    }\n+\n+    def setTimeout(fun: js.Function, delay: Int): MockTimeout = {\n+      val timeout = new MockTimeout(fun)\n+      assert(delay >= 0, \"Delay should be positive.\")\n+      val triggerTime = currentTime + delay\n+      assert(triggerTime >= 0, \"Time overflow\")\n+      timeouts = timeouts.updated(triggerTime,\n+        timeout :: timeouts.getOrElse(triggerTime, Nil))\n+      timeout\n+    }\n+\n+    def clearTimeout(timeout: MockTimeout): Unit = {\n+      timeout.clearTimeout()\n+    }\n+\n+    def tick(ms: Int): Unit = {\n+      assert(installed, \"`tick` should only be used inside withMockedTimeout { tick => ...}\")\n+      @tailrec\n+      def tickLoop(ms: Int): Unit = {\n+        assert(ms >= 0)\n+        val targetTime = currentTime + ms\n+        assert(targetTime >= 0)\n+        timeouts.headOption match {\n+          case Some((fTime, fTimeouts)) if fTime <= targetTime =>\n+            currentTime = fTime\n+            timeouts = timeouts.drop(1)","path":"test-suite/js/src/test/scala/org/scalajs/testsuite/jsinterop/TimeoutMock.scala","position":85,"original_position":85,"commit_id":"e75271107eb4f76f2a31a5da3336991e06ea666a","original_commit_id":"e75271107eb4f76f2a31a5da3336991e06ea666a","user":{"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},"body":"This doesn't look like a very efficient way to deal with a `TreeMap`.\r\n\r\nHave you considered the very simple implementation with a single `List[(Int, MockTiemout)]`:\r\n\r\nInsert is:\r\n```scala\r\nval (before, after) = timeouts.span(_._1 <= triggerTime)\r\ntimeouts = before ::: timeout :: after\r\n```\r\n`tick` is:\r\n```scala\r\nval (before, after) = timeouts.span(_._1 <= targetTime)\r\ntimeouts = after // Note: this *must* come first\r\nbefore.foreach(_.execute()))\r\n```","created_at":"2016-03-09T12:38:55Z","updated_at":"2016-03-09T12:38:55Z","html_url":"https://github.com/scala-js/scala-js/pull/2280#discussion_r55512006","pull_request_url":"https://api.github.com/repos/scala-js/scala-js/pulls/2280","_links":{"self":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/comments/55512006"},"html":{"href":"https://github.com/scala-js/scala-js/pull/2280#discussion_r55512006"},"pull_request":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2280"}}},"pull_request":{"url":"https://api.github.com/repos/scala-js/scala-js/pulls/2280","id":61925735,"html_url":"https://github.com/scala-js/scala-js/pull/2280","diff_url":"https://github.com/scala-js/scala-js/pull/2280.diff","patch_url":"https://github.com/scala-js/scala-js/pull/2280.patch","issue_url":"https://api.github.com/repos/scala-js/scala-js/issues/2280","number":2280,"state":"open","locked":false,"title":"Port testSuite jsinterop tests.","user":{"login":"nicolasstucki","id":3648029,"avatar_url":"https://avatars.githubusercontent.com/u/3648029?v=3","gravatar_id":"","url":"https://api.github.com/users/nicolasstucki","html_url":"https://github.com/nicolasstucki","followers_url":"https://api.github.com/users/nicolasstucki/followers","following_url":"https://api.github.com/users/nicolasstucki/following{/other_user}","gists_url":"https://api.github.com/users/nicolasstucki/gists{/gist_id}","starred_url":"https://api.github.com/users/nicolasstucki/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicolasstucki/subscriptions","organizations_url":"https://api.github.com/users/nicolasstucki/orgs","repos_url":"https://api.github.com/users/nicolasstucki/repos","events_url":"https://api.github.com/users/nicolasstucki/events{/privacy}","received_events_url":"https://api.github.com/users/nicolasstucki/received_events","type":"User","site_admin":false},"body":"","created_at":"2016-03-07T14:42:40Z","updated_at":"2016-03-09T12:38:55Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5e52e51f5e2bb0bf9268df4c942b5683a7058821","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/scala-js/scala-js/pulls/2280/commits","review_comments_url":"https://api.github.com/repos/scala-js/scala-js/pulls/2280/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/2280/comments","statuses_url":"https://api.github.com/repos/scala-js/scala-js/statuses/e75271107eb4f76f2a31a5da3336991e06ea666a","head":{"label":"nicolasstucki:port-testSuite-jsinterop","ref":"port-testSuite-jsinterop","sha":"e75271107eb4f76f2a31a5da3336991e06ea666a","user":{"login":"nicolasstucki","id":3648029,"avatar_url":"https://avatars.githubusercontent.com/u/3648029?v=3","gravatar_id":"","url":"https://api.github.com/users/nicolasstucki","html_url":"https://github.com/nicolasstucki","followers_url":"https://api.github.com/users/nicolasstucki/followers","following_url":"https://api.github.com/users/nicolasstucki/following{/other_user}","gists_url":"https://api.github.com/users/nicolasstucki/gists{/gist_id}","starred_url":"https://api.github.com/users/nicolasstucki/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicolasstucki/subscriptions","organizations_url":"https://api.github.com/users/nicolasstucki/orgs","repos_url":"https://api.github.com/users/nicolasstucki/repos","events_url":"https://api.github.com/users/nicolasstucki/events{/privacy}","received_events_url":"https://api.github.com/users/nicolasstucki/received_events","type":"User","site_admin":false},"repo":{"id":35167756,"name":"scala-js","full_name":"nicolasstucki/scala-js","owner":{"login":"nicolasstucki","id":3648029,"avatar_url":"https://avatars.githubusercontent.com/u/3648029?v=3","gravatar_id":"","url":"https://api.github.com/users/nicolasstucki","html_url":"https://github.com/nicolasstucki","followers_url":"https://api.github.com/users/nicolasstucki/followers","following_url":"https://api.github.com/users/nicolasstucki/following{/other_user}","gists_url":"https://api.github.com/users/nicolasstucki/gists{/gist_id}","starred_url":"https://api.github.com/users/nicolasstucki/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/nicolasstucki/subscriptions","organizations_url":"https://api.github.com/users/nicolasstucki/orgs","repos_url":"https://api.github.com/users/nicolasstucki/repos","events_url":"https://api.github.com/users/nicolasstucki/events{/privacy}","received_events_url":"https://api.github.com/users/nicolasstucki/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/nicolasstucki/scala-js","description":"Scala.js, the Scala to JavaScript compiler","fork":true,"url":"https://api.github.com/repos/nicolasstucki/scala-js","forks_url":"https://api.github.com/repos/nicolasstucki/scala-js/forks","keys_url":"https://api.github.com/repos/nicolasstucki/scala-js/keys{/key_id}","collaborators_url":"https://api.github.com/repos/nicolasstucki/scala-js/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/nicolasstucki/scala-js/teams","hooks_url":"https://api.github.com/repos/nicolasstucki/scala-js/hooks","issue_events_url":"https://api.github.com/repos/nicolasstucki/scala-js/issues/events{/number}","events_url":"https://api.github.com/repos/nicolasstucki/scala-js/events","assignees_url":"https://api.github.com/repos/nicolasstucki/scala-js/assignees{/user}","branches_url":"https://api.github.com/repos/nicolasstucki/scala-js/branches{/branch}","tags_url":"https://api.github.com/repos/nicolasstucki/scala-js/tags","blobs_url":"https://api.github.com/repos/nicolasstucki/scala-js/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/nicolasstucki/scala-js/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/nicolasstucki/scala-js/git/refs{/sha}","trees_url":"https://api.github.com/repos/nicolasstucki/scala-js/git/trees{/sha}","statuses_url":"https://api.github.com/repos/nicolasstucki/scala-js/statuses/{sha}","languages_url":"https://api.github.com/repos/nicolasstucki/scala-js/languages","stargazers_url":"https://api.github.com/repos/nicolasstucki/scala-js/stargazers","contributors_url":"https://api.github.com/repos/nicolasstucki/scala-js/contributors","subscribers_url":"https://api.github.com/repos/nicolasstucki/scala-js/subscribers","subscription_url":"https://api.github.com/repos/nicolasstucki/scala-js/subscription","commits_url":"https://api.github.com/repos/nicolasstucki/scala-js/commits{/sha}","git_commits_url":"https://api.github.com/repos/nicolasstucki/scala-js/git/commits{/sha}","comments_url":"https://api.github.com/repos/nicolasstucki/scala-js/comments{/number}","issue_comment_url":"https://api.github.com/repos/nicolasstucki/scala-js/issues/comments{/number}","contents_url":"https://api.github.com/repos/nicolasstucki/scala-js/contents/{+path}","compare_url":"https://api.github.com/repos/nicolasstucki/scala-js/compare/{base}...{head}","merges_url":"https://api.github.com/repos/nicolasstucki/scala-js/merges","archive_url":"https://api.github.com/repos/nicolasstucki/scala-js/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/nicolasstucki/scala-js/downloads","issues_url":"https://api.github.com/repos/nicolasstucki/scala-js/issues{/number}","pulls_url":"https://api.github.com/repos/nicolasstucki/scala-js/pulls{/number}","milestones_url":"https://api.github.com/repos/nicolasstucki/scala-js/milestones{/number}","notifications_url":"https://api.github.com/repos/nicolasstucki/scala-js/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/nicolasstucki/scala-js/labels{/name}","releases_url":"https://api.github.com/repos/nicolasstucki/scala-js/releases{/id}","deployments_url":"https://api.github.com/repos/nicolasstucki/scala-js/deployments","created_at":"2015-05-06T15:41:56Z","updated_at":"2016-01-11T15:38:56Z","pushed_at":"2016-03-09T11:57:20Z","git_url":"git://github.com/nicolasstucki/scala-js.git","ssh_url":"git@github.com:nicolasstucki/scala-js.git","clone_url":"https://github.com/nicolasstucki/scala-js.git","svn_url":"https://github.com/nicolasstucki/scala-js","homepage":"http://www.scala-js.org/","size":11455,"stargazers_count":0,"watchers_count":0,"language":"Scala","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":"scala-js:master","ref":"master","sha":"f82f5cc34c66c15a7f14578ace4e53e5a034202d","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}","deployments_url":"https://api.github.com/repos/scala-js/scala-js/deployments","created_at":"2013-02-18T16:33:55Z","updated_at":"2016-03-08T22:38:06Z","pushed_at":"2016-03-09T11:58:07Z","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":14297,"stargazers_count":2189,"watchers_count":2189,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":192,"mirror_url":null,"open_issues_count":91,"forks":192,"open_issues":91,"watchers":2189,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2280"},"html":{"href":"https://github.com/scala-js/scala-js/pull/2280"},"issue":{"href":"https://api.github.com/repos/scala-js/scala-js/issues/2280"},"comments":{"href":"https://api.github.com/repos/scala-js/scala-js/issues/2280/comments"},"review_comments":{"href":"https://api.github.com/repos/scala-js/scala-js/pulls/2280/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/2280/commits"},"statuses":{"href":"https://api.github.com/repos/scala-js/scala-js/statuses/e75271107eb4f76f2a31a5da3336991e06ea666a"}}}}