Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit67172e4

Browse files
Triple-slash reference type directives can override the import mode used for their resolution (#47732)
* Triple-slash reference type directives can override the import mode used for their resolutionThey now use the file's default mode by default, rather than always using commonjs. The new arguments to thereference directive look like:```ts///<reference types="pkg" resolution-mode="require" />```or```ts///<reference types="pkg" resolution-mode="import" />```* Omit redundant import modes in emitter* Add test for#47806* Add server test for triple-slash reference mode overrides* Move FileReference mode into helper* Update tests/cases/conformance/node/nodeModulesTripleSlashReferenceModeOverride3.tsCo-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>Co-authored-by: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com>
1 parent1b1530a commit67172e4

File tree

129 files changed

+3158
-102
lines changed

Some content is hidden

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

129 files changed

+3158
-102
lines changed

‎src/compiler/checker.ts‎

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -42202,19 +42202,19 @@ namespace ts {
4220242202
// this variable and functions that use it are deliberately moved here from the outer scope
4220342203
// to avoid scope pollution
4220442204
const resolvedTypeReferenceDirectives = host.getResolvedTypeReferenceDirectives();
42205-
let fileToDirective: ESMap<string, string>;
42205+
let fileToDirective: ESMap<string,[specifier:string, mode: SourceFile["impliedNodeFormat"] | undefined]>;
4220642206
if (resolvedTypeReferenceDirectives) {
4220742207
// populate reverse mapping: file path -> type reference directive that was resolved to this file
42208-
fileToDirective = new Map<string, string>();
42209-
resolvedTypeReferenceDirectives.forEach((resolvedDirective, key) => {
42208+
fileToDirective = new Map<string,[specifier:string, mode: SourceFile["impliedNodeFormat"] | undefined]>();
42209+
resolvedTypeReferenceDirectives.forEach((resolvedDirective, key, mode) => {
4221042210
if (!resolvedDirective || !resolvedDirective.resolvedFileName) {
4221142211
return;
4221242212
}
4221342213
const file = host.getSourceFile(resolvedDirective.resolvedFileName);
4221442214
if (file) {
4221542215
// Add the transitive closure of path references loaded by this file (as long as they are not)
4221642216
// part of an existing type reference.
42217-
addReferencedFilesToTypeDirective(file, key);
42217+
addReferencedFilesToTypeDirective(file, key, mode);
4221842218
}
4221942219
});
4222042220
}
@@ -42337,7 +42337,7 @@ namespace ts {
4233742337
}
4233842338

4233942339
// defined here to avoid outer scope pollution
42340-
function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression): string[] | undefined {
42340+
function getTypeReferenceDirectivesForEntityName(node: EntityNameOrEntityNameExpression):[specifier:string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined {
4234142341
// program does not have any files with type reference directives - bail out
4234242342
if (!fileToDirective) {
4234342343
return undefined;
@@ -42355,13 +42355,13 @@ namespace ts {
4235542355
}
4235642356

4235742357
// defined here to avoid outer scope pollution
42358-
function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[] | undefined {
42358+
function getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags):[specifier:string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined {
4235942359
// program does not have any files with type reference directives - bail out
4236042360
if (!fileToDirective || !isSymbolFromTypeDeclarationFile(symbol)) {
4236142361
return undefined;
4236242362
}
4236342363
// check what declarations in the symbol can contribute to the target meaning
42364-
let typeReferenceDirectives: string[] | undefined;
42364+
let typeReferenceDirectives:[specifier:string, mode: SourceFile["impliedNodeFormat"] | undefined][] | undefined;
4236542365
for (const decl of symbol.declarations!) {
4236642366
// check meaning of the local symbol to see if declaration needs to be analyzed further
4236742367
if (decl.symbol && decl.symbol.flags & meaning!) {
@@ -42412,14 +42412,14 @@ namespace ts {
4241242412
return false;
4241342413
}
4241442414

42415-
function addReferencedFilesToTypeDirective(file: SourceFile, key: string) {
42415+
function addReferencedFilesToTypeDirective(file: SourceFile, key: string, mode: SourceFile["impliedNodeFormat"] | undefined) {
4241642416
if (fileToDirective.has(file.path)) return;
42417-
fileToDirective.set(file.path, key);
42418-
for (const { fileName } of file.referencedFiles) {
42417+
fileToDirective.set(file.path,[key, mode]);
42418+
for (const { fileName, resolutionMode } of file.referencedFiles) {
4241942419
const resolvedFile = resolveTripleslashReference(fileName, file.fileName);
4242042420
const referencedFile = host.getSourceFile(resolvedFile);
4242142421
if (referencedFile) {
42422-
addReferencedFilesToTypeDirective(referencedFile, key);
42422+
addReferencedFilesToTypeDirective(referencedFile, key, resolutionMode || file.impliedNodeFormat);
4242342423
}
4242442424
}
4242542425
}

‎src/compiler/diagnosticMessages.json‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,14 @@
14121412
"category":"Error",
14131413
"code":1451
14141414
},
1415+
"Resolution modes are only supported when `moduleResolution` is `node12` or `nodenext`.": {
1416+
"category":"Error",
1417+
"code":1452
1418+
},
1419+
"`resolution-mode` should be either `require` or `import`.": {
1420+
"category":"Error",
1421+
"code":1453
1422+
},
14151423

14161424
"The 'import.meta' meta-property is not allowed in files which will build into CommonJS output.": {
14171425
"category":"Error",

‎src/compiler/emitter.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3993,8 +3993,11 @@ namespace ts {
39933993
}
39943994
for(constdirectiveoftypes){
39953995
constpos=writer.getTextPos();
3996-
writeComment(`/// <reference types="${directive.fileName}" />`);
3997-
if(bundleFileInfo)bundleFileInfo.sections.push({ pos,end:writer.getTextPos(),kind:BundleFileSectionKind.Type,data:directive.fileName});
3996+
constresolutionMode=directive.resolutionMode&&directive.resolutionMode!==currentSourceFile?.impliedNodeFormat
3997+
?`resolution-mode="${directive.resolutionMode===ModuleKind.ESNext ?"import" :"require"}"`
3998+
:"";
3999+
writeComment(`/// <reference types="${directive.fileName}"${resolutionMode}/>`);
4000+
if(bundleFileInfo)bundleFileInfo.sections.push({ pos,end:writer.getTextPos(),kind:!directive.resolutionMode ?BundleFileSectionKind.Type :directive.resolutionMode===ModuleKind.ESNext ?BundleFileSectionKind.TypeResolutionModeImport :BundleFileSectionKind.TypeResolutionModeRequire,data:directive.fileName});
39984001
writeLine();
39994002
}
40004003
for(constdirectiveoflibs){

‎src/compiler/factory/nodeFactory.ts‎

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6414,7 +6414,7 @@ namespace ts {
64146414
letprologues:UnparsedPrologue[]|undefined;
64156415
lethelpers:UnscopedEmitHelper[]|undefined;
64166416
letreferencedFiles:FileReference[]|undefined;
6417-
lettypeReferenceDirectives:string[]|undefined;
6417+
lettypeReferenceDirectives:FileReference[]|undefined;
64186418
letlibReferenceDirectives:FileReference[]|undefined;
64196419
letprependChildren:UnparsedTextLike[]|undefined;
64206420
lettexts:UnparsedSourceText[]|undefined;
@@ -6435,7 +6435,13 @@ namespace ts {
64356435
referencedFiles=append(referencedFiles,{pos:-1,end:-1,fileName:section.data});
64366436
break;
64376437
caseBundleFileSectionKind.Type:
6438-
typeReferenceDirectives=append(typeReferenceDirectives,section.data);
6438+
typeReferenceDirectives=append(typeReferenceDirectives,{pos:-1,end:-1,fileName:section.data});
6439+
break;
6440+
caseBundleFileSectionKind.TypeResolutionModeImport:
6441+
typeReferenceDirectives=append(typeReferenceDirectives,{pos:-1,end:-1,fileName:section.data,resolutionMode:ModuleKind.ESNext});
6442+
break;
6443+
caseBundleFileSectionKind.TypeResolutionModeRequire:
6444+
typeReferenceDirectives=append(typeReferenceDirectives,{pos:-1,end:-1,fileName:section.data,resolutionMode:ModuleKind.CommonJS});
64396445
break;
64406446
caseBundleFileSectionKind.Lib:
64416447
libReferenceDirectives=append(libReferenceDirectives,{pos:-1,end:-1,fileName:section.data});
@@ -6496,6 +6502,8 @@ namespace ts {
64966502
caseBundleFileSectionKind.NoDefaultLib:
64976503
caseBundleFileSectionKind.Reference:
64986504
caseBundleFileSectionKind.Type:
6505+
caseBundleFileSectionKind.TypeResolutionModeImport:
6506+
caseBundleFileSectionKind.TypeResolutionModeRequire:
64996507
caseBundleFileSectionKind.Lib:
65006508
syntheticReferences=append(syntheticReferences,setTextRange(factory.createUnparsedSyntheticReference(section),section));
65016509
break;

‎src/compiler/moduleNameResolver.ts‎

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,15 +297,15 @@ namespace ts {
297297
* This is possible in case if resolution is performed for directives specified via 'types' parameter. In this case initial path for secondary lookups
298298
* is assumed to be the same as root directory of the project.
299299
*/
300-
exportfunctionresolveTypeReferenceDirective(typeReferenceDirectiveName:string,containingFile:string|undefined,options:CompilerOptions,host:ModuleResolutionHost,redirectedReference?:ResolvedProjectReference,cache?:TypeReferenceDirectiveResolutionCache):ResolvedTypeReferenceDirectiveWithFailedLookupLocations{
300+
exportfunctionresolveTypeReferenceDirective(typeReferenceDirectiveName:string,containingFile:string|undefined,options:CompilerOptions,host:ModuleResolutionHost,redirectedReference?:ResolvedProjectReference,cache?:TypeReferenceDirectiveResolutionCache,resolutionMode?:SourceFile["impliedNodeFormat"]):ResolvedTypeReferenceDirectiveWithFailedLookupLocations{
301301
consttraceEnabled=isTraceEnabled(options,host);
302302
if(redirectedReference){
303303
options=redirectedReference.commandLine.options;
304304
}
305305

306306
constcontainingDirectory=containingFile ?getDirectoryPath(containingFile) :undefined;
307307
constperFolderCache=containingDirectory ?cache&&cache.getOrCreateCacheForDirectory(containingDirectory,redirectedReference) :undefined;
308-
letresult=perFolderCache&&perFolderCache.get(typeReferenceDirectiveName,/*mode*/undefined);
308+
letresult=perFolderCache&&perFolderCache.get(typeReferenceDirectiveName,/*mode*/resolutionMode);
309309
if(result){
310310
if(traceEnabled){
311311
trace(host,Diagnostics.Resolving_type_reference_directive_0_containing_file_1,typeReferenceDirectiveName,containingFile);
@@ -340,8 +340,19 @@ namespace ts {
340340
}
341341

342342
constfailedLookupLocations:string[]=[];
343-
constfeatures=getDefaultNodeResolutionFeatures(options);
344-
constmoduleResolutionState:ModuleResolutionState={compilerOptions:options, host, traceEnabled, failedLookupLocations,packageJsonInfoCache:cache, features,conditions:["node","require","types"]};
343+
letfeatures=getDefaultNodeResolutionFeatures(options);
344+
// Unlike `import` statements, whose mode-calculating APIs are all guaranteed to return `undefined` if we're in an un-mode-ed module resolution
345+
// setting, type references will return their target mode regardless of options because of how the parser works, so we guard against the mode being
346+
// set in a non-modal module resolution setting here. Do note that our behavior is not particularly well defined when these mode-overriding imports
347+
// are present in a non-modal project; while in theory we'd like to either ignore the mode or provide faithful modern resolution, depending on what we feel is best,
348+
// in practice, not every cache has the options available to intelligently make the choice to ignore the mode request, and it's unclear how modern "faithful modern
349+
// resolution" should be (`node12`? `nodenext`?). As such, witnessing a mode-overriding triple-slash reference in a non-modal module resolution
350+
// context should _probably_ be an error - and that should likely be handled by the `Program` (which is what we do).
351+
if(resolutionMode===ModuleKind.ESNext&&(getEmitModuleResolutionKind(options)===ModuleResolutionKind.Node12||getEmitModuleResolutionKind(options)===ModuleResolutionKind.NodeNext)){
352+
features|=NodeResolutionFeatures.EsmMode;
353+
}
354+
constconditions=features&NodeResolutionFeatures.Exports ?features&NodeResolutionFeatures.EsmMode ?["node","import","types"] :["node","require","types"] :[];
355+
constmoduleResolutionState:ModuleResolutionState={compilerOptions:options, host, traceEnabled, failedLookupLocations,packageJsonInfoCache:cache, features, conditions};
345356
letresolved=primaryLookup();
346357
letprimary=true;
347358
if(!resolved){
@@ -362,7 +373,7 @@ namespace ts {
362373
};
363374
}
364375
result={ resolvedTypeReferenceDirective, failedLookupLocations};
365-
perFolderCache?.set(typeReferenceDirectiveName,/*mode*/undefined,result);
376+
perFolderCache?.set(typeReferenceDirectiveName,/*mode*/resolutionMode,result);
366377
if(traceEnabled)traceResult(result);
367378
returnresult;
368379

@@ -733,11 +744,15 @@ namespace ts {
733744
}
734745

735746
/*@internal */
736-
exportfunctionzipToModeAwareCache<V>(file:SourceFile,keys:readonlystring[],values:readonlyV[]):ModeAwareCache<V>{
747+
exportfunctionzipToModeAwareCache<V>(file:SourceFile,keys:readonlystring[]|readonlyFileReference[],values:readonlyV[]):ModeAwareCache<V>{
737748
Debug.assert(keys.length===values.length);
738749
constmap=createModeAwareCache<V>();
739750
for(leti=0;i<keys.length;++i){
740-
map.set(keys[i],getModeForResolutionAtIndex(file,i),values[i]);
751+
constentry=keys[i];
752+
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
753+
constname=!isString(entry) ?entry.fileName.toLowerCase() :entry;
754+
constmode=!isString(entry) ?entry.resolutionMode||file.impliedNodeFormat :getModeForResolutionAtIndex(file,i);
755+
map.set(name,mode,values[i]);
741756
}
742757
returnmap;
743758
}

‎src/compiler/parser.ts‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9306,6 +9306,20 @@ namespace ts {
93069306
moduleName?:string;
93079307
}
93089308

9309+
functionparseResolutionMode(mode:string|undefined,pos:number,end:number,reportDiagnostic:PragmaDiagnosticReporter):ModuleKind.ESNext|ModuleKind.CommonJS|undefined{
9310+
if(!mode){
9311+
returnundefined;
9312+
}
9313+
if(mode==="import"){
9314+
returnModuleKind.ESNext;
9315+
}
9316+
if(mode==="require"){
9317+
returnModuleKind.CommonJS;
9318+
}
9319+
reportDiagnostic(pos,end-pos,Diagnostics.resolution_mode_should_be_either_require_or_import);
9320+
returnundefined;
9321+
}
9322+
93099323
/*@internal*/
93109324
exportfunctionprocessCommentPragmas(context:PragmaContext,sourceText:string):void{
93119325
constpragmas:PragmaPseudoMapEntry[]=[];
@@ -9351,12 +9365,13 @@ namespace ts {
93519365
consttypeReferenceDirectives=context.typeReferenceDirectives;
93529366
constlibReferenceDirectives=context.libReferenceDirectives;
93539367
forEach(toArray(entryOrList)asPragmaPseudoMap["reference"][],arg=>{
9354-
const{ types, lib, path}=arg.arguments;
9368+
const{ types, lib, path,["resolution-mode"]:res}=arg.arguments;
93559369
if(arg.arguments["no-default-lib"]){
93569370
context.hasNoDefaultLib=true;
93579371
}
93589372
elseif(types){
9359-
typeReferenceDirectives.push({pos:types.pos,end:types.end,fileName:types.value});
9373+
constparsed=parseResolutionMode(res,types.pos,types.end,reportDiagnostic);
9374+
typeReferenceDirectives.push({pos:types.pos,end:types.end,fileName:types.value, ...(parsed ?{resolutionMode:parsed} :{})});
93609375
}
93619376
elseif(lib){
93629377
libReferenceDirectives.push({pos:lib.pos,end:lib.end,fileName:lib.value});

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp