v8/test/mjsunit/es6/classes-constructor.js
legendecas 8db991a042 [runtime] throw a realm type error when constructors are called
Each time a constructor is being called without new operator, a TypeError
is thrown. The TypeError should be the realm's one according to 10.2.1.5.b.

Refs: https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
Refs: https://github.com/tc39/ecma262/pull/2216
Bug: v8:11530
Change-Id: Iff10a78e96fb547fe2062c86b9f93a30d2a8be20
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3056830
Reviewed-by: Marja Hölttä <marja@chromium.org>
Commit-Queue: Marja Hölttä <marja@chromium.org>
Cr-Commit-Position: refs/heads/master@{#76002}
2021-07-29 14:34:22 +00:00

133 lines
3.7 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
(function TestDefaultConstructorNoCrash() {
// Regression test for https://code.google.com/p/v8/issues/detail?id=3661
class C {}
assertThrows(function () {C();}, TypeError);
assertThrows(function () {C(1);}, TypeError);
assertTrue(new C() instanceof C);
assertTrue(new C(1) instanceof C);
})();
(function TestConstructorCall(){
var realmIndex = Realm.create();
var otherTypeError = Realm.eval(realmIndex, "TypeError");
var A = Realm.eval(realmIndex, '"use strict"; class A {}; A');
var instance = new A();
var constructor = instance.constructor;
var otherTypeError = Realm.eval(realmIndex, 'TypeError');
if (otherTypeError === TypeError) {
throw Error('Should not happen!');
}
// https://tc39.es/ecma262/#sec-ecmascript-function-objects-call-thisargument-argumentslist
// 10.2.1 [[Call]] throws a TypeError created in callee context with F's
// associated Realm Record when the called function is a classConstructor
assertThrows(function() { Realm.eval(realmIndex, "A()") }, otherTypeError);
assertThrows(function() { instance.constructor() }, otherTypeError);
assertThrows(function() { A() }, otherTypeError);
// ES6 9.3.1 call() first activates the callee context before invoking the
// method. The TypeError from the constructor is thus thrown in the other
// Realm.
assertThrows(function() { Realm.eval(realmIndex, "A.call()") },
otherTypeError);
assertThrows(function() { constructor.call() }, otherTypeError);
assertThrows(function() { A.call() }, otherTypeError);
})();
(function TestConstructorCallOptimized() {
class A { };
function invoke_constructor() { A() }
function call_constructor() { A.call() }
function apply_constructor() { A.apply() }
%PrepareFunctionForOptimization(invoke_constructor);
%PrepareFunctionForOptimization(call_constructor);
%PrepareFunctionForOptimization(apply_constructor);
for (var i=0; i<3; i++) {
assertThrows(invoke_constructor);
assertThrows(call_constructor);
assertThrows(apply_constructor);
}
// Make sure we still check for class constructors when calling optimized
// code.
%OptimizeFunctionOnNextCall(invoke_constructor);
assertThrows(invoke_constructor);
%OptimizeFunctionOnNextCall(call_constructor);
assertThrows(call_constructor);
%OptimizeFunctionOnNextCall(apply_constructor);
assertThrows(apply_constructor);
})();
(function TestDefaultConstructor() {
var calls = 0;
class Base {
constructor() {
calls++;
}
}
class Derived extends Base {}
var object = new Derived;
assertEquals(1, calls);
calls = 0;
assertThrows(function() { Derived(); }, TypeError);
assertEquals(0, calls);
})();
(function TestDefaultConstructorArguments() {
var args, self;
class Base {
constructor() {
self = this;
args = arguments;
}
}
class Derived extends Base {}
new Derived;
assertEquals(0, args.length);
new Derived(0, 1, 2);
assertEquals(3, args.length);
assertTrue(self instanceof Derived);
var arr = new Array(100);
var obj = {};
assertThrows(function() {Derived.apply(obj, arr);}, TypeError);
})();
(function TestDefaultConstructorArguments2() {
var args;
class Base {
constructor(x, y) {
args = arguments;
}
}
class Derived extends Base {}
new Derived;
assertEquals(0, args.length);
new Derived(1);
assertEquals(1, args.length);
assertEquals(1, args[0]);
new Derived(1, 2, 3);
assertEquals(3, args.length);
assertEquals(1, args[0]);
assertEquals(2, args[1]);
assertEquals(3, args[2]);
})();