From dea8f95e9f53b5a7d16a0b8e127ea760bd749216 Mon Sep 17 00:00:00 2001 From: Cristian Carlesso Date: Thu, 24 Aug 2017 12:28:41 +0100 Subject: [PATCH] remove infinite loop in instanceOf --- Source/Core/Core.js | 5 +++++ Specs/Core/Core.js | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/Source/Core/Core.js b/Source/Core/Core.js index c7bed355f..2ae9e4c9f 100644 --- a/Source/Core/Core.js +++ b/Source/Core/Core.js @@ -45,12 +45,17 @@ var typeOf = this.typeOf = function(item){ }; var instanceOf = this.instanceOf = function(item, object){ + var ctors = []; if (item == null) return false; var constructor = item.$constructor || item.constructor; while (constructor){ + if (ctors.contains(constructor)) break; + ctors.push(constructor); + if (constructor === object) return true; constructor = constructor.parent; } + ctors = null; /**/ if (!item.hasOwnProperty) return false; /**/ diff --git a/Specs/Core/Core.js b/Specs/Core/Core.js index 9e368c432..ecbb2106f 100644 --- a/Specs/Core/Core.js +++ b/Specs/Core/Core.js @@ -607,6 +607,38 @@ describe('instanceOf', function(){ expect(instanceOf(new X, Array)).to.equal(true); }); + it('should not go into infinite loop', function(){ + // self reference case + var Foo = function Foo(){ + var ctor = this.constructor; + ctor.parent = ctor; + }; + expect(instanceOf(new Foo(), Foo)).to.equal(true); + expect(instanceOf(new Foo(), String)).to.equal(false); + + // circular reference case + var A, B; + A = function(){this.init();}; + B = function(){this.init();}; + + A.prototype.init = function(){ + this.constructor = B; + }; + A.prototype.parent = B; + + B.prototype.init = function(){ + this.constructor = A; + }; + B.prototype.parent = A; + + expect(instanceOf(new A(), B)).to.equal(true); + expect(instanceOf(new A(), A)).to.equal(true); + expect(instanceOf(new B(), B)).to.equal(true); + expect(instanceOf(new B(), A)).to.equal(true); + + expect(instanceOf(new A(), String)).to.equal(false); + }); + // todo(ibolmo) var dit = typeof window != 'undefined' && window.Element && Element.set ? it : xit; dit('should return true for Element instances', function(){