{"action":"created","comment":{"url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/comments/34047986","id":34047986,"diff_hunk":"@@ -1,361 +1,726 @@\n-/* global Promise,\n-      EventDispatcher\n-*/\n-\n-/* exported Navigation */\n+/*global\n+  Utils\n+ */\n+(function(exports) {\n \n 'use strict';\n \n-(function(window) {\n+/**\n+ * The Defer type is useful when creating promises.\n+ * @typedef {Object} Defer\n+ * @property {function(*)} resolve The Promise's resolve function.\n+ * @property {function(*)} reject The Promise's reject function.\n+ * @property {Promise} promise The actual promise.\n+ */\n+\n+/**\n+ * @function\n+ * The debug function translates to console.log in debug mode.\n+ *\n+ * @param {...*} args The values to be displayed to the console.\n+ */\n+const debug = 1 ? (...args) => console.log(...args) : () => {};\n+\n+/**\n+  * This contains an array of view characteristics, necessary to handle\n+  * navigation requests.\n+  * Each item has the following properties:\n+  * - name: this is the name of the view. This will be used also in the URL\n+  *   hash if the same HTML file holds several views.\n+  * - url: this is the URL used to match the current location and find the\n+  *   current view.\n+  * - view: this is the actual JavaScript object that manages this view.\n+  * - previous (optional): this is the name of the previous view; this is\n+  *   necessary to decide if we do a forward/backward animation.\n+  * - partOf (optional): this is used when a view is part of another view's\n+  *   HTML document. In that case one view is \"master\" and the other are only\n+  *   part of the master view.\n+  * - alsoContains (optional): this is the opposite and holds the view's\n+  *   subviews. (currently unused)\n+  *\n+  * NGA_VIEWS holds the configuration for NGA split views.\n+  */\n+const NGA_VIEWS = Object.freeze([\n+  Object.freeze({\n+    name: 'thread',\n+    url: 'views/conversation/index.html',\n+    view: 'ConversationView',\n+    previous: 'thread-list',\n+    alsoContains: ['report-view', 'composer', 'group-view']\n+  }),\n+  Object.freeze({\n+    name: 'thread-list',\n+    url: 'views/inbox/index.html',\n+    view: 'InboxView'\n+  }),\n+  Object.freeze({\n+    name: 'report-view',\n+    view: 'ReportView',\n+    previous: 'thread',\n+    partOf: 'thread'\n+  }),\n+  Object.freeze({\n+    name: 'composer',\n+    view: 'ConversationView',\n+    previous: 'thread-list',\n+    partOf: 'thread'\n+  }),\n+  Object.freeze({\n+    name: 'group-view',\n+    view: 'GroupView',\n+    previous: 'thread',\n+    partOf: 'thread'\n+  })\n+]);\n+\n+/**\n+  * OA_VIEWS holds the configuration for the old non-split architecture.\n+  */\n+const OA_VIEWS = Object.freeze([\n+  Object.freeze({\n+    name: 'thread-list',\n+    url: 'index.html',\n+    view: 'InboxView',\n+    alsoContains: ['thread', 'composer', 'group-view', 'report-view']\n+  }),\n+  Object.freeze({\n+    name: 'thread',\n+    view: 'ConversationView',\n+    previous: 'thread-list',\n+    partOf: 'thread-list'\n+  }),\n+  Object.freeze({\n+    name: 'composer',\n+    view: 'ConversationView',\n+    previous: 'thread-list',\n+    partOf: 'thread-list'\n+  }),\n+  Object.freeze({\n+    name: 'group-view',\n+    view: 'GroupView',\n+    previous: 'thread',\n+    partOf: 'thread-list'\n+  }),\n+  Object.freeze({\n+    name: 'report-view',\n+    view: 'ReportView',\n+    previous: 'thread',\n+    partOf: 'thread-list'\n+  })\n+]);\n+\n+const VIEWS = isUsingOldArchitecture() ? OA_VIEWS : NGA_VIEWS;\n+\n+var currentState;\n+var navigationTransition;\n+\n+/**\n+ * Navigate to this URL.\n+ *\n+ * @param {String} url URL to load.\n+ */\n+function setLocation(url) {\n+  window.location.assign(url);\n+}\n+\n+/**\n+ * We're using the old architecture if we're not in a split document.\n+ *\n+ * @returns {Boolean} true if we're using the old architecture.\n+ */\n+function isUsingOldArchitecture() {\n+  var pathname = window.location.pathname;\n+  return (pathname === '/' || pathname === '/index.html');\n+}\n+\n+/**\n+ * Tries to find a view name from a URL hash.\n+ * It takes the part of the hash between '/' or the start of the string, and '?'\n+ * or the end of the string. If the resulting string is the name of a view, it\n+ * then returns this view.\n+ *\n+ * @param {String} hash The string to analyze.\n+ * @returns {Object} The found panel, or null.\n+ */\n+function findViewFromHash(hash) {\n+  if (!hash) {\n+    return null;\n+  }\n+\n+  var index = hash.indexOf('/');\n+  if (index != -1) {\n+    hash = hash.slice(index + 1);\n+  }\n+\n+  index = hash.indexOf('?');\n+  if (index !== -1) {\n+    hash = hash.slice(0, index);\n+  }\n+\n+  return findViewFromName(hash);\n+}\n+\n+/**\n+ * Tries to find the correct view from the location.\n+ * First it tries to find the view using the location's hash; if\n+ * findViewFromHash returns something, then we check whether the found view is\n+ * indeed part of this document usinf the full URL.\n+ * If findViewFromHash returns nothing, we try to find a view from the full URL.\n+ *\n+ * @param {Location} location The content of window.location.\n+ * @returns {Object} The found view, or null.\n+ */\n+function findViewFromLocation(location) {\n+  var pathName = location.pathname;\n+  if (pathName.endsWith('/')) {\n+    pathName += 'index.html';\n+  }\n+\n+  var viewFromHash = findViewFromHash(location.hash);\n+  var viewFromPath = VIEWS.find(\n+    (object) => pathName.endsWith('/' + object.url)\n+  ) || null;\n+\n+  if (viewFromHash && viewFromHash.partOf &&\n+      viewFromHash.partOf !== viewFromPath.name) {\n+    console.error(\n+      'The view', viewFromHash.name,\n+      'found from the hash', location.hash,\n+      'is not part of view', viewFromPath.name\n+    );\n+    viewFromHash = null;\n+  }\n+\n+  return viewFromHash || viewFromPath;\n+}\n+\n+/**\n+ * Finds a view from its name.\n+ *\n+ * @param {String} name Name of the view to find.\n+ * @returns {Object} The found view, or null.\n+ */\n+function findViewFromName(name) {\n+  return VIEWS.find((object) => {\n+    return object.name === name;\n+  }) || null;\n+}\n+\n+/**\n+ * Sets up the state to handle the navigation.\n+ * Generally we're waiting for any ongoing transition to end before starting a\n+ * new one. However if the ongoing transition was started with opts.partial ==\n+ * true, we merely augment the ongoing transition with the new information,\n+ * especially arguments.\n+ *\n+ * @param {Object} opts options\n+ * @param {String} opts.newPanel The panel we'll switch to.\n+ * @param {Object} opts.args The arguments we'll use for the next panel.\n+ * @param {Boolean} [opts.partial] If present and true, this new navigation\n+ * request is a partial one missing information (eg arguments) and we'll call\n+ * startNavigation once again without this property once we'll know the missing\n+ * bits.\n+ *\n+ * @returns {Promise} Resolved when we could start the navigation (when an\n+ * previous ongoing one is finished).\n+ */\n+function startNavigation(opts) {\n+  var { newPanel, args, partial } = opts;\n+\n+  debug('startNavigation(', JSON.stringify(opts), ')');\n+  if (navigationTransition && !navigationTransition.partial) {\n+    debug('startNavigation: previous navigation exists, defering.');\n+    return navigationTransition.defer.promise.then(\n+      () => startNavigation(opts)\n+    );\n+  }\n+\n+  if (!navigationTransition) {\n+    var defer = Utils.Promise.defer();\n+\n+    navigationTransition = {\n+      stepsRun: [],\n+      defer\n+    };\n+  }\n+\n+  navigationTransition.partial = partial;\n+\n+  if (args && ('meta' in args)) {\n+    throw new Error('Arguments cannot have a `meta` property.');\n+  }\n+\n+  navigationTransition.transitionArgs = {\n+    meta: {\n+      next: newPanel ? {\n+        panel: newPanel.name,\n+        args\n+      } : null,\n+      prev: currentState ? {\n+        panel: currentState.panel.name,\n+        args: currentState.args\n+      } : null\n+    }\n+  };\n+\n+  Object.assign(navigationTransition.transitionArgs, args);\n+\n+  navigationTransition.states = {\n+    from: currentState,\n+    to: {\n+      panel: newPanel,\n+      args\n+    }\n+  };\n+\n+  return Promise.resolve();\n+}\n+\n+/**\n+ * Sets the currentState variable to its new value.\n+ */\n+function setFutureState() {\n+  currentState = navigationTransition.states.to;\n+}\n+\n+/**\n+ * Ends the navigation so that new navigations can take place.\n+ * This cleans up the navigation states.\n+ */\n+function endNavigation() {\n+  debug('endNavigation()');\n+  navigationTransition && navigationTransition.defer.resolve();\n+  navigationTransition = null;\n+}\n \n-// This function is used as a rejection handler, to swallow errors and log them\n-function catchError(e) {\n+/**\n+ * This function is used to catch errors at the end of navigation promise\n+ * chains. We're ending the navigation if this happens, so that we can start a\n+ * new one afterwards.\n+ *\n+ * @param {Exception} [e] The exception to display, if any.\n+ */\n+function onNavigationError(e) {\n+  console.error('Navigation error', e);\n+  endNavigation();\n+}\n+\n+/**\n+ * This function is used as a rejection handler, to swallow errors and log them.\n+ *\n+ * @param {Exception} [e] The exception to display, if any.\n+ */\n+function catchStepError(e) {\n   if (e) {\n     console.error(\n       'Navigation.toPanel: got an exception: (%s) %s',\n       e, e.stack && e.stack.replace(/\\n/g, '|')\n     );\n   } else {\n-    console.log('Navigation.toPanel: got a rejected promise');\n+    debug('Navigation.toPanel: got a rejected promise');\n   }\n }\n \n-var currentPanel;\n-var queuedPanel;\n+/**\n+ * Executes the lifecycle function for `stepName` on the right object.\n+ *\n+ * @param {String} stepName The step to execute: one of 'beforeLeave',\n+ * 'beforeEnter', 'afterLeave', 'afterEnter'.\n+ * @returns {Promise} Resolved when the step returns a value or a resolved\n+ * promise, rejected when the step either throws or returns a rejected promise.\n+ * Or a resolved promise if no step was executed (because it was already\n+ * executed or there was no function to execute).\n+ */\n+function executeNavigationStep(stepName) {\n+  debug(`executeNavigationStep(${stepName})`);\n+  if (!navigationTransition) {\n+    throw new Error(","path":"apps/sms/views/shared/js/navigation.js","position":348,"original_position":348,"commit_id":"adcf99d3ac32aff81d4411c6ad7c24454b9ec68d","original_commit_id":"adcf99d3ac32aff81d4411c6ad7c24454b9ec68d","user":{"login":"azasypkin","id":1713708,"avatar_url":"https://avatars.githubusercontent.com/u/1713708?v=3","gravatar_id":"","url":"https://api.github.com/users/azasypkin","html_url":"https://github.com/azasypkin","followers_url":"https://api.github.com/users/azasypkin/followers","following_url":"https://api.github.com/users/azasypkin/following{/other_user}","gists_url":"https://api.github.com/users/azasypkin/gists{/gist_id}","starred_url":"https://api.github.com/users/azasypkin/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/azasypkin/subscriptions","organizations_url":"https://api.github.com/users/azasypkin/orgs","repos_url":"https://api.github.com/users/azasypkin/repos","events_url":"https://api.github.com/users/azasypkin/events{/privacy}","received_events_url":"https://api.github.com/users/azasypkin/received_events","type":"User","site_admin":false},"body":"wondering if we should use ```Promise.reject``` here?","created_at":"2015-07-07T14:48:32Z","updated_at":"2015-07-07T14:48:32Z","html_url":"https://github.com/mozilla-b2g/gaia/pull/30630#discussion_r34047986","pull_request_url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630","_links":{"self":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/comments/34047986"},"html":{"href":"https://github.com/mozilla-b2g/gaia/pull/30630#discussion_r34047986"},"pull_request":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630"}}},"pull_request":{"url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630","id":37928931,"html_url":"https://github.com/mozilla-b2g/gaia/pull/30630","diff_url":"https://github.com/mozilla-b2g/gaia/pull/30630.diff","patch_url":"https://github.com/mozilla-b2g/gaia/pull/30630.patch","issue_url":"https://api.github.com/repos/mozilla-b2g/gaia/issues/30630","number":30630,"state":"open","locked":false,"title":"Bug 1162030 - [Messages][NG] Figure out how navigation works","user":{"login":"julienw","id":454175,"avatar_url":"https://avatars.githubusercontent.com/u/454175?v=3","gravatar_id":"","url":"https://api.github.com/users/julienw","html_url":"https://github.com/julienw","followers_url":"https://api.github.com/users/julienw/followers","following_url":"https://api.github.com/users/julienw/following{/other_user}","gists_url":"https://api.github.com/users/julienw/gists{/gist_id}","starred_url":"https://api.github.com/users/julienw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/julienw/subscriptions","organizations_url":"https://api.github.com/users/julienw/orgs","repos_url":"https://api.github.com/users/julienw/repos","events_url":"https://api.github.com/users/julienw/events{/privacy}","received_events_url":"https://api.github.com/users/julienw/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-06-17T17:59:28Z","updated_at":"2015-07-07T14:48:32Z","closed_at":null,"merged_at":null,"merge_commit_sha":"a6ab32e5590dc1aeefbe61fcec922916a8fe9454","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630/commits","review_comments_url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630/comments","review_comment_url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mozilla-b2g/gaia/issues/30630/comments","statuses_url":"https://api.github.com/repos/mozilla-b2g/gaia/statuses/adcf99d3ac32aff81d4411c6ad7c24454b9ec68d","head":{"label":"julienw:1162030-navigation-sms","ref":"1162030-navigation-sms","sha":"adcf99d3ac32aff81d4411c6ad7c24454b9ec68d","user":{"login":"julienw","id":454175,"avatar_url":"https://avatars.githubusercontent.com/u/454175?v=3","gravatar_id":"","url":"https://api.github.com/users/julienw","html_url":"https://github.com/julienw","followers_url":"https://api.github.com/users/julienw/followers","following_url":"https://api.github.com/users/julienw/following{/other_user}","gists_url":"https://api.github.com/users/julienw/gists{/gist_id}","starred_url":"https://api.github.com/users/julienw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/julienw/subscriptions","organizations_url":"https://api.github.com/users/julienw/orgs","repos_url":"https://api.github.com/users/julienw/repos","events_url":"https://api.github.com/users/julienw/events{/privacy}","received_events_url":"https://api.github.com/users/julienw/received_events","type":"User","site_admin":false},"repo":{"id":6565987,"name":"gaia","full_name":"julienw/gaia","owner":{"login":"julienw","id":454175,"avatar_url":"https://avatars.githubusercontent.com/u/454175?v=3","gravatar_id":"","url":"https://api.github.com/users/julienw","html_url":"https://github.com/julienw","followers_url":"https://api.github.com/users/julienw/followers","following_url":"https://api.github.com/users/julienw/following{/other_user}","gists_url":"https://api.github.com/users/julienw/gists{/gist_id}","starred_url":"https://api.github.com/users/julienw/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/julienw/subscriptions","organizations_url":"https://api.github.com/users/julienw/orgs","repos_url":"https://api.github.com/users/julienw/repos","events_url":"https://api.github.com/users/julienw/events{/privacy}","received_events_url":"https://api.github.com/users/julienw/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/julienw/gaia","description":"Gaia is a HTML5-based Phone UI for the Boot 2 Gecko Project","fork":true,"url":"https://api.github.com/repos/julienw/gaia","forks_url":"https://api.github.com/repos/julienw/gaia/forks","keys_url":"https://api.github.com/repos/julienw/gaia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/julienw/gaia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/julienw/gaia/teams","hooks_url":"https://api.github.com/repos/julienw/gaia/hooks","issue_events_url":"https://api.github.com/repos/julienw/gaia/issues/events{/number}","events_url":"https://api.github.com/repos/julienw/gaia/events","assignees_url":"https://api.github.com/repos/julienw/gaia/assignees{/user}","branches_url":"https://api.github.com/repos/julienw/gaia/branches{/branch}","tags_url":"https://api.github.com/repos/julienw/gaia/tags","blobs_url":"https://api.github.com/repos/julienw/gaia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/julienw/gaia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/julienw/gaia/git/refs{/sha}","trees_url":"https://api.github.com/repos/julienw/gaia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/julienw/gaia/statuses/{sha}","languages_url":"https://api.github.com/repos/julienw/gaia/languages","stargazers_url":"https://api.github.com/repos/julienw/gaia/stargazers","contributors_url":"https://api.github.com/repos/julienw/gaia/contributors","subscribers_url":"https://api.github.com/repos/julienw/gaia/subscribers","subscription_url":"https://api.github.com/repos/julienw/gaia/subscription","commits_url":"https://api.github.com/repos/julienw/gaia/commits{/sha}","git_commits_url":"https://api.github.com/repos/julienw/gaia/git/commits{/sha}","comments_url":"https://api.github.com/repos/julienw/gaia/comments{/number}","issue_comment_url":"https://api.github.com/repos/julienw/gaia/issues/comments{/number}","contents_url":"https://api.github.com/repos/julienw/gaia/contents/{+path}","compare_url":"https://api.github.com/repos/julienw/gaia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/julienw/gaia/merges","archive_url":"https://api.github.com/repos/julienw/gaia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/julienw/gaia/downloads","issues_url":"https://api.github.com/repos/julienw/gaia/issues{/number}","pulls_url":"https://api.github.com/repos/julienw/gaia/pulls{/number}","milestones_url":"https://api.github.com/repos/julienw/gaia/milestones{/number}","notifications_url":"https://api.github.com/repos/julienw/gaia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/julienw/gaia/labels{/name}","releases_url":"https://api.github.com/repos/julienw/gaia/releases{/id}","created_at":"2012-11-06T17:18:15Z","updated_at":"2014-06-25T07:25:16Z","pushed_at":"2015-07-06T14:28:23Z","git_url":"git://github.com/julienw/gaia.git","ssh_url":"git@github.com:julienw/gaia.git","clone_url":"https://github.com/julienw/gaia.git","svn_url":"https://github.com/julienw/gaia","homepage":"https://wiki.mozilla.org/B2G","size":937864,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"mozilla-b2g:master","ref":"master","sha":"55496e17a30f0bbd4f02d7cf1bdd64ca81701fb6","user":{"login":"mozilla-b2g","id":1261292,"avatar_url":"https://avatars.githubusercontent.com/u/1261292?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla-b2g","html_url":"https://github.com/mozilla-b2g","followers_url":"https://api.github.com/users/mozilla-b2g/followers","following_url":"https://api.github.com/users/mozilla-b2g/following{/other_user}","gists_url":"https://api.github.com/users/mozilla-b2g/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla-b2g/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla-b2g/subscriptions","organizations_url":"https://api.github.com/users/mozilla-b2g/orgs","repos_url":"https://api.github.com/users/mozilla-b2g/repos","events_url":"https://api.github.com/users/mozilla-b2g/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla-b2g/received_events","type":"Organization","site_admin":false},"repo":{"id":2317369,"name":"gaia","full_name":"mozilla-b2g/gaia","owner":{"login":"mozilla-b2g","id":1261292,"avatar_url":"https://avatars.githubusercontent.com/u/1261292?v=3","gravatar_id":"","url":"https://api.github.com/users/mozilla-b2g","html_url":"https://github.com/mozilla-b2g","followers_url":"https://api.github.com/users/mozilla-b2g/followers","following_url":"https://api.github.com/users/mozilla-b2g/following{/other_user}","gists_url":"https://api.github.com/users/mozilla-b2g/gists{/gist_id}","starred_url":"https://api.github.com/users/mozilla-b2g/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mozilla-b2g/subscriptions","organizations_url":"https://api.github.com/users/mozilla-b2g/orgs","repos_url":"https://api.github.com/users/mozilla-b2g/repos","events_url":"https://api.github.com/users/mozilla-b2g/events{/privacy}","received_events_url":"https://api.github.com/users/mozilla-b2g/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mozilla-b2g/gaia","description":"Gaia is a HTML5-based Phone UI for the Boot 2 Gecko Project. NOTE: For details of what branches are used for what releases, see","fork":false,"url":"https://api.github.com/repos/mozilla-b2g/gaia","forks_url":"https://api.github.com/repos/mozilla-b2g/gaia/forks","keys_url":"https://api.github.com/repos/mozilla-b2g/gaia/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mozilla-b2g/gaia/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mozilla-b2g/gaia/teams","hooks_url":"https://api.github.com/repos/mozilla-b2g/gaia/hooks","issue_events_url":"https://api.github.com/repos/mozilla-b2g/gaia/issues/events{/number}","events_url":"https://api.github.com/repos/mozilla-b2g/gaia/events","assignees_url":"https://api.github.com/repos/mozilla-b2g/gaia/assignees{/user}","branches_url":"https://api.github.com/repos/mozilla-b2g/gaia/branches{/branch}","tags_url":"https://api.github.com/repos/mozilla-b2g/gaia/tags","blobs_url":"https://api.github.com/repos/mozilla-b2g/gaia/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mozilla-b2g/gaia/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mozilla-b2g/gaia/git/refs{/sha}","trees_url":"https://api.github.com/repos/mozilla-b2g/gaia/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mozilla-b2g/gaia/statuses/{sha}","languages_url":"https://api.github.com/repos/mozilla-b2g/gaia/languages","stargazers_url":"https://api.github.com/repos/mozilla-b2g/gaia/stargazers","contributors_url":"https://api.github.com/repos/mozilla-b2g/gaia/contributors","subscribers_url":"https://api.github.com/repos/mozilla-b2g/gaia/subscribers","subscription_url":"https://api.github.com/repos/mozilla-b2g/gaia/subscription","commits_url":"https://api.github.com/repos/mozilla-b2g/gaia/commits{/sha}","git_commits_url":"https://api.github.com/repos/mozilla-b2g/gaia/git/commits{/sha}","comments_url":"https://api.github.com/repos/mozilla-b2g/gaia/comments{/number}","issue_comment_url":"https://api.github.com/repos/mozilla-b2g/gaia/issues/comments{/number}","contents_url":"https://api.github.com/repos/mozilla-b2g/gaia/contents/{+path}","compare_url":"https://api.github.com/repos/mozilla-b2g/gaia/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mozilla-b2g/gaia/merges","archive_url":"https://api.github.com/repos/mozilla-b2g/gaia/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mozilla-b2g/gaia/downloads","issues_url":"https://api.github.com/repos/mozilla-b2g/gaia/issues{/number}","pulls_url":"https://api.github.com/repos/mozilla-b2g/gaia/pulls{/number}","milestones_url":"https://api.github.com/repos/mozilla-b2g/gaia/milestones{/number}","notifications_url":"https://api.github.com/repos/mozilla-b2g/gaia/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mozilla-b2g/gaia/labels{/name}","releases_url":"https://api.github.com/repos/mozilla-b2g/gaia/releases{/id}","created_at":"2011-09-03T01:38:46Z","updated_at":"2015-07-05T22:37:46Z","pushed_at":"2015-07-07T14:39:12Z","git_url":"git://github.com/mozilla-b2g/gaia.git","ssh_url":"git@github.com:mozilla-b2g/gaia.git","clone_url":"https://github.com/mozilla-b2g/gaia.git","svn_url":"https://github.com/mozilla-b2g/gaia","homepage":"https://wiki.mozilla.org/B2G","size":1651324,"stargazers_count":1948,"watchers_count":1948,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":2370,"mirror_url":null,"open_issues_count":1056,"forks":2370,"open_issues":1056,"watchers":1948,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630"},"html":{"href":"https://github.com/mozilla-b2g/gaia/pull/30630"},"issue":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/issues/30630"},"comments":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/issues/30630/comments"},"review_comments":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630/comments"},"review_comment":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/pulls/30630/commits"},"statuses":{"href":"https://api.github.com/repos/mozilla-b2g/gaia/statuses/adcf99d3ac32aff81d4411c6ad7c24454b9ec68d"}}}}