From 71c11e96c64d5d4eb71f48c1eb778c2ba5c63377 Mon Sep 17 00:00:00 2001 From: Igor Minar Date: Thu, 3 Apr 2014 12:34:36 -0700 Subject: [PATCH] fix(Scope): revert the __proto__ cleanup as that could cause regressions When a async task interacts with a scope that has been destroyed already and if it interacts with a property that is prototypically inherited from some parent scope then resetting proto would make these inherited properties inaccessible and would result in NPEs --- src/ng/rootScope.js | 8 -------- test/ng/rootScopeSpec.js | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index 04bde3dda172..1c0f331f1557 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -757,14 +757,6 @@ function $RootScopeProvider(){ // prevent NPEs since these methods have references to properties we nulled out this.$destroy = this.$digest = this.$apply = noop; this.$on = this.$watch = function() { return noop; }; - - - /* jshint -W103 */ - // not all browsers have __proto__ so check first - if (this.__proto__) { - this.__proto__ = null; - } - /* jshint +W103 */ }, /** diff --git a/test/ng/rootScopeSpec.js b/test/ng/rootScopeSpec.js index 343b26851d24..01b5d1bdfdd4 100644 --- a/test/ng/rootScopeSpec.js +++ b/test/ng/rootScopeSpec.js @@ -898,6 +898,25 @@ describe('Scope', function() { var fn = child.$watch('somePath', function() {}); expect(fn).toBe(noop); })); + + + it("should preserve all (own and inherited) model properties on a destroyed scope", + inject(function($rootScope) { + // This test simulates an async task (xhr response) interacting with the scope after the scope + // was destroyed. Since we can't abort the request, we should ensure that the task doesn't + // throw NPEs because the scope was cleaned up during destruction. + + var parent = $rootScope.$new(), + child = parent.$new(); + + parent.parentModel = 'parent'; + child.childModel = 'child'; + + child.$destroy(); + + expect(child.parentModel).toBe('parent'); + expect(child.childModel).toBe('child'); + })); });