Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1eef631

Browse files
author
Matias Niemela
committed
revert: fix(ngMock): prevent memory leak due to data attached to $rootElement
This reverts commit 571e323.
1 parent 2ef92c3 commit 1eef631

File tree

4 files changed

+17
-148
lines changed

4 files changed

+17
-148
lines changed

src/jqLite.js

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,6 @@ function jqLiteHasData(node) {
196196
return false;
197197
}
198198

199-
function jqLiteCleanData(nodes) {
200-
for (var i = 0, ii = nodes.length; i < ii; i++) {
201-
jqLiteRemoveData(nodes[i]);
202-
}
203-
}
204-
205199
function jqLiteBuildFragment(html, context) {
206200
var tmp, tag, wrap,
207201
fragment = context.createDocumentFragment(),
@@ -600,8 +594,7 @@ function getAliasedAttrName(name) {
600594
forEach({
601595
data: jqLiteData,
602596
removeData: jqLiteRemoveData,
603-
hasData: jqLiteHasData,
604-
cleanData: jqLiteCleanData
597+
hasData: jqLiteHasData
605598
}, function(fn, name) {
606599
JQLite[name] = fn;
607600
});

src/ngMock/angular-mocks.js

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -127,12 +127,12 @@ angular.mock.$Browser = function() {
127127
};
128128
angular.mock.$Browser.prototype = {
129129

130-
/**
131-
* @name $browser#poll
132-
*
133-
* @description
134-
* run all fns in pollFns
135-
*/
130+
/**
131+
* @name $browser#poll
132+
*
133+
* @description
134+
* run all fns in pollFns
135+
*/
136136
poll: function poll() {
137137
angular.forEach(this.pollFns, function(pollFn) {
138138
pollFn();
@@ -1879,12 +1879,10 @@ angular.mock.$RAFDecorator = ['$delegate', function($delegate) {
18791879
/**
18801880
*
18811881
*/
1882-
var originalRootElement;
18831882
angular.mock.$RootElementProvider = function() {
1884-
this.$get = ['$injector', function($injector) {
1885-
originalRootElement = angular.element('<div ng-app></div>').data('$injector', $injector);
1886-
return originalRootElement;
1887-
}];
1883+
this.$get = function() {
1884+
return angular.element('<div ng-app></div>');
1885+
};
18881886
};
18891887

18901888
/**
@@ -2298,7 +2296,6 @@ if (window.jasmine || window.mocha) {
22982296

22992297

23002298
(window.beforeEach || window.setup)(function() {
2301-
originalRootElement = null;
23022299
annotatedFunctions = [];
23032300
currentSpec = this;
23042301
});
@@ -2321,15 +2318,7 @@ if (window.jasmine || window.mocha) {
23212318
currentSpec = null;
23222319

23232320
if (injector) {
2324-
// Ensure `$rootElement` is instantiated, before checking `originalRootElement`
2325-
var $rootElement = injector.get('$rootElement');
2326-
var rootNode = $rootElement && $rootElement[0];
2327-
var cleanUpNodes = !originalRootElement ? [] : [originalRootElement[0]];
2328-
if (rootNode && (!originalRootElement || rootNode !== originalRootElement[0])) {
2329-
cleanUpNodes.push(rootNode);
2330-
}
2331-
angular.element.cleanData(cleanUpNodes);
2332-
2321+
injector.get('$rootElement').off();
23332322
}
23342323

23352324
// clean up jquery's fragment cache

test/helpers/testabilityPatch.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,12 @@ function dealoc(obj) {
117117
}
118118

119119
function cleanup(element) {
120-
angular.element.cleanData(element);
121-
120+
element.off().removeData();
121+
if (window.jQuery) {
122+
// jQuery 2.x doesn't expose the cache storage; ensure all element data
123+
// is removed during its cleanup.
124+
jQuery.cleanData([element]);
125+
}
122126
// Note: We aren't using element.contents() here. Under jQuery, element.contents() can fail
123127
// for IFRAME elements. jQuery explicitly uses (element.contentDocument ||
124128
// element.contentWindow.document) and both properties are null for IFRAMES that aren't attached

test/ngMock/angular-mocksSpec.js

Lines changed: 0 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,10 +1596,6 @@ describe('ngMock', function() {
15961596
it('should create mock application root', inject(function($rootElement) {
15971597
expect($rootElement.text()).toEqual('');
15981598
}));
1599-
1600-
it('should attach the `$injector` to `$rootElement`', inject(function($injector, $rootElement) {
1601-
expect($rootElement.injector()).toBe($injector);
1602-
}));
16031599
});
16041600

16051601

@@ -2117,122 +2113,9 @@ describe('ngMockE2E', function() {
21172113
});
21182114
});
21192115

2120-
21212116
describe('make sure that we can create an injector outside of tests', function() {
21222117
//since some libraries create custom injectors outside of tests,
21232118
//we want to make sure that this is not breaking the internals of
21242119
//how we manage annotated function cleanup during tests. See #10967
21252120
angular.injector([function($injector) {}]);
21262121
});
2127-
2128-
2129-
describe('`afterEach` clean-up', function() {
2130-
describe('undecorated `$rootElement`', function() {
2131-
var prevRootElement;
2132-
var prevCleanDataSpy;
2133-
2134-
2135-
it('should set up spies so the next test can verify `$rootElement` was cleaned up', function() {
2136-
module(function($provide) {
2137-
$provide.decorator('$rootElement', function($delegate) {
2138-
prevRootElement = $delegate;
2139-
2140-
// Spy on `angular.element.cleanData()`, so the next test can verify
2141-
// that it has been called as necessary
2142-
prevCleanDataSpy = spyOn(angular.element, 'cleanData').andCallThrough();
2143-
2144-
return $delegate;
2145-
});
2146-
});
2147-
2148-
// Inject the `$rootElement` to ensure it has been created
2149-
inject(function($rootElement) {
2150-
expect($rootElement.injector()).toBeDefined();
2151-
});
2152-
});
2153-
2154-
2155-
it('should clean up `$rootElement` after each test', function() {
2156-
// One call is made by `testabilityPatch`'s `dealoc()`
2157-
// We want to verify the subsequent call, made by `angular-mocks`
2158-
expect(prevCleanDataSpy.callCount).toBe(2);
2159-
2160-
var cleanUpNodes = prevCleanDataSpy.calls[1].args[0];
2161-
expect(cleanUpNodes.length).toBe(1);
2162-
expect(cleanUpNodes[0]).toBe(prevRootElement[0]);
2163-
});
2164-
});
2165-
2166-
2167-
describe('decorated `$rootElement`', function() {
2168-
var prevOriginalRootElement;
2169-
var prevRootElement;
2170-
var prevCleanDataSpy;
2171-
2172-
2173-
it('should set up spies so the next text can verify `$rootElement` was cleaned up', function() {
2174-
module(function($provide) {
2175-
$provide.decorator('$rootElement', function($delegate) {
2176-
prevOriginalRootElement = $delegate;
2177-
2178-
// Mock `$rootElement` to be able to verify that the correct object is cleaned up
2179-
prevRootElement = angular.element('<div></div>');
2180-
2181-
// Spy on `angular.element.cleanData()`, so the next test can verify
2182-
// that it has been called as necessary
2183-
prevCleanDataSpy = spyOn(angular.element, 'cleanData').andCallThrough();
2184-
2185-
return prevRootElement;
2186-
});
2187-
});
2188-
2189-
// Inject the `$rootElement` to ensure it has been created
2190-
inject(function($rootElement) {
2191-
expect($rootElement).toBe(prevRootElement);
2192-
expect(prevOriginalRootElement.injector()).toBeDefined();
2193-
expect(prevRootElement.injector()).toBeUndefined();
2194-
2195-
// If we don't clean up `prevOriginalRootElement`-related data now, `testabilityPatch` will
2196-
// complain about a memory leak, because it doesn't clean up after the original
2197-
// `$rootElement`
2198-
// This is a false alarm, because `angular-mocks` would have cleaned up in a subsequent
2199-
// `afterEach` block
2200-
prevOriginalRootElement.removeData();
2201-
});
2202-
});
2203-
2204-
2205-
it('should clean up `$rootElement` (both original and decorated) after each test', function() {
2206-
// One call is made by `testabilityPatch`'s `dealoc()`
2207-
// We want to verify the subsequent call, made by `angular-mocks`
2208-
expect(prevCleanDataSpy.callCount).toBe(2);
2209-
2210-
var cleanUpNodes = prevCleanDataSpy.calls[1].args[0];
2211-
expect(cleanUpNodes.length).toBe(2);
2212-
expect(cleanUpNodes[0]).toBe(prevOriginalRootElement[0]);
2213-
expect(cleanUpNodes[1]).toBe(prevRootElement[0]);
2214-
});
2215-
});
2216-
2217-
2218-
describe('uninstantiated or falsy `$rootElement`', function() {
2219-
it('should not break if `$rootElement` was never instantiated', function() {
2220-
// Just an empty test to verify that `angular-mocks` doesn't break,
2221-
// when trying to clean up `$rootElement`, if `$rootElement` was never injected in the test
2222-
// (and thus never instantiated/created)
2223-
2224-
// Ensure the `$injector` is created - if there is no `$injector`, no clean-up takes places
2225-
inject(function() {});
2226-
});
2227-
2228-
2229-
it('should not break if the decorated `$rootElement` is falsy (e.g. `null`)', function() {
2230-
module(function($provide) {
2231-
$provide.value('$rootElement', null);
2232-
});
2233-
2234-
// Ensure the `$injector` is created - if there is no `$injector`, no clean-up takes places
2235-
inject(function() {});
2236-
});
2237-
});
2238-
});

0 commit comments

Comments
 (0)