mirror of
https://github.com/vercel-labs/scriptc.git
synced 2026-10-29 07:04:09 +08:00
Test runtime classes' dispatch branches before their subclasses' (#1747)
This commit is contained in:
@@ -407,9 +407,27 @@ function withTypedReceiver(value: IrExpr, receiver: IrExpr): IrExpr {
|
||||
});
|
||||
}
|
||||
|
||||
/** Re-adds the entries of `set` after the first `from` sorted. */
|
||||
function sortAdded(set: Set<string>, from: number): void {
|
||||
const added = [...set].slice(from).sort();
|
||||
/** Re-adds the classes of `set` after the first `from` in a fixed order:
|
||||
* the program's classes by name, then the classes the runtime implements by
|
||||
* name. The dispatch helpers add each class's branch in front of the
|
||||
* earlier ones, so a runtime class's branch, which answers its methods for
|
||||
* instances of the program's subclasses too, is tested before the
|
||||
* subclasses' own branches. */
|
||||
function sortAdded(lowerer: Lowerer, set: Set<string>, from: number): void {
|
||||
const runtime = (name: string): boolean => {
|
||||
const info = lowerer.classes.get(name);
|
||||
return !!(
|
||||
info &&
|
||||
(info.def.runtime || info.builtinEmitter || info.builtinStream || info.builtinError)
|
||||
);
|
||||
};
|
||||
const added = [...set]
|
||||
.slice(from)
|
||||
.sort(
|
||||
(left, right) =>
|
||||
Number(runtime(left)) - Number(runtime(right)) ||
|
||||
(left < right ? -1 : left > right ? 1 : 0),
|
||||
);
|
||||
for (const name of added) set.delete(name);
|
||||
for (const name of added) set.add(name);
|
||||
}
|
||||
@@ -932,10 +950,10 @@ export class ClassDynamicDispatch {
|
||||
return true;
|
||||
},
|
||||
});
|
||||
// The classes this pass found join the tables by name, not in the order
|
||||
// the scan met them.
|
||||
sortAdded(this.boxed, boxedBefore);
|
||||
sortAdded(this.boxedConstructors, boxedConstructorsBefore);
|
||||
// The classes this pass found join the tables in a fixed order, not in
|
||||
// the order the scan met them.
|
||||
sortAdded(lowerer, this.boxed, boxedBefore);
|
||||
sortAdded(lowerer, this.boxedConstructors, boxedConstructorsBefore);
|
||||
changed = this.caughtDispatch.dynamicPayloads(lowerer, caughtSites, this.boxed) || changed;
|
||||
if (this.boxed.size === 0 && rewrite.size === 0) return changed;
|
||||
const converting = this.convertingHints(lowerer);
|
||||
|
||||
Reference in New Issue
Block a user