1e6294d3c3
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}
132 lines
2.6 KiB
JavaScript
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);
|
|
}
|