When reparsing top level await dont set original node for the new source file (#56439)

This commit is contained in:
Sheetal Nandi 2023-11-21 13:35:49 -08:00 committed by GitHub
parent 2c0c128e98
commit 13c9b16b2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 201 additions and 22 deletions

View File

@ -133,6 +133,7 @@ import {
hasSyntacticModifier,
HeritageClause,
Identifier,
identity,
idText,
IfStatement,
ImmediatelyInvokedArrowFunction,
@ -509,7 +510,7 @@ export function addNodeFactoryPatcher(fn: (factory: NodeFactory) => void) {
* @internal
*/
export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory): NodeFactory {
const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal;
const setOriginal = flags & NodeFactoryFlags.NoOriginalNode ? identity : setOriginalNode;
// Lazily load the parenthesizer, node converters, and some factory methods until they are used.
const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory));
@ -6135,7 +6136,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
function cloneSourceFile(source: SourceFile) {
const node = source.redirectInfo ? cloneRedirectedSourceFile(source) : cloneSourceFileWorker(source);
setOriginalNode(node, source);
setOriginal(node, source);
return node;
}
@ -6365,7 +6366,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
const clone = createBaseIdentifier(node.escapedText) as Mutable<GeneratedIdentifier>;
clone.flags |= node.flags & ~NodeFlags.Synthesized;
clone.transformFlags = node.transformFlags;
setOriginalNode(clone, node);
setOriginal(clone, node);
setIdentifierAutoGenerate(clone, { ...node.emitNode.autoGenerate });
return clone;
}
@ -6377,7 +6378,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
clone.flowNode = node.flowNode;
clone.symbol = node.symbol;
clone.transformFlags = node.transformFlags;
setOriginalNode(clone, node);
setOriginal(clone, node);
// clone type arguments for emitter/typeWriter
const typeArguments = getIdentifierTypeArguments(node);
@ -6389,7 +6390,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
const clone = createBasePrivateIdentifier(node.escapedText) as Mutable<GeneratedPrivateIdentifier>;
clone.flags |= node.flags & ~NodeFlags.Synthesized;
clone.transformFlags = node.transformFlags;
setOriginalNode(clone, node);
setOriginal(clone, node);
setIdentifierAutoGenerate(clone, { ...node.emitNode.autoGenerate });
return clone;
}
@ -6398,7 +6399,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
const clone = createBasePrivateIdentifier(node.escapedText);
clone.flags |= node.flags & ~NodeFlags.Synthesized;
clone.transformFlags = node.transformFlags;
setOriginalNode(clone, node);
setOriginal(clone, node);
return clone;
}
@ -6432,7 +6433,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
(clone as Mutable<T>).flags |= node.flags & ~NodeFlags.Synthesized;
(clone as Mutable<T>).transformFlags = node.transformFlags;
setOriginalNode(clone, node);
setOriginal(clone, node);
for (const key in node) {
if (hasProperty(clone, key) || !hasProperty(node, key)) {
@ -7197,7 +7198,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
function asEmbeddedStatement<T extends Node>(statement: T): T | EmptyStatement;
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined;
function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined {
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement;
return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginal(createEmptyStatement(), statement), statement) : statement;
}
function asVariableDeclaration(variableDeclaration: string | BindingName | VariableDeclaration | undefined) {
@ -7211,21 +7212,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
}
return variableDeclaration;
}
}
function updateWithoutOriginal<T extends Node>(updated: Mutable<T>, original: T): T {
if (updated !== original) {
setTextRange(updated, original);
function update<T extends Node>(updated: Mutable<T>, original: T): T {
if (updated !== original) {
setOriginal(updated, original);
setTextRange(updated, original);
}
return updated;
}
return updated;
}
function updateWithOriginal<T extends Node>(updated: Mutable<T>, original: T): T {
if (updated !== original) {
setOriginalNode(updated, original);
setTextRange(updated, original);
}
return updated;
}
function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string {

View File

@ -1971,8 +1971,9 @@ namespace Parser {
// If we parsed this as an external module, it may contain top-level await
if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) {
const oldSourceFile = sourceFile;
sourceFile = reparseTopLevelAwait(sourceFile);
setFields(sourceFile);
if (oldSourceFile !== sourceFile) setFields(sourceFile);
}
return sourceFile;

View File

@ -0,0 +1,70 @@
//// [tests/cases/compiler/dynamicImportsDeclaration.ts] ////
//// [case0.ts]
export default 0;
//// [case1.ts]
export default 1;
//// [caseFallback.ts]
export default 'fallback';
//// [index.ts]
export const mod = await (async () => {
const x: number = 0;
switch (x) {
case 0:
return await import("./case0.js");
case 1:
return await import("./case1.js");
default:
return await import("./caseFallback.js");
}
})();
//// [case0.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = 0;
//// [case1.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = 1;
//// [caseFallback.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = 'fallback';
//// [index.js]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.mod = void 0;
exports.mod = await (async () => {
const x = 0;
switch (x) {
case 0:
return await import("./case0.js");
case 1:
return await import("./case1.js");
default:
return await import("./caseFallback.js");
}
})();
//// [case0.d.ts]
declare const _default: 0;
export default _default;
//// [case1.d.ts]
declare const _default: 1;
export default _default;
//// [caseFallback.d.ts]
declare const _default: "fallback";
export default _default;
//// [index.d.ts]
export declare const mod: {
default: typeof import("./case0.js");
} | {
default: typeof import("./case1.js");
} | {
default: typeof import("./caseFallback.js");
};

View File

@ -0,0 +1,37 @@
//// [tests/cases/compiler/dynamicImportsDeclaration.ts] ////
=== /case0.ts ===
export default 0;
=== /case1.ts ===
export default 1;
=== /caseFallback.ts ===
export default 'fallback';
=== /index.ts ===
export const mod = await (async () => {
>mod : Symbol(mod, Decl(index.ts, 0, 12))
const x: number = 0;
>x : Symbol(x, Decl(index.ts, 1, 7))
switch (x) {
>x : Symbol(x, Decl(index.ts, 1, 7))
case 0:
return await import("./case0.js");
>"./case0.js" : Symbol("/case0", Decl(case0.ts, 0, 0))
case 1:
return await import("./case1.js");
>"./case1.js" : Symbol("/case1", Decl(case1.ts, 0, 0))
default:
return await import("./caseFallback.js");
>"./caseFallback.js" : Symbol("/caseFallback", Decl(caseFallback.ts, 0, 0))
}
})();

View File

@ -0,0 +1,52 @@
//// [tests/cases/compiler/dynamicImportsDeclaration.ts] ////
=== /case0.ts ===
export default 0;
=== /case1.ts ===
export default 1;
=== /caseFallback.ts ===
export default 'fallback';
=== /index.ts ===
export const mod = await (async () => {
>mod : { default: typeof import("/case0"); } | { default: typeof import("/case1"); } | { default: typeof import("/caseFallback"); }
>await (async () => { const x: number = 0; switch (x) { case 0: return await import("./case0.js"); case 1: return await import("./case1.js"); default: return await import("./caseFallback.js"); }})() : { default: typeof import("/case0"); } | { default: typeof import("/case1"); } | { default: typeof import("/caseFallback"); }
>(async () => { const x: number = 0; switch (x) { case 0: return await import("./case0.js"); case 1: return await import("./case1.js"); default: return await import("./caseFallback.js"); }})() : Promise<{ default: typeof import("/case0"); } | { default: typeof import("/case1"); } | { default: typeof import("/caseFallback"); }>
>(async () => { const x: number = 0; switch (x) { case 0: return await import("./case0.js"); case 1: return await import("./case1.js"); default: return await import("./caseFallback.js"); }}) : () => Promise<{ default: typeof import("/case0"); } | { default: typeof import("/case1"); } | { default: typeof import("/caseFallback"); }>
>async () => { const x: number = 0; switch (x) { case 0: return await import("./case0.js"); case 1: return await import("./case1.js"); default: return await import("./caseFallback.js"); }} : () => Promise<{ default: typeof import("/case0"); } | { default: typeof import("/case1"); } | { default: typeof import("/caseFallback"); }>
const x: number = 0;
>x : number
>0 : 0
switch (x) {
>x : number
case 0:
>0 : 0
return await import("./case0.js");
>await import("./case0.js") : { default: typeof import("/case0"); }
>import("./case0.js") : Promise<{ default: typeof import("/case0"); }>
>"./case0.js" : "./case0.js"
case 1:
>1 : 1
return await import("./case1.js");
>await import("./case1.js") : { default: typeof import("/case1"); }
>import("./case1.js") : Promise<{ default: typeof import("/case1"); }>
>"./case1.js" : "./case1.js"
default:
return await import("./caseFallback.js");
>await import("./caseFallback.js") : { default: typeof import("/caseFallback"); }
>import("./caseFallback.js") : Promise<{ default: typeof import("/caseFallback"); }>
>"./caseFallback.js" : "./caseFallback.js"
}
})();

View File

@ -0,0 +1,25 @@
// @declaration: true
// @module: nodenext
// @target: esnext
// @filename: /case0.ts
export default 0;
// @filename: /case1.ts
export default 1;
// @filename: /caseFallback.ts
export default 'fallback';
// @filename: /index.ts
export const mod = await (async () => {
const x: number = 0;
switch (x) {
case 0:
return await import("./case0.js");
case 1:
return await import("./case1.js");
default:
return await import("./caseFallback.js");
}
})();