5ceb4feca3
It shipped in Chrome 47. Review URL: https://codereview.chromium.org/1519073004 Cr-Commit-Position: refs/heads/master@{#32816}
2217 lines
52 KiB
JavaScript
2217 lines
52 KiB
JavaScript
// Copyright 2014 the V8 project authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Flags: --allow-natives-syntax
|
|
// Flags: --harmony-destructuring-bind --harmony-sloppy
|
|
|
|
(function TestSuperNamedLoads() {
|
|
function Base() { }
|
|
function fBase() { }
|
|
Base.prototype = {
|
|
f() {
|
|
return "Base " + this.toString();
|
|
},
|
|
x: 15,
|
|
toString() {
|
|
return "this is Base";
|
|
}
|
|
};
|
|
|
|
function Derived() {
|
|
this.derivedDataProperty = "xxx";
|
|
}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
toString() { return "this is Derived"; },
|
|
x: 27,
|
|
f() {
|
|
assertEquals("Base this is Derived", super.f());
|
|
var a = super.x;
|
|
assertEquals(15, a);
|
|
assertEquals(15, super.x);
|
|
assertEquals(27, this.x);
|
|
return "Derived";
|
|
}
|
|
};
|
|
|
|
assertEquals("Base this is Base", new Base().f());
|
|
assertEquals("Derived", new Derived().f());
|
|
}());
|
|
|
|
|
|
(function TestSuperKeyedLoads() {
|
|
'use strict';
|
|
|
|
var x = 'x';
|
|
var derivedDataProperty = 'derivedDataProperty';
|
|
var f = 'f';
|
|
|
|
class Base {
|
|
f() {
|
|
return "Base " + this.toString();
|
|
}
|
|
toString() {
|
|
return "this is Base";
|
|
}
|
|
}
|
|
|
|
Base.prototype[x] = 15;
|
|
|
|
function Derived() {
|
|
this[derivedDataProperty] = "xxx";
|
|
}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
toString() { return "this is Derived"; },
|
|
x: 27,
|
|
f() {
|
|
assertEquals("Base this is Derived", super[f]());
|
|
var a = super[x];
|
|
assertEquals(15, a);
|
|
assertEquals(15, super[x]);
|
|
assertEquals(27, this[x]);
|
|
return "Derived";
|
|
}
|
|
};
|
|
|
|
assertEquals("Base this is Base", new Base().f());
|
|
assertEquals("Derived", new Derived().f());
|
|
}());
|
|
|
|
|
|
(function TestSuperKeywordNonMethod() {
|
|
'use strict';
|
|
|
|
class C {
|
|
f() {
|
|
super.unknown();
|
|
}
|
|
}
|
|
|
|
assertThrows(function() {
|
|
new C().f();
|
|
}, TypeError);
|
|
}());
|
|
|
|
|
|
(function TestGetter() {
|
|
function Base() {}
|
|
var derived;
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
assertSame(this, derived);
|
|
return this._x;
|
|
},
|
|
_x: 'base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 'derived',
|
|
testGetter() {
|
|
return super.x;
|
|
},
|
|
testGetterStrict() {
|
|
'use strict';
|
|
return super.x;
|
|
}
|
|
};
|
|
|
|
derived = new Derived();
|
|
assertEquals('derived', derived.testGetter());
|
|
derived = new Derived();
|
|
assertEquals('derived', derived.testGetterStrict());
|
|
}());
|
|
|
|
|
|
(function TestGetterKeyed() {
|
|
var x = 'x';
|
|
function Base() {}
|
|
var derived;
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
assertSame(this, derived);
|
|
return this._x;
|
|
},
|
|
_x: 'base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 'derived',
|
|
testGetter() {
|
|
return super[x];
|
|
},
|
|
testGetterStrict() {
|
|
'use strict';
|
|
return super[x];
|
|
},
|
|
testGetterWithToString() {
|
|
var toStringCalled;
|
|
var o = { toString: function() {
|
|
toStringCalled++;
|
|
return 'x';
|
|
} };
|
|
|
|
toStringCalled = 0;
|
|
assertEquals('derived', super[o]);
|
|
assertEquals(1, toStringCalled);
|
|
|
|
var eToThrow = new Error();
|
|
var oThrowsInToString = { toString: function() {
|
|
throw eToThrow;
|
|
} };
|
|
|
|
var ex = null;
|
|
try {
|
|
super[oThrowsInToString];
|
|
} catch(e) { ex = e }
|
|
assertEquals(eToThrow, ex);
|
|
|
|
var oReturnsNumericString = { toString: function() {
|
|
return "1";
|
|
} };
|
|
|
|
assertEquals(undefined, super[oReturnsNumericString]);
|
|
assertEquals(undefined, super[1]);
|
|
}
|
|
};
|
|
|
|
derived = new Derived();
|
|
assertEquals('derived', derived.testGetter());
|
|
derived = new Derived();
|
|
assertEquals('derived', derived.testGetterStrict());
|
|
derived = new Derived();
|
|
derived.testGetterWithToString();
|
|
}());
|
|
|
|
|
|
(function TestGetterNumericKeyed() {
|
|
var x = 42;
|
|
function Base() {}
|
|
var derived;
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
_x: 'base'
|
|
};
|
|
|
|
Object.defineProperty(Base.prototype, x, { get: function() {
|
|
assertSame(this, derived);
|
|
return this._x;
|
|
}});
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 'derived',
|
|
testGetter() {
|
|
return super[x];
|
|
},
|
|
testGetterStrict() {
|
|
'use strict';
|
|
return super[x];
|
|
},
|
|
testGetterWithToString() {
|
|
var toStringCalled;
|
|
var o = {
|
|
toString: function() {
|
|
toStringCalled++;
|
|
return '42';
|
|
}
|
|
};
|
|
|
|
toStringCalled = 0;
|
|
assertEquals('derived', super[o]);
|
|
assertEquals(1, toStringCalled);
|
|
|
|
var eToThrow = new Error();
|
|
var oThrowsInToString = {
|
|
toString: function() {
|
|
throw eToThrow;
|
|
}
|
|
};
|
|
|
|
var ex = null;
|
|
try {
|
|
super[oThrowsInToString];
|
|
} catch(e) { ex = e }
|
|
assertEquals(eToThrow, ex);
|
|
|
|
var oReturnsNumericString = {
|
|
toString: function() {
|
|
return "42";
|
|
}
|
|
};
|
|
|
|
assertEquals('derived', super[oReturnsNumericString]);
|
|
assertEquals('derived', super[42]);
|
|
}
|
|
};
|
|
|
|
derived = new Derived();
|
|
assertEquals('derived', derived.testGetter());
|
|
derived = new Derived();
|
|
assertEquals('derived', derived.testGetterStrict());
|
|
derived = new Derived();
|
|
derived.testGetterWithToString();
|
|
}());
|
|
|
|
|
|
(function TestSetter() {
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
return this._x;
|
|
},
|
|
set x(v) {
|
|
this._x = v;
|
|
},
|
|
_x: 'base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 'derived',
|
|
testSetter() {
|
|
assertEquals('foobar', super.x = 'foobar');
|
|
assertEquals('foobarabc', super.x += 'abc');
|
|
},
|
|
testSetterStrict() {
|
|
'use strict';
|
|
assertEquals('foobar', super.x = 'foobar');
|
|
assertEquals('foobarabc', super.x += 'abc');
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
d.testSetter();
|
|
assertEquals('base', Base.prototype._x);
|
|
assertEquals('foobarabc', d._x);
|
|
d._x = '';
|
|
|
|
d.testSetterStrict();
|
|
assertEquals('base', Base.prototype._x);
|
|
assertEquals('foobarabc', d._x);
|
|
}());
|
|
|
|
|
|
(function TestSetterNumericKeyed() {
|
|
var x = 42;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
_x: 'base'
|
|
};
|
|
|
|
Object.defineProperty(Base.prototype, x,
|
|
{ get: function() { return this._x; },
|
|
set: function(v) { this._x = v; }
|
|
});
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 'derived',
|
|
testSetter() {
|
|
assertEquals('foobar', super[x] = 'foobar');
|
|
assertEquals('foobarabc', super[x] += 'abc');
|
|
},
|
|
testSetterStrict() {
|
|
'use strict';
|
|
assertEquals('foobar', super[x] = 'foobar');
|
|
assertEquals('foobarabc', super[x] += 'abc');
|
|
},
|
|
testSetterWithToString() {
|
|
var toStringCalled;
|
|
var o = {
|
|
toString: function() {
|
|
toStringCalled++;
|
|
return x;
|
|
}
|
|
};
|
|
|
|
toStringCalled = 0;
|
|
super[o] = 'set';
|
|
assertEquals(1, toStringCalled);
|
|
assertEquals('set', this._x);
|
|
|
|
var eToThrow = new Error();
|
|
var oThrowsInToString = {
|
|
toString: function() {
|
|
throw eToThrow;
|
|
}
|
|
};
|
|
|
|
var ex = null;
|
|
try {
|
|
super[oThrowsInToString] = 'xyz';
|
|
} catch(e) { ex = e }
|
|
assertEquals(eToThrow, ex);
|
|
assertEquals('set', this._x);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
d.testSetter();
|
|
assertEquals('base', Base.prototype._x);
|
|
assertEquals('foobarabc', d._x);
|
|
d._x = '';
|
|
|
|
d.testSetterStrict();
|
|
assertEquals('base', Base.prototype._x);
|
|
assertEquals('foobarabc', d._x);
|
|
|
|
d = new Derived();
|
|
d.testSetterWithToString();
|
|
}());
|
|
|
|
|
|
(function TestSetterKeyed() {
|
|
var x = 'x';
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
return this._x;
|
|
},
|
|
set x(v) {
|
|
this._x = v;
|
|
},
|
|
_x: 'base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 'derived',
|
|
testSetter() {
|
|
assertEquals('foobar', super[x] = 'foobar');
|
|
assertEquals('foobarabc', super[x] += 'abc');
|
|
},
|
|
testSetterStrict() {
|
|
'use strict';
|
|
assertEquals('foobar', super[x] = 'foobar');
|
|
assertEquals('foobarabc', super[x] += 'abc');
|
|
},
|
|
testSetterWithToString() {
|
|
var toStringCalled;
|
|
var o = {
|
|
toString: function() {
|
|
toStringCalled++;
|
|
return 'x';
|
|
}
|
|
};
|
|
|
|
toStringCalled = 0;
|
|
super[o] = 'set';
|
|
assertEquals(1, toStringCalled);
|
|
assertEquals('set', this._x);
|
|
|
|
var eToThrow = new Error();
|
|
var oThrowsInToString = {
|
|
toString: function() {
|
|
throw eToThrow;
|
|
}
|
|
};
|
|
|
|
var ex = null;
|
|
try {
|
|
super[oThrowsInToString] = 'xyz';
|
|
} catch(e) { ex = e }
|
|
assertEquals(eToThrow, ex);
|
|
assertEquals('set', this._x);
|
|
|
|
var oReturnsNumericString = {
|
|
toString: function() {
|
|
return "1";
|
|
}
|
|
};
|
|
|
|
assertEquals('abc', super[oReturnsNumericString] = 'abc');
|
|
|
|
assertEquals('set', this._x);
|
|
|
|
assertEquals(10, super[1] = 10);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
d.testSetter();
|
|
assertEquals('base', Base.prototype._x);
|
|
assertEquals('foobarabc', d._x);
|
|
d._x = '';
|
|
d.testSetterStrict();
|
|
assertEquals('base', Base.prototype._x);
|
|
assertEquals('foobarabc', d._x);
|
|
|
|
d = new Derived();
|
|
d.testSetterWithToString();
|
|
}());
|
|
|
|
|
|
(function TestSetterDataProperties() {
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
x: 'x from Base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testSetter() {
|
|
assertEquals('x from Base', super.x);
|
|
super.x = 'data property';
|
|
assertEquals('x from Base', super.x);
|
|
assertEquals('data property', this.x);
|
|
}
|
|
};
|
|
|
|
new Derived().testSetter();
|
|
}());
|
|
|
|
|
|
(function TestKeyedSetterDataProperties() {
|
|
var x = 'x';
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
x: 'x from Base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testSetter() {
|
|
assertEquals('x from Base', super[x]);
|
|
super[x] = 'data property';
|
|
assertEquals('x from Base', super[x]);
|
|
assertEquals('data property', this[x]);
|
|
}
|
|
};
|
|
|
|
new Derived().testSetter();
|
|
}());
|
|
|
|
|
|
(function TestKeyedNumericSetterDataProperties() {
|
|
var x = 42;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
42: 'x from Base'
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testSetter() {
|
|
assertEquals('x from Base', super[x]);
|
|
super[x] = 'data property';
|
|
assertEquals('x from Base', super[x]);
|
|
assertEquals('data property', this[x]);
|
|
}
|
|
};
|
|
|
|
new Derived().testSetter();
|
|
}());
|
|
|
|
|
|
(function TestAccessorsOnPrimitives() {
|
|
var getCalled = 0;
|
|
var setCalled = 0;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
getCalled++;
|
|
return 1;
|
|
},
|
|
set x(v) {
|
|
setCalled++;
|
|
return v;
|
|
},
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testSetter() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals('object', typeof this);
|
|
assertInstanceof(this, Number)
|
|
assertEquals(42, this.valueOf());
|
|
assertEquals(1, super.x);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
assertEquals(5, super.x = 5);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
assertEquals(6, super.x += 5);
|
|
assertEquals(2, getCalled);
|
|
assertEquals(2, setCalled);
|
|
|
|
super.newProperty = 15;
|
|
assertEquals(15, this.newProperty);
|
|
assertEquals(undefined, super.newProperty);
|
|
},
|
|
testSetterStrict() {
|
|
'use strict';
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
assertTrue(42 === this);
|
|
|
|
assertEquals(1, super.x);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
assertEquals(5, super.x = 5);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
assertEquals(6, super.x += 5);
|
|
assertEquals(2, getCalled);
|
|
assertEquals(2, setCalled);
|
|
|
|
var ex;
|
|
try {
|
|
super.newProperty = 15;
|
|
} catch (e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
}
|
|
}
|
|
|
|
Derived.prototype.testSetter.call(42);
|
|
Derived.prototype.testSetterStrict.call(42);
|
|
|
|
function DerivedFromString() {}
|
|
DerivedFromString.prototype = {
|
|
__proto__: String.prototype,
|
|
f() {
|
|
'use strict';
|
|
assertTrue(42 === this);
|
|
assertEquals(String.prototype.toString, super.toString);
|
|
var ex;
|
|
try {
|
|
super.toString();
|
|
} catch(e) { ex = e; }
|
|
|
|
assertInstanceof(ex, TypeError);
|
|
}
|
|
};
|
|
|
|
DerivedFromString.prototype.f.call(42);
|
|
}());
|
|
|
|
|
|
(function TestKeyedAccessorsOnPrimitives() {
|
|
var x = 'x';
|
|
var newProperty = 'newProperty';
|
|
var toString = 'toString';
|
|
var getCalled = 0;
|
|
var setCalled = 0;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
getCalled++;
|
|
return 1;
|
|
},
|
|
set x(v) {
|
|
setCalled++;
|
|
return v;
|
|
},
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testSetter() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals('object', typeof this);
|
|
assertInstanceof(this, Number)
|
|
assertEquals(42, this.valueOf());
|
|
assertEquals(1, super[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
assertEquals(5, super[x] = 5);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
assertEquals(6, super[x] += 5);
|
|
assertEquals(2, getCalled);
|
|
assertEquals(2, setCalled);
|
|
|
|
super[newProperty] = 15;
|
|
assertEquals(15, this[newProperty]);
|
|
assertEquals(undefined, super[newProperty]);
|
|
},
|
|
testSetterStrict() {
|
|
'use strict';
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
assertTrue(42 === this);
|
|
|
|
assertEquals(1, super[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
assertEquals(5, super[x] = 5);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
assertEquals(6, super[x] += 5);
|
|
assertEquals(2, getCalled);
|
|
assertEquals(2, setCalled);
|
|
|
|
var ex;
|
|
try {
|
|
super[newProperty] = 15;
|
|
} catch (e) { ex = e; }
|
|
assertInstanceof(ex,TypeError);
|
|
}
|
|
};
|
|
|
|
Derived.prototype.testSetter.call(42);
|
|
Derived.prototype.testSetterStrict.call(42);
|
|
|
|
function DerivedFromString() {}
|
|
DerivedFromString.prototype = {
|
|
__proto__: String.prototype,
|
|
f() {
|
|
'use strict';
|
|
assertTrue(42 === this);
|
|
assertEquals(String.prototype.toString, super[toString]);
|
|
var ex;
|
|
try {
|
|
super[toString]();
|
|
} catch(e) { ex = e; }
|
|
|
|
assertInstanceof(ex, TypeError);
|
|
}
|
|
};
|
|
DerivedFromString.prototype.f.call(42);
|
|
}());
|
|
|
|
|
|
(function TestNumericKeyedAccessorsOnPrimitives() {
|
|
var x = 42;
|
|
var newProperty = 43;
|
|
var getCalled = 0;
|
|
var setCalled = 0;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
};
|
|
|
|
Object.defineProperty(Base.prototype, x, {
|
|
get: function() {
|
|
getCalled++;
|
|
return 1;
|
|
},
|
|
set: function(v) {
|
|
setCalled++;
|
|
return v;
|
|
}
|
|
});
|
|
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testSetter() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals('object', typeof this);
|
|
assertInstanceof(this, Number)
|
|
assertEquals(42, this.valueOf());
|
|
assertEquals(1, super[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
assertEquals(5, super[x] = 5);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
assertEquals(6, super[x] += 5);
|
|
assertEquals(2, getCalled);
|
|
assertEquals(2, setCalled);
|
|
|
|
super[newProperty] = 15;
|
|
assertEquals(15, this[newProperty]);
|
|
assertEquals(undefined, super[newProperty]);
|
|
},
|
|
testSetterStrict() {
|
|
'use strict';
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
assertTrue(42 === this);
|
|
|
|
assertEquals(1, super[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
assertEquals(5, super[x] = 5);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
assertEquals(6, super[x] += 5);
|
|
assertEquals(2, getCalled);
|
|
assertEquals(2, setCalled);
|
|
|
|
var ex;
|
|
try {
|
|
super[newProperty] = 15;
|
|
} catch (e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
}
|
|
};
|
|
|
|
Derived.prototype.testSetter.call(42);
|
|
Derived.prototype.testSetterStrict.call(42);
|
|
}());
|
|
|
|
|
|
(function TestKeyedNumericSetterOnExotics() {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
callSetterOnArray() {
|
|
super[42] = 1;
|
|
},
|
|
callStrictSetterOnString() {
|
|
'use strict';
|
|
assertEquals('string', typeof this);
|
|
assertTrue('abcdef' === this);
|
|
var ex = null;
|
|
try {
|
|
super[5] = 'q';
|
|
} catch(e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
|
|
ex = null;
|
|
try {
|
|
super[1024] = 'q';
|
|
} catch(e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
}
|
|
};
|
|
|
|
var x = [];
|
|
assertEquals(0, x.length);
|
|
Derived.prototype.callSetterOnArray.call(x);
|
|
assertEquals(43, x.length);
|
|
assertEquals(1, x[42]);
|
|
|
|
var s = 'abcdef';
|
|
Derived.prototype.callStrictSetterOnString.call(s)
|
|
}());
|
|
|
|
|
|
(function TestSetterUndefinedProperties() {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(undefined, super.x);
|
|
assertEquals(undefined, this.x);
|
|
super.x = 10;
|
|
assertEquals(10, this.x);
|
|
assertEquals(undefined, super.x);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(undefined, super.x);
|
|
assertEquals(undefined, this.x);
|
|
super.x = 10;
|
|
assertEquals(10, this.x);
|
|
assertEquals(undefined, super.x);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
d.mSloppy();
|
|
assertEquals(10, d.x);
|
|
var d1 = new Derived();
|
|
d1.mStrict();
|
|
assertEquals(10, d.x);
|
|
}());
|
|
|
|
|
|
(function TestKeyedSetterUndefinedProperties() {
|
|
var x = 'x';
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(undefined, super[x]);
|
|
assertEquals(undefined, this[x]);
|
|
super[x] = 10;
|
|
assertEquals(10, this[x]);
|
|
assertEquals(undefined, super[x]);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(undefined, super[x]);
|
|
assertEquals(undefined, this[x]);
|
|
super[x] = 10;
|
|
assertEquals(10, this[x]);
|
|
assertEquals(undefined, super[x]);
|
|
}
|
|
};
|
|
var d = new Derived();
|
|
d.mSloppy();
|
|
assertEquals(10, d.x);
|
|
var d1 = new Derived();
|
|
d1.mStrict();
|
|
assertEquals(10, d.x);
|
|
}());
|
|
|
|
|
|
(function TestKeyedNumericSetterUndefinedProperties() {
|
|
var x = 42;
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(undefined, super[x]);
|
|
assertEquals(undefined, this[x]);
|
|
super[x] = 10;
|
|
assertEquals(10, this[x]);
|
|
assertEquals(undefined, super[x]);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(undefined, super[x]);
|
|
assertEquals(undefined, this[x]);
|
|
super[x] = 10;
|
|
assertEquals(10, this[x]);
|
|
assertEquals(undefined, super[x]);
|
|
}
|
|
};
|
|
var d = new Derived();
|
|
d.mSloppy();
|
|
assertEquals(10, d[x]);
|
|
var d1 = new Derived();
|
|
d1.mStrict();
|
|
assertEquals(10, d[x]);
|
|
}());
|
|
|
|
|
|
(function TestSetterCreatingOwnPropertiesReconfigurable() {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(42, this.ownReadOnly);
|
|
super.ownReadOnly = 55;
|
|
assertSame(undefined, super.ownReadOnly);
|
|
assertEquals(42, this.ownReadOnly);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownReadOnly'));
|
|
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
super.ownReadonlyAccessor = 25;
|
|
assertSame(undefined, super.ownReadonlyAccessor);
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownReadonlyAccessor'));
|
|
|
|
super.ownSetter = 35;
|
|
assertSame(undefined, super.ownSetter);
|
|
var descr = Object.getOwnPropertyDescriptor(this, 'ownSetter');
|
|
assertTrue('set' in descr);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownSetter'));
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(42, this.ownReadOnly);
|
|
assertThrows(() => {super.ownReadOnly = 55}, TypeError);
|
|
assertSame(undefined, super.ownReadOnly);
|
|
assertEquals(42, this.ownReadOnly);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownReadOnly'));
|
|
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
assertThrows(() => {super.ownReadonlyAccessor = 25}, TypeError);
|
|
assertSame(undefined, super.ownReadonlyAccessor);
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownReadonlyAccessor'));
|
|
|
|
assertThrows(() => {super.ownSetter = 35}, TypeError);
|
|
assertSame(undefined, super.ownSetter);
|
|
var descr = Object.getOwnPropertyDescriptor(this, 'ownSetter');
|
|
assertTrue('set' in descr);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownSetter'));
|
|
},
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, 'ownReadOnly', {
|
|
value: 42,
|
|
writable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, 'ownSetter', {
|
|
set: function() { assertUnreachable(); },
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, 'ownReadonlyAccessor', {
|
|
get: function() { return 15; },
|
|
configurable: true
|
|
});
|
|
|
|
d.mSloppy();
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, 'ownReadOnly', {
|
|
value: 42,
|
|
writable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, 'ownSetter', {
|
|
set: function() { assertUnreachable(); },
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, 'ownReadonlyAccessor', {
|
|
get: function() { return 15; },
|
|
configurable: true
|
|
});
|
|
d.mStrict();
|
|
}());
|
|
|
|
|
|
(function TestSetterCreatingOwnPropertiesNonConfigurable() {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(42, this.ownReadOnly);
|
|
super.ownReadOnly = 55;
|
|
assertEquals(42, this.ownReadOnly);
|
|
var descr = Object.getOwnPropertyDescriptor(this, 'ownReadOnly');
|
|
assertEquals(42, descr.value);
|
|
assertFalse(descr.configurable);
|
|
assertFalse(descr.enumerable);
|
|
assertFalse(descr.writable);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownReadOnly'));
|
|
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
super.ownReadonlyAccessor = 25;
|
|
assertSame(undefined, super.ownReadonlyAccessor);
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
var descr = Object.getOwnPropertyDescriptor(this, 'ownReadonlyAccessor');
|
|
assertFalse(descr.configurable);
|
|
assertFalse(descr.enumerable);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownReadonlyAccessor'));
|
|
|
|
super.ownSetter = 35;
|
|
var descr = Object.getOwnPropertyDescriptor(this, 'ownSetter');
|
|
assertFalse(descr.configurable);
|
|
assertFalse(descr.enumerable);
|
|
assertFalse(Base.prototype.hasOwnProperty('ownSetter'));
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
var ex;
|
|
assertEquals(42, this.ownReadOnly);
|
|
try {
|
|
super.ownReadOnly = 55;
|
|
} catch (e) {
|
|
ex = e;
|
|
}
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals(
|
|
"Cannot assign to read only property 'ownReadOnly' of object '#<Base>'",
|
|
ex.message);
|
|
assertEquals(42, this.ownReadOnly);
|
|
|
|
ex = null;
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
try {
|
|
super.ownReadonlyAccessor = 25;
|
|
} catch (e) {
|
|
ex = e;
|
|
}
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals('Cannot redefine property: ownReadonlyAccessor', ex.message);
|
|
assertEquals(15, this.ownReadonlyAccessor);
|
|
|
|
ex = null;
|
|
try {
|
|
super.ownSetter = 35;
|
|
} catch (e) {
|
|
ex = e;
|
|
}
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals('Cannot redefine property: ownSetter', ex.message);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, 'ownReadOnly', { value : 42, writable : false });
|
|
Object.defineProperty(d, 'ownSetter',
|
|
{ set : function() { assertUnreachable(); } });
|
|
Object.defineProperty(d, 'ownReadonlyAccessor',
|
|
{ get : function() { return 15; }});
|
|
d.mSloppy();
|
|
d.mStrict();
|
|
}());
|
|
|
|
|
|
(function TestSetterInForIn() {
|
|
var setCalled = 0;
|
|
var getCalled = 0;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
getCalled++;
|
|
return 1;
|
|
},
|
|
set x(v) {
|
|
setCalled++;
|
|
this.x_.push(v);
|
|
},
|
|
};
|
|
|
|
function Derived() {
|
|
this.x_ = [];
|
|
}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
testIter() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
for (super.x in [1,2,3]) {}
|
|
assertEquals(0, getCalled);
|
|
assertEquals(3, setCalled);
|
|
assertEquals(["0", "1", "2"], this.x_);
|
|
},
|
|
testIterKeyed() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
for (super[x] in [1,2,3]) {}
|
|
assertEquals(0, getCalled);
|
|
assertEquals(3, setCalled);
|
|
assertEquals(["0","1","2"], this.x_);
|
|
|
|
this.x_ = [];
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
var toStringCalled = 0;
|
|
var o = {toString: function () { toStringCalled++; return x }};
|
|
for (super[o] in [1,2,3]) {}
|
|
assertEquals(0, getCalled);
|
|
assertEquals(3, setCalled);
|
|
assertEquals(3, toStringCalled);
|
|
assertEquals(["0","1","2"], this.x_);
|
|
}
|
|
};
|
|
|
|
new Derived().testIter();
|
|
|
|
var x = 'x';
|
|
|
|
new Derived().testIterKeyed();
|
|
}());
|
|
|
|
|
|
function TestKeyedSetterCreatingOwnPropertiesReconfigurable(ownReadOnly,
|
|
ownReadonlyAccessor, ownSetter) {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(42, this[ownReadOnly]);
|
|
super[ownReadOnly] = 55;
|
|
assertSame(undefined, super[ownReadOnly]);
|
|
assertEquals(42, this[ownReadOnly]);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownReadOnly));
|
|
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
super[ownReadonlyAccessor] = 25;
|
|
assertSame(undefined, super[ownReadonlyAccessor]);
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownReadonlyAccessor));
|
|
|
|
super[ownSetter] = 35;
|
|
assertSame(undefined, super[ownSetter]);
|
|
var descr = Object.getOwnPropertyDescriptor(this, ownSetter);
|
|
assertTrue('set' in descr);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownSetter));
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(42, this[ownReadOnly]);
|
|
assertThrows(() => {super[ownReadOnly] = 55}, TypeError);
|
|
assertSame(undefined, super[ownReadOnly]);
|
|
assertEquals(42, this[ownReadOnly]);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownReadOnly));
|
|
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
assertThrows(() => {super[ownReadonlyAccessor] = 25}, TypeError);
|
|
assertSame(undefined, super[ownReadonlyAccessor]);
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownReadonlyAccessor));
|
|
|
|
assertThrows(() => {super[ownSetter] = 35}, TypeError);
|
|
assertSame(undefined, super[ownSetter]);
|
|
var descr = Object.getOwnPropertyDescriptor(this, ownSetter);
|
|
assertTrue('set' in descr);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownSetter));
|
|
},
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, ownReadOnly, {
|
|
value: 42,
|
|
writable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, ownSetter, {
|
|
set: function() { assertUnreachable(); },
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, ownReadonlyAccessor, {
|
|
get: function() { return 15; },
|
|
configurable: true
|
|
});
|
|
|
|
d.mSloppy();
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, ownReadOnly, {
|
|
value: 42,
|
|
writable: false,
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, ownSetter, {
|
|
set: function() { assertUnreachable(); },
|
|
configurable: true
|
|
});
|
|
Object.defineProperty(d, ownReadonlyAccessor, {
|
|
get: function() { return 15; },
|
|
configurable: true
|
|
});
|
|
d.mStrict();
|
|
}
|
|
TestKeyedSetterCreatingOwnPropertiesReconfigurable('ownReadOnly',
|
|
'ownReadonlyAccessor',
|
|
'ownSetter');
|
|
TestKeyedSetterCreatingOwnPropertiesReconfigurable(42, 43, 44);
|
|
|
|
|
|
function TestKeyedSetterCreatingOwnPropertiesNonConfigurable(
|
|
ownReadOnly, ownReadonlyAccessor, ownSetter) {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
assertEquals(42, this[ownReadOnly]);
|
|
super[ownReadOnly] = 55;
|
|
assertEquals(42, this[ownReadOnly]);
|
|
var descr = Object.getOwnPropertyDescriptor(this, ownReadOnly);
|
|
assertEquals(42, descr.value);
|
|
assertFalse(descr.configurable);
|
|
assertFalse(descr.enumerable);
|
|
assertFalse(descr.writable);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownReadOnly));
|
|
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
super[ownReadonlyAccessor] = 25;
|
|
assertSame(undefined, super[ownReadonlyAccessor]);
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
var descr = Object.getOwnPropertyDescriptor(this, ownReadonlyAccessor);
|
|
assertFalse(descr.configurable);
|
|
assertFalse(descr.enumerable);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownReadonlyAccessor));
|
|
|
|
super[ownSetter] = 35;
|
|
var descr = Object.getOwnPropertyDescriptor(this, ownSetter);
|
|
assertFalse(descr.configurable);
|
|
assertFalse(descr.enumerable);
|
|
assertFalse(Base.prototype.hasOwnProperty(ownSetter));
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
var ex;
|
|
assertEquals(42, this[ownReadOnly]);
|
|
try {
|
|
super[ownReadOnly] = 55;
|
|
} catch (e) {
|
|
ex = e;
|
|
}
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals(
|
|
"Cannot assign to read only property '" + ownReadOnly +
|
|
"' of object '#<Base>'",
|
|
ex.message);
|
|
assertEquals(42, this[ownReadOnly]);
|
|
|
|
ex = null;
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
try {
|
|
super[ownReadonlyAccessor] = 25;
|
|
} catch (e) {
|
|
ex = e;
|
|
}
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals('Cannot redefine property: ' + ownReadonlyAccessor,
|
|
ex.message);
|
|
assertEquals(15, this[ownReadonlyAccessor]);
|
|
|
|
ex = null;
|
|
try {
|
|
super[ownSetter] = 35;
|
|
} catch (e) {
|
|
ex = e;
|
|
}
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals('Cannot redefine property: ' + ownSetter, ex.message);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, ownReadOnly, { value : 42, writable : false });
|
|
Object.defineProperty(d, ownSetter,
|
|
{ set : function() { assertUnreachable(); } });
|
|
Object.defineProperty(d, ownReadonlyAccessor,
|
|
{ get : function() { return 15; }});
|
|
d.mSloppy();
|
|
d.mStrict();
|
|
}
|
|
TestKeyedSetterCreatingOwnPropertiesNonConfigurable('ownReadOnly',
|
|
'ownReadonlyAccessor', 'ownSetter');
|
|
TestKeyedSetterCreatingOwnPropertiesNonConfigurable(42, 43, 44);
|
|
|
|
|
|
(function TestSetterNoProtoWalk() {
|
|
function Base() {}
|
|
function Derived() {}
|
|
var getCalled;
|
|
var setCalled;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
get x() { getCalled++; return 42; },
|
|
set x(v) { setCalled++; },
|
|
mSloppy() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals(42, this.x);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
this.x = 43;
|
|
assertEquals(0, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
super.x = 15;
|
|
assertEquals(0, setCalled);
|
|
assertEquals(0, getCalled);
|
|
|
|
assertEquals(15, this.x);
|
|
assertEquals(0, getCalled);
|
|
assertEquals(0, setCalled);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals(42, this.x);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
this.x = 43;
|
|
assertEquals(0, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
super.x = 15;
|
|
assertEquals(0, setCalled);
|
|
assertEquals(0, getCalled);
|
|
|
|
assertEquals(15, this.x);
|
|
assertEquals(0, getCalled);
|
|
assertEquals(0, setCalled);
|
|
}
|
|
};
|
|
|
|
new Derived().mSloppy();
|
|
new Derived().mStrict();
|
|
}());
|
|
|
|
|
|
(function TestKeyedSetterNoProtoWalk() {
|
|
var x = 'x';
|
|
function Base() {}
|
|
function Derived() {}
|
|
var getCalled;
|
|
var setCalled;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
get x() { getCalled++; return 42; },
|
|
set x(v) { setCalled++; },
|
|
mSloppy() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals(42, this[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
this[x] = 43;
|
|
assertEquals(0, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
super[x] = 15;
|
|
assertEquals(0, setCalled);
|
|
assertEquals(0, getCalled);
|
|
|
|
assertEquals(15, this[x]);
|
|
assertEquals(0, getCalled);
|
|
assertEquals(0, setCalled);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals(42, this[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
this[x] = 43;
|
|
assertEquals(0, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
super[x] = 15;
|
|
assertEquals(0, setCalled);
|
|
assertEquals(0, getCalled);
|
|
|
|
assertEquals(15, this[x]);
|
|
assertEquals(0, getCalled);
|
|
assertEquals(0, setCalled);
|
|
}
|
|
};
|
|
|
|
new Derived().mSloppy();
|
|
new Derived().mStrict();
|
|
}());
|
|
|
|
|
|
(function TestKeyedNumericSetterNoProtoWalk() {
|
|
var x = 42;
|
|
function Base() {}
|
|
function Derived() {}
|
|
var getCalled;
|
|
var setCalled;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mSloppy() {
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals(42, this[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
this[x] = 43;
|
|
assertEquals(0, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
super[x] = 15;
|
|
assertEquals(0, setCalled);
|
|
assertEquals(0, getCalled);
|
|
|
|
assertEquals(15, this[x]);
|
|
assertEquals(0, getCalled);
|
|
assertEquals(0, setCalled);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
setCalled = 0;
|
|
getCalled = 0;
|
|
assertEquals(42, this[x]);
|
|
assertEquals(1, getCalled);
|
|
assertEquals(0, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
this[x] = 43;
|
|
assertEquals(0, getCalled);
|
|
assertEquals(1, setCalled);
|
|
|
|
getCalled = 0;
|
|
setCalled = 0;
|
|
super[x] = 15;
|
|
assertEquals(0, setCalled);
|
|
assertEquals(0, getCalled);
|
|
|
|
assertEquals(15, this[x]);
|
|
assertEquals(0, getCalled);
|
|
assertEquals(0, setCalled);
|
|
}
|
|
};
|
|
|
|
Object.defineProperty(Derived.prototype, x, {
|
|
get: function() { getCalled++; return 42; },
|
|
set: function(v) { setCalled++; }
|
|
});
|
|
|
|
new Derived().mSloppy();
|
|
new Derived().mStrict();
|
|
}());
|
|
|
|
|
|
(function TestSetterDoesNotReconfigure() {
|
|
function Base() {}
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Derived.prototype,
|
|
mStrict(){
|
|
'use strict';
|
|
super.nonEnumConfig = 5;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumConfig');
|
|
assertEquals(5, d1.value);
|
|
assertTrue(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
|
|
super.nonEnumNonConfig = 5;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumNonConfig');
|
|
assertEquals(5, d1.value);
|
|
assertFalse(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
},
|
|
mSloppy(){
|
|
super.nonEnumConfig = 42;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumConfig');
|
|
assertEquals(42, d1.value);
|
|
assertTrue(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
|
|
super.nonEnumNonConfig = 42;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, 'nonEnumNonConfig');
|
|
assertEquals(42, d1.value);
|
|
assertFalse(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, 'nonEnumConfig',
|
|
{ value : 0, enumerable : false, configurable : true, writable : true });
|
|
Object.defineProperty(d, 'nonEnumNonConfig',
|
|
{ value : 0, enumerable : false, configurable : false, writable : true });
|
|
d.mStrict();
|
|
d.mSloppy();
|
|
}());
|
|
|
|
|
|
(function TestKeyedSetterDoesNotReconfigure() {
|
|
var nonEnumConfig = 'nonEnumConfig';
|
|
var nonEnumNonConfig = 'nonEnumNonConfig';
|
|
function Base() {}
|
|
function Derived() {}
|
|
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mStrict(){
|
|
'use strict';
|
|
super[nonEnumConfig] = 5;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumConfig);
|
|
assertEquals(5, d1.value);
|
|
assertTrue(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
|
|
super[nonEnumNonConfig] = 5;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumNonConfig);
|
|
assertEquals(5, d1.value);
|
|
assertFalse(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
},
|
|
mSloppy(){
|
|
super[nonEnumConfig] = 42;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumConfig);
|
|
assertEquals(42, d1.value);
|
|
assertTrue(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
|
|
super[nonEnumNonConfig] = 42;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumNonConfig);
|
|
assertEquals(42, d1.value);
|
|
assertFalse(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, nonEnumConfig,
|
|
{ value : 0, enumerable : false, configurable : true, writable : true });
|
|
Object.defineProperty(d, nonEnumNonConfig,
|
|
{ value : 0, enumerable : false, configurable : false, writable : true });
|
|
d.mStrict();
|
|
d.mSloppy();
|
|
}());
|
|
|
|
|
|
(function TestKeyedNumericSetterDoesNotReconfigure() {
|
|
var nonEnumConfig = 42;
|
|
var nonEnumNonConfig = 43;
|
|
function Base() {}
|
|
function Derived() {}
|
|
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
mStrict(){
|
|
'use strict';
|
|
super[nonEnumConfig] = 5;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumConfig);
|
|
assertEquals(5, d1.value);
|
|
assertTrue(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
|
|
super[nonEnumNonConfig] = 5;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumNonConfig);
|
|
assertEquals(5, d1.value);
|
|
assertFalse(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
},
|
|
mSloppy(){
|
|
super[nonEnumConfig] = 42;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumConfig);
|
|
assertEquals(42, d1.value);
|
|
assertTrue(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
|
|
super[nonEnumNonConfig] = 42;
|
|
var d1 = Object.getOwnPropertyDescriptor(this, nonEnumNonConfig);
|
|
assertEquals(42, d1.value);
|
|
assertFalse(d1.configurable);
|
|
assertFalse(d1.enumerable);
|
|
}
|
|
};
|
|
|
|
var d = new Derived();
|
|
Object.defineProperty(d, nonEnumConfig,
|
|
{ value : 0, enumerable : false, configurable : true, writable : true });
|
|
Object.defineProperty(d, nonEnumNonConfig,
|
|
{ value : 0, enumerable : false, configurable : false, writable : true });
|
|
d.mStrict();
|
|
d.mSloppy();
|
|
}());
|
|
|
|
|
|
(function TestCountOperations() {
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
return this._x;
|
|
},
|
|
set x(v) {
|
|
this._x = v;
|
|
},
|
|
_x: 1
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 2,
|
|
testCounts() {
|
|
assertEquals(2, this._x);
|
|
assertEquals(2, super.x);
|
|
super.x++;
|
|
assertEquals(3, super.x);
|
|
++super.x;
|
|
assertEquals(4, super.x);
|
|
assertEquals(4, super.x++);
|
|
assertEquals(5, super.x);
|
|
assertEquals(6, ++super.x);
|
|
assertEquals(6, super.x);
|
|
assertEquals(6, this._x);
|
|
|
|
super.x--;
|
|
assertEquals(5, super.x);
|
|
--super.x;
|
|
assertEquals(4, super.x);
|
|
assertEquals(4, super.x--);
|
|
assertEquals(3, super.x);
|
|
assertEquals(2, --super.x);
|
|
assertEquals(2, super.x);
|
|
assertEquals(2, this._x);
|
|
}
|
|
};
|
|
new Derived().testCounts();
|
|
}());
|
|
|
|
|
|
(function TestKeyedCountOperations() {
|
|
var x = 'x';
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
get x() {
|
|
return this._x;
|
|
},
|
|
set x(v) {
|
|
this._x = v;
|
|
},
|
|
_x: 1
|
|
};
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 2,
|
|
testCounts() {
|
|
assertEquals(2, this._x);
|
|
assertEquals(2, super[x]);
|
|
super[x]++;
|
|
assertEquals(3, super[x]);
|
|
++super[x];
|
|
assertEquals(4, super[x]);
|
|
assertEquals(4, super[x]++);
|
|
assertEquals(5, super[x]);
|
|
assertEquals(6, ++super[x]);
|
|
assertEquals(6, super[x]);
|
|
assertEquals(6, this._x);
|
|
|
|
super[x]--;
|
|
assertEquals(5, super[x]);
|
|
--super[x];
|
|
assertEquals(4, super[x]);
|
|
assertEquals(4, super[x]--);
|
|
assertEquals(3, super[x]);
|
|
assertEquals(2, --super[x]);
|
|
assertEquals(2, super[x]);
|
|
assertEquals(2, this._x);
|
|
}
|
|
};
|
|
new Derived().testCounts();
|
|
}());
|
|
|
|
|
|
(function TestKeyedNumericCountOperations() {
|
|
var x = 42;
|
|
function Base() {}
|
|
Base.prototype = {
|
|
constructor: Base,
|
|
_x: 1
|
|
};
|
|
|
|
Object.defineProperty(Base.prototype, x, {
|
|
get: function() { return this._x; },
|
|
set: function(v) { this._x = v;; }
|
|
});
|
|
|
|
function Derived() {}
|
|
Derived.__proto__ = Base;
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
_x: 2,
|
|
testCounts() {
|
|
assertEquals(2, this._x);
|
|
assertEquals(2, super[x]);
|
|
super[x]++;
|
|
assertEquals(3, super[x]);
|
|
++super[x];
|
|
assertEquals(4, super[x]);
|
|
assertEquals(4, super[x]++);
|
|
assertEquals(5, super[x]);
|
|
assertEquals(6, ++super[x]);
|
|
assertEquals(6, super[x]);
|
|
assertEquals(6, this._x);
|
|
|
|
super[x]--;
|
|
assertEquals(5, super[x]);
|
|
--super[x];
|
|
assertEquals(4, super[x]);
|
|
assertEquals(4, super[x]--);
|
|
assertEquals(3, super[x]);
|
|
assertEquals(2, --super[x]);
|
|
assertEquals(2, super[x]);
|
|
assertEquals(2, this._x);
|
|
}
|
|
};
|
|
new Derived().testCounts();
|
|
}());
|
|
|
|
|
|
(function TestSetterSuperNonWritable() {
|
|
function Base() {}
|
|
Object.defineProperty(Base.prototype, 'x', { value : 27, writable: false });
|
|
function Derived() {}
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
mSloppy() {
|
|
assertEquals(27, super.x);
|
|
assertEquals(27, this.x);
|
|
super.x = 10;
|
|
assertEquals(27, super.x);
|
|
assertEquals(27, this.x);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(27, super.x);
|
|
assertEquals(27, this.x);
|
|
var ex = null;
|
|
try { super.x = 10; } catch(e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals(27, super.x);
|
|
assertEquals(27, this.x);
|
|
}
|
|
};
|
|
new Derived().mSloppy();
|
|
new Derived().mStrict();
|
|
}());
|
|
|
|
|
|
(function TestSetterKeyedSuperNonWritable() {
|
|
var x = 'xyz';
|
|
function Base() {}
|
|
Object.defineProperty(Base.prototype, x, { value : 27, writable: false });
|
|
function Derived() {}
|
|
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
mSloppy() {
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
super[x] = 10;
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
var ex = null;
|
|
try { super[x] = 10; } catch(e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
}
|
|
};
|
|
new Derived().mSloppy();
|
|
new Derived().mStrict();
|
|
}());
|
|
|
|
|
|
(function TestSetterKeyedNumericSuperNonWritable() {
|
|
var x = 42;
|
|
function Base() {}
|
|
Object.defineProperty(Base.prototype, x, { value : 27, writable: false });
|
|
function Derived() {}
|
|
|
|
Derived.prototype = {
|
|
__proto__: Base.prototype,
|
|
constructor: Derived,
|
|
mSloppy() {
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
super[x] = 10;
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
},
|
|
mStrict() {
|
|
'use strict';
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
var ex = null;
|
|
try { super[x] = 10; } catch(e) { ex = e; }
|
|
assertInstanceof(ex, TypeError);
|
|
assertEquals(27, super[x]);
|
|
assertEquals(27, this[x]);
|
|
}
|
|
};
|
|
new Derived().mSloppy();
|
|
new Derived().mStrict();
|
|
}());
|
|
|
|
|
|
(function TestSuperCall() {
|
|
'use strict';
|
|
|
|
var baseCalled = 0;
|
|
var derivedCalled = 0;
|
|
var derivedDerivedCalled = 0;
|
|
|
|
class Base {
|
|
constructor() {
|
|
baseCalled++;
|
|
}
|
|
}
|
|
|
|
class Derived extends Base {
|
|
constructor() {
|
|
let r = super();
|
|
assertEquals(this, r);
|
|
derivedCalled++;
|
|
}
|
|
}
|
|
|
|
assertEquals(Base, Base.prototype.constructor);
|
|
assertEquals(Base.prototype, Derived.prototype.__proto__);
|
|
|
|
baseCalled = 0;
|
|
derivedCalled = 0;
|
|
new Derived();
|
|
assertEquals(1, baseCalled);
|
|
assertEquals(1, derivedCalled);
|
|
|
|
class DerivedDerived extends Derived {
|
|
constructor() {
|
|
let r = super();
|
|
assertEquals(this, r);
|
|
derivedDerivedCalled++;
|
|
}
|
|
}
|
|
|
|
baseCalled = 0;
|
|
derivedCalled = 0;
|
|
derivedDerivedCalled = 0;
|
|
new DerivedDerived();
|
|
assertEquals(1, baseCalled);
|
|
assertEquals(1, derivedCalled);
|
|
assertEquals(1, derivedDerivedCalled);
|
|
|
|
class Base2 {
|
|
constructor(v) {
|
|
this.fromBase = v;
|
|
}
|
|
}
|
|
class Derived2 extends Base2 {
|
|
constructor(v1, v2) {
|
|
let r = super(v1);
|
|
assertEquals(this, r);
|
|
this.fromDerived = v2;
|
|
}
|
|
}
|
|
|
|
var d = new Derived2("base", "derived");
|
|
assertEquals("base", d.fromBase);
|
|
assertEquals("derived", d.fromDerived);
|
|
|
|
var calls = 0;
|
|
class G {
|
|
constructor() {
|
|
calls++;
|
|
}
|
|
}
|
|
|
|
class F extends Object {
|
|
constructor() {
|
|
super();
|
|
}
|
|
}
|
|
F.__proto__ = G;
|
|
new F();
|
|
assertEquals(1, calls);
|
|
F.__proto__ = function() {};
|
|
new F();
|
|
assertEquals(1, calls);
|
|
}());
|
|
|
|
|
|
(function TestExtendsObject() {
|
|
'use strict';
|
|
class F extends Object { }
|
|
var f = new F(42);
|
|
|
|
assertInstanceof(f, F);
|
|
assertInstanceof(f, Object);
|
|
}());
|
|
|
|
|
|
(function TestSuperCallErrorCases() {
|
|
'use strict';
|
|
class T extends Object {
|
|
constructor() {
|
|
super();
|
|
}
|
|
}
|
|
|
|
T.__proto__ = null;
|
|
assertThrows(function() { new T(); }, TypeError);
|
|
}());
|
|
|
|
|
|
(function TestSuperPropertyInEval() {
|
|
'use strict';
|
|
let y = 3;
|
|
class Base {
|
|
m() { return 1; }
|
|
get x() { return 2; }
|
|
}
|
|
class Derived extends Base {
|
|
evalM() {
|
|
assertEquals(1, eval('super.m()'));
|
|
}
|
|
evalX() {
|
|
assertEquals(2, eval('super.x'));
|
|
}
|
|
globalEval1() {
|
|
assertThrows('super.x', SyntaxError);
|
|
assertThrows('super.m()', SyntaxError);
|
|
}
|
|
globalEval2() {
|
|
super.x;
|
|
assertThrows('super.x', SyntaxError);
|
|
assertThrows('super.m()', SyntaxError);
|
|
}
|
|
}
|
|
let d = new Derived();
|
|
d.globalEval1();
|
|
d.globalEval2();
|
|
d.evalM();
|
|
d.evalX();
|
|
})();
|
|
|
|
|
|
(function TestSuperPropertyInArrow() {
|
|
'use strict';
|
|
let y = 3;
|
|
class Base {
|
|
m() { return 1; }
|
|
get x() { return 2; }
|
|
}
|
|
class Derived extends Base {
|
|
arrow() {
|
|
assertSame(super.x, (() => super.x)());
|
|
assertSame(super.m(), (() => super.m())());
|
|
return (() => super.m())();
|
|
}
|
|
}
|
|
let d = new Derived();
|
|
assertSame(1, d.arrow());
|
|
})();
|
|
|
|
|
|
(function TestSuperInOtherScopes() {
|
|
var p = {x: 99};
|
|
var o0 = {__proto__: p, f() { return eval("'use strict'; super.x") }};
|
|
assertEquals(p.x, o0.f());
|
|
var o1 = {__proto__: p, f() { with ({}) return super.x }};
|
|
assertEquals(p.x, o1.f());
|
|
var o2 = {__proto__: p, f({a}) { return super.x }};
|
|
assertEquals(p.x, o2.f({}));
|
|
var o3 = {__proto__: p, f(...a) { return super.x }};
|
|
assertEquals(p.x, o3.f());
|
|
var o4 = {__proto__: p, f() { 'use strict'; { let x; return super.x } }};
|
|
assertEquals(p.x, o4.f());
|
|
})();
|
|
|
|
|
|
(function TestSuperCallInOtherScopes() {
|
|
class C {constructor() { this.x = 99 }}
|
|
class D0 extends C {constructor() { eval("'use strict'; super()") }}
|
|
assertEquals(99, (new D0).x);
|
|
class D2 extends C {constructor({a}) { super() }}
|
|
assertEquals(99, (new D2({})).x);
|
|
class D3 extends C {constructor(...a) { super() }}
|
|
assertEquals(99, (new D3()).x);
|
|
class D4 extends C {constructor() { { let x; super() } }}
|
|
assertEquals(99, (new D4).x);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallInEval() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
class Derived extends Base {
|
|
constructor(x) {
|
|
let r = eval('super(x)');
|
|
assertEquals(this, r);
|
|
}
|
|
}
|
|
let d = new Derived(42);
|
|
assertSame(42, d.x);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallInArrow() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
class Derived extends Base {
|
|
constructor(x) {
|
|
let r = (() => super(x))();
|
|
assertEquals(this, r);
|
|
}
|
|
}
|
|
let d = new Derived(42);
|
|
assertSame(42, d.x);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallEscapes() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
|
|
let f;
|
|
class Derived extends Base {
|
|
constructor() {
|
|
f = () => super(2);
|
|
}
|
|
}
|
|
assertThrows(function() {
|
|
new Derived();
|
|
}, ReferenceError);
|
|
|
|
let o = f();
|
|
assertEquals(2, o.x);
|
|
assertInstanceof(o, Derived);
|
|
|
|
assertThrows(function() {
|
|
f();
|
|
}, ReferenceError);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallInLoop() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
class Derived extends Base {
|
|
constructor(x, n) {
|
|
for (var i = 0; i < n; ++i) {
|
|
super(x);
|
|
}
|
|
}
|
|
}
|
|
|
|
let o = new Derived(23, 1);
|
|
assertEquals(23, o.x);
|
|
assertInstanceof(o, Derived);
|
|
|
|
assertThrows("new Derived(42, 0)", ReferenceError);
|
|
assertThrows("new Derived(65, 2)", ReferenceError);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallReentrant() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(fun) {
|
|
this.x = fun();
|
|
}
|
|
}
|
|
class Derived extends Base {
|
|
constructor(x) {
|
|
let f = () => super(() => x)
|
|
super(f);
|
|
}
|
|
}
|
|
assertThrows("new Derived(23)", ReferenceError);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallSpreadInEval() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
class Derived extends Base {
|
|
constructor(x) {
|
|
let r = eval('super(...[x])');
|
|
assertEquals(this, r);
|
|
}
|
|
}
|
|
let d = new Derived(42);
|
|
assertSame(42, d.x);
|
|
})();
|
|
|
|
|
|
(function TestSuperCallSpreadInArrow() {
|
|
'use strict';
|
|
class Base {
|
|
constructor(x) {
|
|
this.x = x;
|
|
}
|
|
}
|
|
class Derived extends Base {
|
|
constructor(x) {
|
|
let r = (() => super(...[x]))();
|
|
assertEquals(this, r);
|
|
}
|
|
}
|
|
let d = new Derived(42);
|
|
assertSame(42, d.x);
|
|
})();
|