Skip to content

Commit

Permalink
Tighten heuristic for definite dts moduleness to check for syntactic …
Browse files Browse the repository at this point in the history
…default (#22814)

* Tighten heuristic for definite dts moduleness to check for syntactic default exports

* Inline function
  • Loading branch information
weswigham authored Mar 26, 2018
1 parent 36b49c0 commit dcbc478
Show file tree
Hide file tree
Showing 5 changed files with 123 additions and 3 deletions.
11 changes: 8 additions & 3 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1730,14 +1730,19 @@ namespace ts {
: resolveSymbol(moduleSymbol.exports.get(name), dontResolveAlias);
}

function isSyntacticDefault(node: Node) {
return ((isExportAssignment(node) && !node.isExportEquals) || hasModifier(node, ModifierFlags.Default));
}

function canHaveSyntheticDefault(file: SourceFile | undefined, moduleSymbol: Symbol, dontResolveAlias: boolean) {
if (!allowSyntheticDefaultImports) {
return false;
}
// Declaration files (and ambient modules)
if (!file || file.isDeclarationFile) {
// Definitely cannot have a synthetic default if they have a default member specified
if (resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias)) {
// Definitely cannot have a synthetic default if they have a syntactic default member specified
const defaultExportSymbol = resolveExportByName(moduleSymbol, InternalSymbolName.Default, dontResolveAlias);
if (defaultExportSymbol && defaultExportSymbol.valueDeclaration && isSyntacticDefault(defaultExportSymbol.valueDeclaration)) {
return false;
}
// It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member
Expand Down Expand Up @@ -1777,7 +1782,7 @@ namespace ts {
if (!exportDefaultSymbol && !hasSyntheticDefault) {
error(node.name, Diagnostics.Module_0_has_no_default_export, symbolToString(moduleSymbol));
}
else if (!exportDefaultSymbol && hasSyntheticDefault) {
else if (hasSyntheticDefault) {
// per emit behavior, a synthetic default overrides a "real" .default member if `__esModule` is not present
return resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) || resolveSymbol(moduleSymbol, dontResolveAlias);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
//// [tests/cases/compiler/esModuleInteropDefaultMemberMustBeSyntacticallyDefaultExport.ts] ////

//// [point.d.ts]
declare class Point {
x: number;
y: number;

constructor(x: number, y: number);

static default: "foo";
}

export = Point;
//// [index.ts]
import Point from "./point";

const C = Point;
const p = new C(1, 2);


//// [index.js]
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
var point_1 = __importDefault(require("./point"));
var C = point_1["default"];
var p = new C(1, 2);
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
=== tests/cases/compiler/point.d.ts ===
declare class Point {
>Point : Symbol(Point, Decl(point.d.ts, 0, 0))

x: number;
>x : Symbol(Point.x, Decl(point.d.ts, 0, 21))

y: number;
>y : Symbol(Point.y, Decl(point.d.ts, 1, 14))

constructor(x: number, y: number);
>x : Symbol(x, Decl(point.d.ts, 4, 16))
>y : Symbol(y, Decl(point.d.ts, 4, 26))

static default: "foo";
>default : Symbol(Point.default, Decl(point.d.ts, 4, 38))
}

export = Point;
>Point : Symbol(Point, Decl(point.d.ts, 0, 0))

=== tests/cases/compiler/index.ts ===
import Point from "./point";
>Point : Symbol(Point, Decl(index.ts, 0, 6))

const C = Point;
>C : Symbol(C, Decl(index.ts, 2, 5))
>Point : Symbol(Point, Decl(index.ts, 0, 6))

const p = new C(1, 2);
>p : Symbol(p, Decl(index.ts, 3, 5))
>C : Symbol(C, Decl(index.ts, 2, 5))

Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
=== tests/cases/compiler/point.d.ts ===
declare class Point {
>Point : Point

x: number;
>x : number

y: number;
>y : number

constructor(x: number, y: number);
>x : number
>y : number

static default: "foo";
>default : "foo"
}

export = Point;
>Point : Point

=== tests/cases/compiler/index.ts ===
import Point from "./point";
>Point : typeof Point

const C = Point;
>C : typeof Point
>Point : typeof Point

const p = new C(1, 2);
>p : Point
>new C(1, 2) : Point
>C : typeof Point
>1 : 1
>2 : 2

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// @esModuleInterop: true
// @filename: point.d.ts
declare class Point {
x: number;
y: number;

constructor(x: number, y: number);

static default: "foo";
}

export = Point;
// @filename: index.ts
import Point from "./point";

const C = Point;
const p = new C(1, 2);

0 comments on commit dcbc478

Please sign in to comment.