mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-11-08 08:44:37 +08:00
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.
34 lines
1.2 KiB
JavaScript
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(" "); };
|