Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Commit f43c226

Browse files
committed
fix(copy,equals): prevent browser crashes with Scope or Window
Scope and Window instances are special and when copied can crash browser. For this reason it makes sense to compare them only by identity.
1 parent 0e1fa2a commit f43c226

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

src/Angular.js

+9-2
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,12 @@ function isWindow(obj) {
413413
return obj && obj.document && obj.location && obj.alert && obj.setInterval;
414414
}
415415

416+
417+
function isScope(obj) {
418+
return obj && obj.$evalAsync && obj.$watch;
419+
}
420+
421+
416422
function isBoolean(value) {return typeof value == $boolean;}
417423
function isTextNode(node) {return nodeName_(node) == '#text';}
418424

@@ -580,6 +586,7 @@ function isLeafNode (node) {
580586
* @returns {*} The copy or updated `destination`, if `destination` was specified.
581587
*/
582588
function copy(source, destination){
589+
if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope");
583590
if (!destination) {
584591
destination = source;
585592
if (source) {
@@ -629,8 +636,7 @@ function copy(source, destination){
629636
* During a property comparision, properties of `function` type and properties with names
630637
* that begin with `$` are ignored.
631638
*
632-
* Note: This function is used to augment the Object type in Angular expressions. See
633-
* {@link angular.module.ng.$filter} for more information about Angular arrays.
639+
* Scope and DOMWindow objects are being compared only be identify (`===`).
634640
*
635641
* @param {*} o1 Object or value to compare.
636642
* @param {*} o2 Object or value to compare.
@@ -650,6 +656,7 @@ function equals(o1, o2) {
650656
return true;
651657
}
652658
} else {
659+
if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2)) return false;
653660
keySet = {};
654661
for(key in o1) {
655662
if (key.charAt(0) !== '$' && !isFunction(o1[key]) && !equals(o1[key], o2[key])) {

test/AngularSpec.js

+24
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ describe('angular', function() {
5757
expect(copy(123)).toEqual(123);
5858
expect(copy([{key:null}])).toEqual([{key:null}]);
5959
});
60+
61+
it('should throw an exception if a Scope is being copied', inject(function($rootScope) {
62+
expect(function() { copy($rootScope.$new()); }).toThrow("Can't copy Window or Scope");
63+
}));
64+
65+
it('should throw an exception if a Window is being copied', function() {
66+
expect(function() { copy(window); }).toThrow("Can't copy Window or Scope");
67+
});
6068
});
6169

6270
describe('equals', function() {
@@ -114,6 +122,22 @@ describe('angular', function() {
114122
it('should treat two NaNs as equal', function() {
115123
expect(equals(NaN, NaN)).toBe(true);
116124
});
125+
126+
it('should compare Scope instances only by identity', inject(function($rootScope) {
127+
var scope1 = $rootScope.$new(),
128+
scope2 = $rootScope.$new();
129+
130+
expect(equals(scope1, scope1)).toBe(true);
131+
expect(equals(scope1, scope2)).toBe(false);
132+
expect(equals($rootScope, scope1)).toBe(false);
133+
expect(equals(undefined, scope1)).toBe(false);
134+
}));
135+
136+
it('should compare Window instances only by identity', function() {
137+
expect(equals(window, window)).toBe(true);
138+
expect(equals(window, window.parent)).toBe(false);
139+
expect(equals(window, undefined)).toBe(false);
140+
});
117141
});
118142

119143
describe('size', function() {

0 commit comments

Comments
 (0)