Skip to content

Commit 92e68f4

Browse files
committed
Make old behavior toggleable, disable outside testing for continued perf comparisons
1 parent 1d18102 commit 92e68f4

File tree

3 files changed

+33
-9
lines changed

3 files changed

+33
-9
lines changed

Herebyfile.mjs

+7-1
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ async function runDtsBundler(entrypoint, output) {
175175
* @property {boolean} [exportIsTsObject]
176176
* @property {boolean} [treeShaking]
177177
* @property {boolean} [usePublicAPI]
178+
* @property {boolean} [tsgoCompat]
178179
* @property {() => void} [onWatchRebuild]
179180
*/
180181
function createBundler(entrypoint, outfile, taskOptions = {}) {
@@ -196,6 +197,9 @@ function createBundler(entrypoint, outfile, taskOptions = {}) {
196197
treeShaking: taskOptions.treeShaking,
197198
packages: "external",
198199
logLevel: "warning",
200+
define: {
201+
__TSGO_COMPAT__: taskOptions.tsgoCompat ? "true" : "false",
202+
},
199203
// legalComments: "none", // If we add copyright headers to the source files, uncomment.
200204
};
201205

@@ -232,7 +236,8 @@ function createBundler(entrypoint, outfile, taskOptions = {}) {
232236
const require = "require";
233237
const fakeName = "Q".repeat(require.length);
234238
const fakeNameRegExp = new RegExp(fakeName, "g");
235-
options.define = { [require]: fakeName };
239+
options.define ||= {};
240+
options.define[require] = fakeName;
236241

237242
// For historical reasons, TypeScript does not set __esModule. Hack esbuild's __toCommonJS to be a noop.
238243
// We reference `__copyProps` to ensure the final bundle doesn't have any unreferenced code.
@@ -541,6 +546,7 @@ const { main: tests, watch: watchTests } = entrypointBuildTask({
541546
output: testRunner,
542547
mainDeps: [generateLibs],
543548
bundlerOptions: {
549+
tsgoCompat: true,
544550
// Ensure we never drop any dead code, which might be helpful while debugging.
545551
treeShaking: false,
546552
onWatchRebuild() {

src/compiler/checker.ts

+20-8
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ import {
8484
compareComparableValues,
8585
compareDiagnostics,
8686
comparePaths,
87+
compareValues,
8788
Comparison,
8889
CompilerOptions,
8990
ComputedPropertyName,
@@ -5394,7 +5395,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
53945395
}
53955396

53965397
function createTypeofType() {
5397-
return getUnionType(map([...typeofNEFacts.keys()].sort(), getStringLiteralType));
5398+
return getUnionType(map(__TSGO_COMPAT__ ? [...typeofNEFacts.keys()].sort() : arrayFrom(typeofNEFacts.keys()), getStringLiteralType));
53985399
}
53995400

54005401
function createTypeParameter(symbol?: Symbol) {
@@ -5420,7 +5421,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
54205421
(result || (result = [])).push(symbol);
54215422
}
54225423
});
5423-
result?.sort(compareSymbols);
5424+
sortSymbolsIfTSGoCompat(result);
54245425
return result || emptyArray;
54255426
}
54265427

@@ -17653,11 +17654,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1765317654
}
1765417655

1765517656
function containsType(types: readonly Type[], type: Type): boolean {
17656-
return binarySearch(types, type, identity, compareTypes) >= 0;
17657+
return __TSGO_COMPAT__ ? binarySearch(types, type, identity, compareTypes) >= 0 : binarySearch(types, type, getTypeId, compareValues) >= 0;
1765717658
}
1765817659

1765917660
function insertType(types: Type[], type: Type): boolean {
17660-
const index = binarySearch(types, type, identity, compareTypes);
17661+
const index = __TSGO_COMPAT__ ? binarySearch(types, type, identity, compareTypes) : binarySearch(types, type, getTypeId, compareValues);
1766117662
if (index < 0) {
1766217663
types.splice(~index, 0, type);
1766317664
return true;
@@ -17678,7 +17679,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1767817679
if (!(getObjectFlags(type) & ObjectFlags.ContainsWideningType)) includes |= TypeFlags.IncludesNonWideningType;
1767917680
}
1768017681
else {
17681-
const index = binarySearch(typeSet, type, identity, compareTypes);
17682+
const len = typeSet.length;
17683+
const index = __TSGO_COMPAT__ ? binarySearch(typeSet, type, identity, compareTypes) : (len && type.id > typeSet[len - 1].id ? ~len : binarySearch(typeSet, type, getTypeId, compareValues));
1768217684
if (index < 0) {
1768317685
typeSet.splice(~index, 0, type);
1768417686
}
@@ -34717,16 +34719,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3471734719
// So the table *contains* `x` but `x` isn't actually in scope.
3471834720
// However, resolveNameHelper will continue and call this callback again, so we'll eventually get a correct suggestion.
3471934721
if (symbol) return symbol;
34720-
let candidates = arrayFrom(symbols.values()).sort(compareSymbols);
34722+
let candidates = arrayFrom(symbols.values());
3472134723
if (symbols === globals) {
3472234724
const primitives = mapDefined(
3472334725
["string", "number", "boolean", "object", "bigint", "symbol"],
3472434726
s => symbols.has((s.charAt(0).toUpperCase() + s.slice(1)) as __String)
3472534727
? createSymbol(SymbolFlags.TypeAlias, s as __String) as Symbol
3472634728
: undefined,
3472734729
);
34728-
candidates = concatenate(candidates, primitives);
34730+
candidates = concatenate(primitives, candidates);
3472934731
}
34732+
sortSymbolsIfTSGoCompat(candidates);
3473034733
return getSpellingSuggestionForName(unescapeLeadingUnderscores(name), candidates, meaning);
3473134734
}
3473234735
function getSuggestedSymbolForNonexistentSymbol(location: Node | undefined, outerName: __String, meaning: SymbolFlags): Symbol | undefined {
@@ -34736,7 +34739,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3473634739
}
3473734740

3473834741
function getSuggestedSymbolForNonexistentModule(name: Identifier, targetModule: Symbol): Symbol | undefined {
34739-
return targetModule.exports && getSpellingSuggestionForName(idText(name), getExportsOfModuleAsArray(targetModule).sort(compareSymbols), SymbolFlags.ModuleMember); // eslint-disable-line local/no-array-mutating-method-expressions
34742+
return targetModule.exports && getSpellingSuggestionForName(idText(name), sortSymbolsIfTSGoCompat(getExportsOfModuleAsArray(targetModule)), SymbolFlags.ModuleMember);
3474034743
}
3474134744

3474234745
function getSuggestionForNonexistentIndexSignature(objectType: Type, expr: ElementAccessExpression, keyedType: Type): string | undefined {
@@ -52850,6 +52853,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
5285052853
return specifier;
5285152854
}
5285252855

52856+
function sortSymbolsIfTSGoCompat(array: Symbol[]): Symbol[];
52857+
function sortSymbolsIfTSGoCompat(array: Symbol[] | undefined): Symbol[] | undefined;
52858+
function sortSymbolsIfTSGoCompat(array: Symbol[] | undefined): Symbol[] | undefined {
52859+
if (__TSGO_COMPAT__ && array) {
52860+
return array.sort(compareSymbols);
52861+
}
52862+
return array;
52863+
}
52864+
5285352865
function compareSymbols(s1: Symbol | undefined, s2: Symbol | undefined): number {
5285452866
if (s1 === s2) return 0;
5285552867
if (s1 === undefined) return 1;

src/compiler/corePublic.ts

+6
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ export const versionMajorMinor = "5.7";
55
/** The version of the TypeScript compiler release */
66
export const version: string = `${versionMajorMinor}.0-dev`;
77

8+
declare global {
9+
var __TSGO_COMPAT__: boolean | undefined;
10+
}
11+
12+
globalThis.__TSGO_COMPAT__ ??= false;
13+
814
/**
915
* Type of objects whose values are all of the same type.
1016
* The `in` and `for-in` operators can *not* be safely used,

0 commit comments

Comments
 (0)