text: // 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: --harmony-classes
  
  'use strict';
  (function TestArgumentsAccess() {
    class Base {
      constructor() {
        assertEquals(2, arguments.length);
        assertEquals(1, arguments[0]);
        assertEquals(2, arguments[1]);
      }
    }
  
    let b = new Base(1,2);
  
    class Subclass extends Base {
      constructor() {
        assertEquals(2, arguments.length);
        assertEquals(3, arguments[0]);
        assertEquals(4, arguments[1]);
        super(1,2);
      }
    }
  
    let s = new Subclass(3,4);
    assertEquals(0, Subclass.length);
  
    class Subclass2 extends Base {
      constructor(x,y) {
        assertEquals(2, arguments.length);
        assertEquals(3, arguments[0]);
        assertEquals(4, arguments[1]);
        super(1,2);
      }
    }
  
    let s2 = new Subclass2(3,4);
    assertEquals(2, Subclass2.length);
  }());
  
  (function TestThisAccessRestriction() {
    class Base {
      constructor(a, b) {
        let o = new Object();
        o.prp = a + b;
        return o;
      }
    }
  
    class Subclass extends Base {
      constructor(a, b) {
        var exn;
        try {
          this.prp1 = 3;
        } catch (e) {
          exn = e;
        }
        assertTrue(exn instanceof ReferenceError);
        super(a, b);
        assertSame(a + b, this.prp);
        assertSame(undefined, this.prp1);
        assertFalse(this.hasOwnProperty("prp1"));
        return this;
      }
    }
  
    let b = new Base(1, 2);
    assertSame(3, b.prp);
  
  
    let s = new Subclass(2, -1);
    assertSame(1, s.prp);
    assertSame(undefined, s.prp1);
    assertFalse(s.hasOwnProperty("prp1"));
  
    class Subclass2 extends Base {
      constructor(x) {
        super(1,2);
  
        if (x < 0) return;
  
        let called = false;
        function tmp() { called = true; return 3; }
        var exn = null;
        try {
          super(tmp(),4);
        } catch (e) { exn = e; }
        assertTrue(exn instanceof ReferenceError);
        assertTrue(called);
      }
    }
  
    var s2 = new Subclass2(1);
    assertSame(3, s2.prp);
  
    var s3 = new Subclass2(-1);
    assertSame(3, s3.prp);
  
    assertThrows(function() { Subclass.call(new Object(), 1, 2); }, TypeError);
    assertThrows(function() { Base.call(new Object(), 1, 2); }, TypeError);
  
    class BadSubclass extends Base {
      constructor() {}
    }
  
    assertThrows(function() { new BadSubclass(); }, ReferenceError);
  }());
  
  (function TestThisCheckOrdering() {
    let baseCalled = 0;
    class Base {
      constructor() { baseCalled++ }
    }
  
    let fCalled = 0;
    function f() { fCalled++; return 3; }
  
    class Subclass1 extends Base {
      constructor() {
        baseCalled = 0;
        super();
        assertEquals(1, baseCalled);
        let obj = this;
  
        let exn = null;
        baseCalled = 0;
        fCalled = 0;
        try {
          super(f());
        } catch (e) { exn = e; }
        assertTrue(exn instanceof ReferenceError);
        assertEquals(1, fCalled);
        assertEquals(1, baseCalled);
        assertSame(obj, this);
  
        exn = null;
        baseCalled = 0;
        fCalled = 0;
        try {
          super(super(), f());
        } catch (e) { exn = e; }
        assertTrue(exn instanceof ReferenceError);
        assertEquals(0, fCalled);
        assertEquals(1, baseCalled);
        assertSame(obj, this);
  
        exn = null;
        baseCalled = 0;
        fCalled = 0;
        try {
          super(f(), super());
        } catch (e) { exn = e; }
        assertTrue(exn instanceof ReferenceError);
        assertEquals(1, fCalled);
        assertEquals(1, baseCalled);
        assertSame(obj, this);
      }
    }
  
    new Subclass1();
  }());
  
  
  (function TestPrototypeWiring() {
    class Base {
      constructor(x) {
        this.foobar = x;
      }
    }
  
    class Subclass extends Base {
      constructor(x) {
        super(x);
      }
    }
  
    let s = new Subclass(1);
    assertSame(1, s.foobar);
    assertSame(Subclass.prototype, s.__proto__);
  
    let s1 = new Subclass(1, 2);
    assertSame(1, s1.foobar);
    assertTrue(s1.__proto__ === Subclass.prototype);
  
    let s2 = new Subclass();
    assertSame(undefined, s2.foobar);
    assertSame(Subclass.prototype, s2.__proto__);
    assertThrows(function() { Subclass(1); }, TypeError);
    assertThrows(function() { Subclass(1,2,3,4); }, TypeError);
  
    class Subclass2 extends Subclass {
      constructor() {
        super(5, 6, 7);
      }
    }
  
    let ss2 = new Subclass2();
    assertSame(5, ss2.foobar);
    assertSame(Subclass2.prototype, ss2.__proto__);
  
    class Subclass3 extends Base {
      constructor(x,y) {
        super(x + y);
      }
    }
  
    let ss3 = new Subclass3(27,42-27);
    assertSame(42, ss3.foobar);
    assertSame(Subclass3.prototype, ss3.__proto__);
  }());
  
  (function TestSublclassingBuiltins() {
    class ExtendedUint8Array extends Uint8Array {
      constructor() {
        super(10);
        this[0] = 255;
        this[1] = 0xFFA;
      }
    }
  
    var eua = new ExtendedUint8Array();
    assertEquals(10, eua.length);
    assertEquals(10, eua.byteLength);
    assertEquals(0xFF, eua[0]);
    assertEquals(0xFA, eua[1]);
    assertSame(ExtendedUint8Array.prototype, eua.__proto__);
    assertEquals("[object Uint8Array]", Object.prototype.toString.call(eua));
  }());
  
  (function TestSubclassingNull() {
    let N = null;
  
    class Foo extends N {
      constructor(x,y) {
        assertSame(1, x);
        assertSame(2, y);
        return {};
      }
    }
  
    new Foo(1,2);
  }());
  
  (function TestSubclassBinding() {
    class Base {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    }
  
    let obj = {};
    class Subclass extends Base {
      constructor(x,y) {
        super(x,y);
        assertTrue(this !== obj);
      }
    }
  
    let f = Subclass.bind(obj);
    assertThrows(function () { f(1, 2); }, TypeError);
    let s = new f(1, 2);
    assertSame(1, s.x);
    assertSame(2, s.y);
    assertSame(Subclass.prototype, s.__proto__);
  
    let s1 = new f(1);
    assertSame(1, s1.x);
    assertSame(undefined, s1.y);
    assertSame(Subclass.prototype, s1.__proto__);
  
    let g = Subclass.bind(obj, 1);
    assertThrows(function () { g(8); }, TypeError);
    let s2 = new g(8);
    assertSame(1, s2.x);
    assertSame(8, s2.y);
    assertSame(Subclass.prototype, s.__proto__);
  }());
  
  
  (function TestDefaultConstructor() {
    class Base1 { }
    assertThrows(function() { Base1(); }, TypeError);
  
    class Subclass1 extends Base1 { }
  
    assertThrows(function() { Subclass1(); }, TypeError);
  
    let s1 = new Subclass1();
    assertSame(s1.__proto__, Subclass1.prototype);
  
    class Base2 {
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }
    }
  
    class Subclass2 extends Base2 {};
  
    let s2 = new Subclass2(1, 2);
  
    assertSame(s2.__proto__, Subclass2.prototype);
    assertSame(1, s2.x);
    assertSame(2, s2.y);
  
    let f = Subclass2.bind({}, 3, 4);
    let s2prime = new f();
    assertSame(s2prime.__proto__, Subclass2.prototype);
    assertSame(3, s2prime.x);
    assertSame(4, s2prime.y);
  
    let obj = {};
    class Base3 {
      constructor() {
        return obj;
      }
    }
  
    class Subclass3 extends Base3 {};
  
    let s3 = new Subclass3();
    assertSame(obj, s3);
  
    class ExtendedUint8Array extends Uint8Array { }
  
    var eua = new ExtendedUint8Array(10);
    assertEquals(10, eua.length);
    assertEquals(10, eua.byteLength);
    eua[0] = 0xFF;
    eua[1] = 0xFFA;
    assertEquals(0xFF, eua[0]);
    assertEquals(0xFA, eua[1]);
    assertSame(ExtendedUint8Array.prototype, eua.__proto__);
    assertEquals("[object Uint8Array]", Object.prototype.toString.call(eua));
  }());
  