{"action":"created","comment":{"url":"https://api.github.com/repos/1stdibs/serverVars/pulls/comments/38480722","id":38480722,"diff_hunk":"@@ -9,52 +9,74 @@\n \n var _ = require('underscore');\n var findNamespaceValue = require('find-namespace-value');\n+var realClientServerVars;\n+var clientServerVars;\n \n-var serverVarsFactory = function () {\n-    return Object.create({\n-        store: {},\n-        add: function (key, val) {\n-            if (typeof key === 'object') {\n-                _.extend(this.store, key);\n-            } else {\n-                this.store[key] = typeof val === 'object' ? _.clone(val) : val;\n-            }\n-        },\n-        get: function(key) {\n-            if (!key) {\n-                return _.clone(this.store);\n+var ServerVars = function () {\n+    this._svStack = [{}];\n+};\n+ServerVars.prototype = {\n+    add: function (key, val) {\n+        if (typeof key === 'object') {\n+            _.extend(this.getStore(), key);\n+        } else {\n+            this.getStore()[key] = typeof val === 'object' ? _.clone(val) : val;\n+        }\n+    },\n+    get: function(key) {\n+        var svValue;\n+        var i;\n+        if (!key) {\n+            return _.clone(_.extend.apply(_, [{}].concat(this._svStack)));\n+        }\n+        for(i=this._svStack.length - 1; i >= 0; --i) {\n+            if (svValue = findNamespaceValue(key, this._svStack[i])) {\n+                return svValue;\n             }\n-            return findNamespaceValue(key, this.store);\n-        },\n-        inject: function () {\n-            return '<script type=\"text/javascript\">' +\n-                'window.__SERVER_VARS__ = ' +\n-                    // safely embed JSON within HTML\n-                    // see http://stackoverflow.com/a/4180424/266795\n-                JSON.stringify(this.store)\n-                    .replace(/</g, '\\\\u003c')\n-                    .replace(/-->/g, '--\\\\>')\n-                    .replace(/\\u2028/g, '\\\\u2028')\n-                    .replace(/\\u2029/g, '\\\\u2029') +\n-                ';</script>';\n         }\n-    });\n+    },\n+    getStore: function () {\n+        return this._svStack[this._svStack.length - 1];\n+    },\n+    push: function () {\n+        return Array.prototype.push.apply(this._svStack, arguments);\n+    },\n+    pop: function () {\n+        return Array.prototype.pop.apply(this._svStack, arguments);\n+    },\n+    inject: function () {\n+        return '<script type=\"text/javascript\">' +\n+            'window.__SERVER_VARS__ = ' +\n+                // safely embed JSON within HTML\n+                // see http://stackoverflow.com/a/4180424/266795\n+            JSON.stringify(this.get())\n+                .replace(/</g, '\\\\u003c')\n+                .replace(/-->/g, '--\\\\>')\n+                .replace(/\\u2028/g, '\\\\u2028')\n+                .replace(/\\u2029/g, '\\\\u2029') +\n+            ';</script>';\n+    }\n };\n \n-var serverVars = serverVarsFactory();\n+var serverVars = new ServerVars();\n \n serverVars.middleware = function (req, res, next) {\n-    res.serverVars = res.locals.serverVars = serverVarsFactory();\n-    res.serverVars.add(_.clone(serverVars.store)); // get a copy of app-wide serverVars\n+    res.serverVars = res.locals.serverVars = new ServerVars();\n+    res.serverVars.add(_.clone(serverVars.get())); // get a copy of app-wide serverVars\n     next();\n };\n \n // on the client, this module exports the bootstrapped serverVars\n if (typeof window !== 'undefined' && window.__SERVER_VARS__) {\n-    serverVars = window.__SERVER_VARS__;\n-    serverVars.get = function (key) {\n-        return findNamespaceValue(key, serverVars);\n-    };\n+    realClientServerVars = new ServerVars();","path":"index.js","position":97,"original_position":97,"commit_id":"b6092fe07e5dc470867d5d7b5e0b9ac6ee889dbe","original_commit_id":"b6092fe07e5dc470867d5d7b5e0b9ac6ee889dbe","user":{"login":"twhid","id":299945,"avatar_url":"https://avatars.githubusercontent.com/u/299945?v=3","gravatar_id":"","url":"https://api.github.com/users/twhid","html_url":"https://github.com/twhid","followers_url":"https://api.github.com/users/twhid/followers","following_url":"https://api.github.com/users/twhid/following{/other_user}","gists_url":"https://api.github.com/users/twhid/gists{/gist_id}","starred_url":"https://api.github.com/users/twhid/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/twhid/subscriptions","organizations_url":"https://api.github.com/users/twhid/orgs","repos_url":"https://api.github.com/users/twhid/repos","events_url":"https://api.github.com/users/twhid/events{/privacy}","received_events_url":"https://api.github.com/users/twhid/received_events","type":"User","site_admin":false},"body":"That's always a danger with this module. If somebody sets properties on SV\non the client, then things could definitely go wrong.\n\nIf you need a instance of SV for your tests for some reason, then I refer\nyou to my previous comment.\n\nOn the client serverVars is only mutable because JS (and the way it's\ncurrently implemented). It should be immutable. Perhaps we should\nObject.freeze it where supported.\n","created_at":"2015-09-01T22:36:30Z","updated_at":"2015-09-01T22:36:30Z","html_url":"https://github.com/1stdibs/serverVars/pull/1#discussion_r38480722","pull_request_url":"https://api.github.com/repos/1stdibs/serverVars/pulls/1","_links":{"self":{"href":"https://api.github.com/repos/1stdibs/serverVars/pulls/comments/38480722"},"html":{"href":"https://github.com/1stdibs/serverVars/pull/1#discussion_r38480722"},"pull_request":{"href":"https://api.github.com/repos/1stdibs/serverVars/pulls/1"}}},"pull_request":{"url":"https://api.github.com/repos/1stdibs/serverVars/pulls/1","id":43466348,"html_url":"https://github.com/1stdibs/serverVars/pull/1","diff_url":"https://github.com/1stdibs/serverVars/pull/1.diff","patch_url":"https://github.com/1stdibs/serverVars/pull/1.patch","issue_url":"https://api.github.com/repos/1stdibs/serverVars/issues/1","number":1,"state":"open","locked":false,"title":"push and pop methods for serverVars. useful in beforeEach and afterEach during unit tests.","user":{"login":"antialias","id":447517,"avatar_url":"https://avatars.githubusercontent.com/u/447517?v=3","gravatar_id":"","url":"https://api.github.com/users/antialias","html_url":"https://github.com/antialias","followers_url":"https://api.github.com/users/antialias/followers","following_url":"https://api.github.com/users/antialias/following{/other_user}","gists_url":"https://api.github.com/users/antialias/gists{/gist_id}","starred_url":"https://api.github.com/users/antialias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antialias/subscriptions","organizations_url":"https://api.github.com/users/antialias/orgs","repos_url":"https://api.github.com/users/antialias/repos","events_url":"https://api.github.com/users/antialias/events{/privacy}","received_events_url":"https://api.github.com/users/antialias/received_events","type":"User","site_admin":false},"body":null,"created_at":"2015-08-27T00:03:38Z","updated_at":"2015-09-01T22:36:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"cda11f5ee9a92f9a4e0fca8269520526dc6712cc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/1stdibs/serverVars/pulls/1/commits","review_comments_url":"https://api.github.com/repos/1stdibs/serverVars/pulls/1/comments","review_comment_url":"https://api.github.com/repos/1stdibs/serverVars/pulls/comments{/number}","comments_url":"https://api.github.com/repos/1stdibs/serverVars/issues/1/comments","statuses_url":"https://api.github.com/repos/1stdibs/serverVars/statuses/b6092fe07e5dc470867d5d7b5e0b9ac6ee889dbe","head":{"label":"antialias:push-n-pop","ref":"push-n-pop","sha":"b6092fe07e5dc470867d5d7b5e0b9ac6ee889dbe","user":{"login":"antialias","id":447517,"avatar_url":"https://avatars.githubusercontent.com/u/447517?v=3","gravatar_id":"","url":"https://api.github.com/users/antialias","html_url":"https://github.com/antialias","followers_url":"https://api.github.com/users/antialias/followers","following_url":"https://api.github.com/users/antialias/following{/other_user}","gists_url":"https://api.github.com/users/antialias/gists{/gist_id}","starred_url":"https://api.github.com/users/antialias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antialias/subscriptions","organizations_url":"https://api.github.com/users/antialias/orgs","repos_url":"https://api.github.com/users/antialias/repos","events_url":"https://api.github.com/users/antialias/events{/privacy}","received_events_url":"https://api.github.com/users/antialias/received_events","type":"User","site_admin":false},"repo":{"id":41454977,"name":"serverVars","full_name":"antialias/serverVars","owner":{"login":"antialias","id":447517,"avatar_url":"https://avatars.githubusercontent.com/u/447517?v=3","gravatar_id":"","url":"https://api.github.com/users/antialias","html_url":"https://github.com/antialias","followers_url":"https://api.github.com/users/antialias/followers","following_url":"https://api.github.com/users/antialias/following{/other_user}","gists_url":"https://api.github.com/users/antialias/gists{/gist_id}","starred_url":"https://api.github.com/users/antialias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/antialias/subscriptions","organizations_url":"https://api.github.com/users/antialias/orgs","repos_url":"https://api.github.com/users/antialias/repos","events_url":"https://api.github.com/users/antialias/events{/privacy}","received_events_url":"https://api.github.com/users/antialias/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/antialias/serverVars","description":"","fork":true,"url":"https://api.github.com/repos/antialias/serverVars","forks_url":"https://api.github.com/repos/antialias/serverVars/forks","keys_url":"https://api.github.com/repos/antialias/serverVars/keys{/key_id}","collaborators_url":"https://api.github.com/repos/antialias/serverVars/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/antialias/serverVars/teams","hooks_url":"https://api.github.com/repos/antialias/serverVars/hooks","issue_events_url":"https://api.github.com/repos/antialias/serverVars/issues/events{/number}","events_url":"https://api.github.com/repos/antialias/serverVars/events","assignees_url":"https://api.github.com/repos/antialias/serverVars/assignees{/user}","branches_url":"https://api.github.com/repos/antialias/serverVars/branches{/branch}","tags_url":"https://api.github.com/repos/antialias/serverVars/tags","blobs_url":"https://api.github.com/repos/antialias/serverVars/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/antialias/serverVars/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/antialias/serverVars/git/refs{/sha}","trees_url":"https://api.github.com/repos/antialias/serverVars/git/trees{/sha}","statuses_url":"https://api.github.com/repos/antialias/serverVars/statuses/{sha}","languages_url":"https://api.github.com/repos/antialias/serverVars/languages","stargazers_url":"https://api.github.com/repos/antialias/serverVars/stargazers","contributors_url":"https://api.github.com/repos/antialias/serverVars/contributors","subscribers_url":"https://api.github.com/repos/antialias/serverVars/subscribers","subscription_url":"https://api.github.com/repos/antialias/serverVars/subscription","commits_url":"https://api.github.com/repos/antialias/serverVars/commits{/sha}","git_commits_url":"https://api.github.com/repos/antialias/serverVars/git/commits{/sha}","comments_url":"https://api.github.com/repos/antialias/serverVars/comments{/number}","issue_comment_url":"https://api.github.com/repos/antialias/serverVars/issues/comments{/number}","contents_url":"https://api.github.com/repos/antialias/serverVars/contents/{+path}","compare_url":"https://api.github.com/repos/antialias/serverVars/compare/{base}...{head}","merges_url":"https://api.github.com/repos/antialias/serverVars/merges","archive_url":"https://api.github.com/repos/antialias/serverVars/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/antialias/serverVars/downloads","issues_url":"https://api.github.com/repos/antialias/serverVars/issues{/number}","pulls_url":"https://api.github.com/repos/antialias/serverVars/pulls{/number}","milestones_url":"https://api.github.com/repos/antialias/serverVars/milestones{/number}","notifications_url":"https://api.github.com/repos/antialias/serverVars/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/antialias/serverVars/labels{/name}","releases_url":"https://api.github.com/repos/antialias/serverVars/releases{/id}","created_at":"2015-08-26T23:31:30Z","updated_at":"2015-08-26T23:31:30Z","pushed_at":"2015-08-27T00:03:13Z","git_url":"git://github.com/antialias/serverVars.git","ssh_url":"git@github.com:antialias/serverVars.git","clone_url":"https://github.com/antialias/serverVars.git","svn_url":"https://github.com/antialias/serverVars","homepage":null,"size":79,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","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":"1stdibs:master","ref":"master","sha":"175e92bbbd291be1fe9a06b6d3aa6d0e389027de","user":{"login":"1stdibs","id":1521176,"avatar_url":"https://avatars.githubusercontent.com/u/1521176?v=3","gravatar_id":"","url":"https://api.github.com/users/1stdibs","html_url":"https://github.com/1stdibs","followers_url":"https://api.github.com/users/1stdibs/followers","following_url":"https://api.github.com/users/1stdibs/following{/other_user}","gists_url":"https://api.github.com/users/1stdibs/gists{/gist_id}","starred_url":"https://api.github.com/users/1stdibs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/1stdibs/subscriptions","organizations_url":"https://api.github.com/users/1stdibs/orgs","repos_url":"https://api.github.com/users/1stdibs/repos","events_url":"https://api.github.com/users/1stdibs/events{/privacy}","received_events_url":"https://api.github.com/users/1stdibs/received_events","type":"Organization","site_admin":false},"repo":{"id":35247906,"name":"serverVars","full_name":"1stdibs/serverVars","owner":{"login":"1stdibs","id":1521176,"avatar_url":"https://avatars.githubusercontent.com/u/1521176?v=3","gravatar_id":"","url":"https://api.github.com/users/1stdibs","html_url":"https://github.com/1stdibs","followers_url":"https://api.github.com/users/1stdibs/followers","following_url":"https://api.github.com/users/1stdibs/following{/other_user}","gists_url":"https://api.github.com/users/1stdibs/gists{/gist_id}","starred_url":"https://api.github.com/users/1stdibs/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/1stdibs/subscriptions","organizations_url":"https://api.github.com/users/1stdibs/orgs","repos_url":"https://api.github.com/users/1stdibs/repos","events_url":"https://api.github.com/users/1stdibs/events{/privacy}","received_events_url":"https://api.github.com/users/1stdibs/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/1stdibs/serverVars","description":"","fork":false,"url":"https://api.github.com/repos/1stdibs/serverVars","forks_url":"https://api.github.com/repos/1stdibs/serverVars/forks","keys_url":"https://api.github.com/repos/1stdibs/serverVars/keys{/key_id}","collaborators_url":"https://api.github.com/repos/1stdibs/serverVars/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/1stdibs/serverVars/teams","hooks_url":"https://api.github.com/repos/1stdibs/serverVars/hooks","issue_events_url":"https://api.github.com/repos/1stdibs/serverVars/issues/events{/number}","events_url":"https://api.github.com/repos/1stdibs/serverVars/events","assignees_url":"https://api.github.com/repos/1stdibs/serverVars/assignees{/user}","branches_url":"https://api.github.com/repos/1stdibs/serverVars/branches{/branch}","tags_url":"https://api.github.com/repos/1stdibs/serverVars/tags","blobs_url":"https://api.github.com/repos/1stdibs/serverVars/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/1stdibs/serverVars/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/1stdibs/serverVars/git/refs{/sha}","trees_url":"https://api.github.com/repos/1stdibs/serverVars/git/trees{/sha}","statuses_url":"https://api.github.com/repos/1stdibs/serverVars/statuses/{sha}","languages_url":"https://api.github.com/repos/1stdibs/serverVars/languages","stargazers_url":"https://api.github.com/repos/1stdibs/serverVars/stargazers","contributors_url":"https://api.github.com/repos/1stdibs/serverVars/contributors","subscribers_url":"https://api.github.com/repos/1stdibs/serverVars/subscribers","subscription_url":"https://api.github.com/repos/1stdibs/serverVars/subscription","commits_url":"https://api.github.com/repos/1stdibs/serverVars/commits{/sha}","git_commits_url":"https://api.github.com/repos/1stdibs/serverVars/git/commits{/sha}","comments_url":"https://api.github.com/repos/1stdibs/serverVars/comments{/number}","issue_comment_url":"https://api.github.com/repos/1stdibs/serverVars/issues/comments{/number}","contents_url":"https://api.github.com/repos/1stdibs/serverVars/contents/{+path}","compare_url":"https://api.github.com/repos/1stdibs/serverVars/compare/{base}...{head}","merges_url":"https://api.github.com/repos/1stdibs/serverVars/merges","archive_url":"https://api.github.com/repos/1stdibs/serverVars/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/1stdibs/serverVars/downloads","issues_url":"https://api.github.com/repos/1stdibs/serverVars/issues{/number}","pulls_url":"https://api.github.com/repos/1stdibs/serverVars/pulls{/number}","milestones_url":"https://api.github.com/repos/1stdibs/serverVars/milestones{/number}","notifications_url":"https://api.github.com/repos/1stdibs/serverVars/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/1stdibs/serverVars/labels{/name}","releases_url":"https://api.github.com/repos/1stdibs/serverVars/releases{/id}","created_at":"2015-05-07T23:07:49Z","updated_at":"2015-05-07T23:47:21Z","pushed_at":"2015-08-27T00:03:38Z","git_url":"git://github.com/1stdibs/serverVars.git","ssh_url":"git@github.com:1stdibs/serverVars.git","clone_url":"https://github.com/1stdibs/serverVars.git","svn_url":"https://github.com/1stdibs/serverVars","homepage":null,"size":152,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":1,"forks":1,"open_issues":1,"watchers":0,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/1stdibs/serverVars/pulls/1"},"html":{"href":"https://github.com/1stdibs/serverVars/pull/1"},"issue":{"href":"https://api.github.com/repos/1stdibs/serverVars/issues/1"},"comments":{"href":"https://api.github.com/repos/1stdibs/serverVars/issues/1/comments"},"review_comments":{"href":"https://api.github.com/repos/1stdibs/serverVars/pulls/1/comments"},"review_comment":{"href":"https://api.github.com/repos/1stdibs/serverVars/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/1stdibs/serverVars/pulls/1/commits"},"statuses":{"href":"https://api.github.com/repos/1stdibs/serverVars/statuses/b6092fe07e5dc470867d5d7b5e0b9ac6ee889dbe"}}}}