v8/test/mjsunit/harmony/private-brand-nested-super.js
Joyee Cheung 1e6294d3c3 [class] initialize brand after super() in nested arrow function
Handle the case of nested super() by checking if the class scope
contains a private brand. In this case the ContextScope chain
is different from the actual context chain so this added back
the AddPrivateBrand() runtime function but with the additional
step of walking the context chain to get the correct class
context that will be stored as the value of the brand property
for the debugger.

Bug: v8:12354
Change-Id: Ieeb9b9d6372bfbb1a39c4c2dc9e9848e9109f02a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3275137
Reviewed-by: Shu-yu Guo <syg@chromium.org>
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Marja Hölttä <marja@chromium.org>
Commit-Queue: Joyee Cheung <joyee@igalia.com>
Cr-Commit-Position: refs/heads/main@{#79032}
2022-02-10 14:05:48 +00:00

132 lines
2.6 KiB
JavaScript

// Copyright 2022 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.
"use strict";
// Tests that brand initialization works when super() is called in a nested
// arrow function or in eval().
// IIFE nested super().
{
class A extends class {} {
#method() { }
constructor() {
(() => super())();
}
test() { this.#method(); }
check() { return #method in this; }
}
const a = new A();
a.test();
assertTrue(a.check());
}
// Non-IIFE nested super().
{
class A extends class {} {
#method() { }
constructor() {
const callSuper = () => super();
callSuper();
}
test() { this.#method(); }
check() { return #method in this; }
}
const a = new A();
a.test();
assertTrue(a.check());
}
// Eval'ed nested super().
{
class A extends class {} {
#method() { }
constructor(str) {
eval(str);
}
test() { this.#method(); }
check() { return #method in this; }
}
const a = new A("super()");
a.test();
assertTrue(a.check());
}
// Test that private brands don't leak into class in heritage
// position with the class scope optimized away.
{
class A extends class B extends class {} {
constructor() { (() => super())(); }
static get B() { return B; }
} {
#method() {}
static run(obj) { obj.#method(); }
static get B() { return super.B; }
}
const b = new (A.B)();
assertThrows(() => A.run(b));
}
{
class C {
#c() { }
#field = 1;
static A = class A extends class B extends Object {
constructor() {
(() => super())();
}
field(obj) { return obj.#field; }
} {};
static run(obj) { obj.#c(); }
}
const a = new (C.A);
assertThrows(() => C.run(a));
const c = new C;
assertEquals(a.field(c), 1);
}
{
class C {
#c() { }
#field = 1;
static A = class A extends class B extends Object {
constructor() {
(() => {
eval("super()");
})();
}
field(obj) { return obj.#field; }
} {};
static run(obj) { obj.#c(); }
}
const a = new (C.A);
assertThrows(() => C.run(a));
const c = new C;
assertEquals(a.field(c), 1);
}
{
class C {
#c() { }
#field = 1;
static A = class A extends class B extends Object {
constructor() {
(() => {
{
super();
}
})();
}
field(obj) { return obj.#field; }
} {};
static run(obj) { obj.#c(); }
}
const a = new (C.A);
assertThrows(() => C.run(a));
const c = new C;
assertEquals(a.field(c), 1);
}