Skip to content

Commit ec2bd4e

Browse files
authored
perf: replace String and Array indexOf method calls with includes method call (microsoft#55482)
1 parent c3c5abb commit ec2bd4e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+98
-124
lines changed

scripts/errorCheck.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ async function checkSourceFiles() {
7171
let count = 0;
7272
console.log("== List of errors not used in source ==");
7373
for (const errName of errorNames) {
74-
if (allSrc.indexOf(errName) < 0) {
74+
if (!allSrc.includes(errName)) {
7575
console.log(errName);
7676
count++;
7777
}

scripts/eslint/rules/argument-trivia.cjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ module.exports = createRule({
157157
}
158158
}
159159

160-
const hasNewLine = sourceCodeText.slice(commentRangeEnd, argRangeStart).indexOf("\n") >= 0;
160+
const hasNewLine = sourceCodeText.slice(commentRangeEnd, argRangeStart).includes("\n");
161161
if (argRangeStart !== commentRangeEnd + 1 && !hasNewLine) {
162162
// TODO(jakebailey): range should be whitespace
163163
context.report({

scripts/update-experimental-branches.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ async function main() {
8888
const mergeTree = runSequence([
8989
["git", ["merge-tree", mergeBase.trim(), branch, "experimental"]],
9090
]);
91-
if (mergeTree.indexOf(`===${"="}===`) >= 0) { // 7 equals is the center of the merge conflict marker
91+
if (mergeTree.includes(`===${"="}===`)) { // 7 equals is the center of the merge conflict marker
9292
throw new Error(`Merge conflict detected involving PR ${branch} with other experiment`);
9393
}
9494
// Merge (always producing a merge commit)

src/cancellationToken/cancellationToken.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ function createCancellationToken(args: string[]): ServerCancellationToken {
3939
// in this case pipe name will be build dynamically as <cancellationPipeName><request_seq>.
4040
if (cancellationPipeName.charAt(cancellationPipeName.length - 1) === "*") {
4141
const namePrefix = cancellationPipeName.slice(0, -1);
42-
if (namePrefix.length === 0 || namePrefix.indexOf("*") >= 0) {
42+
if (namePrefix.length === 0 || namePrefix.includes("*")) {
4343
throw new Error("Invalid name for template cancellation pipe: it should have length greater than 2 characters and contain only one '*'.");
4444
}
4545
let perRequestPipeName: string | undefined;

src/compiler/checker.ts

+6-7
Original file line numberDiff line numberDiff line change
@@ -964,7 +964,6 @@ import {
964964
SpreadElement,
965965
startsWith,
966966
Statement,
967-
stringContains,
968967
StringLiteral,
969968
StringLiteralLike,
970969
StringLiteralType,
@@ -7908,14 +7907,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
79087907
if (!specifier) {
79097908
specifier = getSpecifierForModuleSymbol(chain[0], context);
79107909
}
7911-
if (!(context.flags & NodeBuilderFlags.AllowNodeModulesRelativePaths) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic && specifier.indexOf("/node_modules/") >= 0) {
7910+
if (!(context.flags & NodeBuilderFlags.AllowNodeModulesRelativePaths) && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Classic && specifier.includes("/node_modules/")) {
79127911
const oldSpecifier = specifier;
79137912
if (getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(compilerOptions) === ModuleResolutionKind.NodeNext) {
79147913
// We might be able to write a portable import type using a mode override; try specifier generation again, but with a different mode set
79157914
const swappedMode = contextFile?.impliedNodeFormat === ModuleKind.ESNext ? ModuleKind.CommonJS : ModuleKind.ESNext;
79167915
specifier = getSpecifierForModuleSymbol(chain[0], context, swappedMode);
79177916

7918-
if (specifier.indexOf("/node_modules/") >= 0) {
7917+
if (specifier.includes("/node_modules/")) {
79197918
// Still unreachable :(
79207919
specifier = oldSpecifier;
79217920
}
@@ -8661,7 +8660,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
86618660
if (group.length > 1) {
86628661
// remove group members from statements and then merge group members and add back to statements
86638662
statements = [
8664-
...filter(statements, s => group.indexOf(s as ExportDeclaration) === -1),
8663+
...filter(statements, s => !group.includes(s as ExportDeclaration)),
86658664
factory.createExportDeclaration(
86668665
/*modifiers*/ undefined,
86678666
/*isTypeOnly*/ false,
@@ -24250,7 +24249,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2425024249
const originalKeywordKind = identifierToKeywordKind(param.name);
2425124250
if (
2425224251
(isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) &&
24253-
param.parent.parameters.indexOf(param) > -1 &&
24252+
param.parent.parameters.includes(param) &&
2425424253
(resolveName(param, param.name.escapedText, SymbolFlags.Type, /*nameNotFoundMessage*/ undefined, param.name.escapedText, /*isUse*/ true) ||
2425524254
originalKeywordKind && isTypeNodeKind(originalKeywordKind))
2425624255
) {
@@ -30962,7 +30961,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3096230961
}
3096330962

3096430963
function isHyphenatedJsxName(name: string | __String) {
30965-
return stringContains(name as string, "-");
30964+
return (name as string).includes("-");
3096630965
}
3096730966

3096830967
/**
@@ -49648,7 +49647,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4964849647
// Realism (size) checking
4964949648
// We should test against `getTextOfNode(node)` rather than `node.text`, because `node.text` for large numeric literals can contain "."
4965049649
// e.g. `node.text` for numeric literal `1100000000000000000000` is `1.1e21`.
49651-
const isFractional = getTextOfNode(node).indexOf(".") !== -1;
49650+
const isFractional = getTextOfNode(node).includes(".");
4965249651
const isScientific = node.numericLiteralFlags & TokenFlags.Scientific;
4965349652

4965449653
// Scientific notation (e.g. 2e54 and 1e00000000010) can't be converted to bigint

src/compiler/commandLineParser.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ import {
104104
returnTrue,
105105
ScriptTarget,
106106
startsWith,
107-
stringContains,
108107
StringLiteral,
109108
SyntaxKind,
110109
sys,
@@ -1710,7 +1709,7 @@ export function parseListTypeOption(opt: CommandLineOptionOfListType, value = ""
17101709
if (startsWith(value, "-")) {
17111710
return undefined;
17121711
}
1713-
if (opt.type === "listOrElement" && !stringContains(value, ",")) {
1712+
if (opt.type === "listOrElement" && !value.includes(",")) {
17141713
return validateJsonOptionValue(opt, value, errors);
17151714
}
17161715
if (value === "") {
@@ -3078,7 +3077,7 @@ function parseConfig(
30783077
basePath = normalizeSlashes(basePath);
30793078
const resolvedPath = getNormalizedAbsolutePath(configFileName || "", basePath);
30803079

3081-
if (resolutionStack.indexOf(resolvedPath) >= 0) {
3080+
if (resolutionStack.includes(resolvedPath)) {
30823081
errors.push(createCompilerDiagnostic(Diagnostics.Circularity_detected_while_resolving_configuration_Colon_0, [...resolutionStack, resolvedPath].join(" -> ")));
30833082
return { raw: json || convertToObject(sourceFile!, errors) };
30843083
}

src/compiler/core.ts

-5
Original file line numberDiff line numberDiff line change
@@ -2484,11 +2484,6 @@ export function tryRemoveSuffix(str: string, suffix: string): string | undefined
24842484
return endsWith(str, suffix) ? str.slice(0, str.length - suffix.length) : undefined;
24852485
}
24862486

2487-
/** @internal */
2488-
export function stringContains(str: string, substring: string): boolean {
2489-
return str.indexOf(substring) !== -1;
2490-
}
2491-
24922487
/**
24932488
* Takes a string like "jquery-min.4.2.3" and returns "jquery"
24942489
*

src/compiler/emitter.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,6 @@ import {
407407
SpreadElement,
408408
stableSort,
409409
Statement,
410-
stringContains,
411410
StringLiteral,
412411
supportedJSExtensionsFlat,
413412
SwitchStatement,
@@ -3065,9 +3064,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri
30653064
// If the number will be printed verbatim and it doesn't already contain a dot or an exponent indicator, add one
30663065
// if the expression doesn't have any comments that will be emitted.
30673066
return !(expression.numericLiteralFlags & TokenFlags.WithSpecifier)
3068-
&& !stringContains(text, tokenToString(SyntaxKind.DotToken)!)
3069-
&& !stringContains(text, String.fromCharCode(CharacterCodes.E))
3070-
&& !stringContains(text, String.fromCharCode(CharacterCodes.e));
3067+
&& !text.includes(tokenToString(SyntaxKind.DotToken)!)
3068+
&& !text.includes(String.fromCharCode(CharacterCodes.E))
3069+
&& !text.includes(String.fromCharCode(CharacterCodes.e));
30713070
}
30723071
else if (isAccessExpression(expression)) {
30733072
// check if constant enum value is a non-negative integer

src/compiler/moduleNameResolver.ts

+14-15
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,6 @@ import {
100100
sort,
101101
SourceFile,
102102
startsWith,
103-
stringContains,
104103
supportedDeclarationExtensions,
105104
supportedJSExtensionsFlat,
106105
supportedTSImplementationExtensions,
@@ -1808,7 +1807,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa
18081807
&& features & NodeResolutionFeatures.Exports
18091808
&& !isExternalModuleNameRelative(moduleName)
18101809
&& !extensionIsOk(Extensions.TypeScript | Extensions.Declaration, result.value.resolved.extension)
1811-
&& conditions.indexOf("import") > -1
1810+
&& conditions.includes("import")
18121811
) {
18131812
traceIfEnabled(state, Diagnostics.Resolution_of_non_relative_name_failed_trying_with_modern_Node_resolution_features_disabled_to_see_if_npm_library_needs_configuration_update);
18141813
const diagnosticState = {
@@ -1849,7 +1848,7 @@ function nodeModuleNameResolverWorker(features: NodeResolutionFeatures, moduleNa
18491848
resolved = loadModuleFromSelfNameReference(extensions, moduleName, containingDirectory, state, cache, redirectedReference);
18501849
}
18511850
if (!resolved) {
1852-
if (moduleName.indexOf(":") > -1) {
1851+
if (moduleName.includes(":")) {
18531852
if (traceEnabled) {
18541853
trace(host, Diagnostics.Skipping_module_0_that_looks_like_an_absolute_URI_target_file_types_Colon_1, moduleName, formatExtensions(extensions));
18551854
}
@@ -1944,7 +1943,7 @@ function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string,
19441943
export const nodeModulesPathPart = "/node_modules/";
19451944
/** @internal */
19461945
export function pathContainsNodeModules(path: string): boolean {
1947-
return stringContains(path, nodeModulesPathPart);
1946+
return path.includes(nodeModulesPathPart);
19481947
}
19491948

19501949
/**
@@ -2006,7 +2005,7 @@ function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecor
20062005

20072006
function loadModuleFromFileNoImplicitExtensions(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined {
20082007
const filename = getBaseFileName(candidate);
2009-
if (filename.indexOf(".") === -1) {
2008+
if (!filename.includes(".")) {
20102009
return undefined; // extensionless import, no lookups performed, since we don't support extensionless files
20112010
}
20122011
let extensionless = removeFileExtension(candidate);
@@ -2223,7 +2222,7 @@ function loadEntrypointsFromExportMap(
22232222

22242223
function loadEntrypointsFromTargetExports(target: unknown): boolean | undefined {
22252224
if (typeof target === "string" && startsWith(target, "./")) {
2226-
if (target.indexOf("*") >= 0 && state.host.readDirectory) {
2225+
if (target.includes("*") && state.host.readDirectory) {
22272226
if (target.indexOf("*") !== target.lastIndexOf("*")) {
22282227
return false;
22292228
}
@@ -2243,7 +2242,7 @@ function loadEntrypointsFromExportMap(
22432242
}
22442243
else {
22452244
const partsAfterFirst = getPathComponents(target).slice(2);
2246-
if (partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 || partsAfterFirst.indexOf("node_modules") >= 0) {
2245+
if (partsAfterFirst.includes("..") || partsAfterFirst.includes(".") || partsAfterFirst.includes("node_modules")) {
22472246
return false;
22482247
}
22492248
const resolvedTarget = combinePaths(scope.packageDirectory, target);
@@ -2609,11 +2608,11 @@ export function comparePatternKeys(a: string, b: string) {
26092608
function loadModuleFromImportsOrExports(extensions: Extensions, state: ModuleResolutionState, cache: ModuleResolutionCache | undefined, redirectedReference: ResolvedProjectReference | undefined, moduleName: string, lookupTable: object, scope: PackageJsonInfo, isImports: boolean): SearchResult<Resolved> | undefined {
26102609
const loadModuleFromTargetImportOrExport = getLoadModuleFromTargetImportOrExport(extensions, state, cache, redirectedReference, moduleName, scope, isImports);
26112610

2612-
if (!endsWith(moduleName, directorySeparator) && moduleName.indexOf("*") === -1 && hasProperty(lookupTable, moduleName)) {
2611+
if (!endsWith(moduleName, directorySeparator) && !moduleName.includes("*") && hasProperty(lookupTable, moduleName)) {
26132612
const target = (lookupTable as { [idx: string]: unknown; })[moduleName];
26142613
return loadModuleFromTargetImportOrExport(target, /*subpath*/ "", /*pattern*/ false, moduleName);
26152614
}
2616-
const expandingKeys = sort(filter(getOwnKeys(lookupTable as MapLike<unknown>), k => k.indexOf("*") !== -1 || endsWith(k, "/")), comparePatternKeys);
2615+
const expandingKeys = sort(filter(getOwnKeys(lookupTable as MapLike<unknown>), k => k.includes("*") || endsWith(k, "/")), comparePatternKeys);
26172616
for (const potentialTarget of expandingKeys) {
26182617
if (state.features & NodeResolutionFeatures.ExportsPatternTrailers && matchesPatternWithTrailer(potentialTarget, moduleName)) {
26192618
const target = (lookupTable as { [idx: string]: unknown; })[potentialTarget];
@@ -2677,7 +2676,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
26772676
}
26782677
const parts = pathIsRelative(target) ? getPathComponents(target).slice(1) : getPathComponents(target);
26792678
const partsAfterFirst = parts.slice(1);
2680-
if (partsAfterFirst.indexOf("..") >= 0 || partsAfterFirst.indexOf(".") >= 0 || partsAfterFirst.indexOf("node_modules") >= 0) {
2679+
if (partsAfterFirst.includes("..") || partsAfterFirst.includes(".") || partsAfterFirst.includes("node_modules")) {
26812680
if (state.traceEnabled) {
26822681
trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName);
26832682
}
@@ -2687,7 +2686,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
26872686
// TODO: Assert that `resolvedTarget` is actually within the package directory? That's what the spec says.... but I'm not sure we need
26882687
// to be in the business of validating everyone's import and export map correctness.
26892688
const subpathParts = getPathComponents(subpath);
2690-
if (subpathParts.indexOf("..") >= 0 || subpathParts.indexOf(".") >= 0 || subpathParts.indexOf("node_modules") >= 0) {
2689+
if (subpathParts.includes("..") || subpathParts.includes(".") || subpathParts.includes("node_modules")) {
26912690
if (state.traceEnabled) {
26922691
trace(state.host, Diagnostics.package_json_scope_0_has_invalid_type_for_target_of_specifier_1, scope.packageDirectory, moduleName);
26932692
}
@@ -2706,7 +2705,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
27062705
if (!Array.isArray(target)) {
27072706
traceIfEnabled(state, Diagnostics.Entering_conditional_exports);
27082707
for (const condition of getOwnKeys(target as MapLike<unknown>)) {
2709-
if (condition === "default" || state.conditions.indexOf(condition) >= 0 || isApplicableVersionedTypesKey(state.conditions, condition)) {
2708+
if (condition === "default" || state.conditions.includes(condition) || isApplicableVersionedTypesKey(state.conditions, condition)) {
27102709
traceIfEnabled(state, Diagnostics.Matched_0_condition_1, isImports ? "imports" : "exports", condition);
27112710
const subTarget = (target as MapLike<unknown>)[condition];
27122711
const result = loadModuleFromTargetImportOrExport(subTarget, subpath, pattern, key);
@@ -2772,7 +2771,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
27722771
if (
27732772
!state.isConfigLookup
27742773
&& (state.compilerOptions.declarationDir || state.compilerOptions.outDir)
2775-
&& finalPath.indexOf("/node_modules/") === -1
2774+
&& !finalPath.includes("/node_modules/")
27762775
&& (state.compilerOptions.configFile ? containsPath(scope.packageDirectory, toAbsolutePath(state.compilerOptions.configFile.fileName), !useCaseSensitiveFileNames(state)) : true)
27772776
) {
27782777
// So that all means we'll only try these guesses for files outside `node_modules` in a directory where the `package.json` and `tsconfig.json` are siblings.
@@ -2876,7 +2875,7 @@ function getLoadModuleFromTargetImportOrExport(extensions: Extensions, state: Mo
28762875

28772876
/** @internal */
28782877
export function isApplicableVersionedTypesKey(conditions: readonly string[], key: string) {
2879-
if (conditions.indexOf("types") === -1) return false; // only apply versioned types conditions if the types condition is applied
2878+
if (!conditions.includes("types")) return false; // only apply versioned types conditions if the types condition is applied
28802879
if (!startsWith(key, "types@")) return false;
28812880
const range = VersionRange.tryParse(key.substring("types@".length));
28822881
if (!range) return false;
@@ -3099,7 +3098,7 @@ export function getPackageNameFromTypesPackageName(mangledName: string): string
30993098

31003099
/** @internal */
31013100
export function unmangleScopedPackageName(typesPackageName: string): string {
3102-
return stringContains(typesPackageName, mangledScopedPackageSeparator) ?
3101+
return typesPackageName.includes(mangledScopedPackageSeparator) ?
31033102
"@" + typesPackageName.replace(mangledScopedPackageSeparator, directorySeparator) :
31043103
typesPackageName;
31053104
}

0 commit comments

Comments
 (0)