Files
scriptc/tests/corpus/8302-class-super-method-values/lib.cjs
T
Chris Tate 478feb15cd Call the declared base method for super calls in JavaScript method values
Since 76735a8d9 (#1975), a `super.m()` call in a JavaScript class method
whose `this` is the call-site receiver reflected the base class's whole
prototype and read `m` from it. An instance's member lookup first tests
its property bag, which inherits from its class's prototype data, so once
the base's prototype was reflected, `child[k]` for a method the subclass
overrides found the base's method there: `value[name](arg)` on a subclass
instance called the base method.

While no code reads a prototype method by name, `super.m()` now calls the
declaring class's receiver-independent method value with the receiver, as
the method's [[HomeObject]] lookup answers, without reflecting the base
prototype. Programs that read prototype methods by name keep the
reflected lookup.
2026-10-25 00:26:55 -05:00

34 lines
1.2 KiB
JavaScript

"use strict";
// Subclasses whose methods call super, read and called through computed and
// literal keys, as values called with call(), and directly.
class Base {
constructor(n) { this.n = n; }
scale(k) { return this.n * k; }
label() { return "base:" + this.n; }
plain(k) { return k; }
}
class Child extends Base {
scale(k) { return super.scale(k) * 10; }
label() { return "child(" + super.label() + ")"; }
plain(k) { return k * 100; }
}
class Grandchild extends Child {
scale(k) { return super.scale(k) + 1; }
}
class Sibling extends Base {
scale(k) { return -k; }
plain(k) { return super.plain(k) + 0.5; }
}
exports.make = function (i) {
switch (i % 4) {
case 0: return new Base(i);
case 1: return new Child(i);
case 2: return new Grandchild(i);
default: return new Sibling(i);
}
};
exports.computed = function (value, name, arg) { return value[name](arg); };
exports.viaCall = function (value, name, arg) { const f = value[name]; return f.call(value, arg); };
exports.literal = function (value, arg) { return [value["scale"](arg), value["plain"](arg), value["label"]()].join(" "); };
exports.direct = function (value, arg) { return [value.scale(arg), value.plain(arg), value.label()].join(" "); };