Fix crash intersecting dynamic import w/esModuleInterop (#40249)

* Fix crash intersecting dynamic import w/esModuleInterop

The dynamic import shim creates a symbol without some properties that
the intersection-creating code assumes are present as of #38673.

This PR adds the smallest possible set of properties to avoid the crash.
I'm not sure what others would be good to add.

* Use symbol's declarations instead

* Fix getResolvedMembersOrExportsOfSymbol instead

* comment from code review
This commit is contained in:
Nathan Shively-Sanders
2020-09-01 09:10:36 -07:00
committed by GitHub
parent 378083fcec
commit d572dcb272
5 changed files with 76 additions and 1 deletions

View File

@@ -9714,7 +9714,7 @@ namespace ts {
// fill in any as-yet-unresolved late-bound members.
const lateSymbols = createSymbolTable() as UnderscoreEscapedMap<TransientSymbol>;
for (const decl of symbol.declarations) {
for (const decl of symbol.declarations || emptyArray) {
const members = getMembersOfDeclaration(decl);
if (members) {
for (const member of members) {

View File

@@ -1,3 +1,5 @@
//// [tests/cases/conformance/types/intersection/intersectionsAndEmptyObjects.ts] ////
//// [intersectionsAndEmptyObjects.ts]
// Empty object type literals are removed from intersections types
// that contain other object types
@@ -80,11 +82,38 @@ var unknownChoicesAndEmpty: choices<IUnknownChoiceList & {}>;
type Foo1 = { x: string } & { [x: number]: Foo1 };
type Foo2 = { x: string } & { [K in number]: Foo2 };
// Repro from #40239
declare function mock<M>(_: Promise<M>): {} & M;
mock(import('./ex'))
//// [ex.d.ts]
export {}
//// [intersectionsAndEmptyObjects.js]
// Empty object type literals are removed from intersections types
// that contain other object types
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
let x01;
let x02;
let x03;
@@ -121,3 +150,4 @@ var myChoices;
var myChoicesAndEmpty;
var unknownChoices;
var unknownChoicesAndEmpty;
mock(Promise.resolve().then(() => __importStar(require('./ex'))));

View File

@@ -260,3 +260,21 @@ type Foo2 = { x: string } & { [K in number]: Foo2 };
>K : Symbol(K, Decl(intersectionsAndEmptyObjects.ts, 80, 31))
>Foo2 : Symbol(Foo2, Decl(intersectionsAndEmptyObjects.ts, 79, 50))
// Repro from #40239
declare function mock<M>(_: Promise<M>): {} & M;
>mock : Symbol(mock, Decl(intersectionsAndEmptyObjects.ts, 80, 52))
>M : Symbol(M, Decl(intersectionsAndEmptyObjects.ts, 84, 22))
>_ : Symbol(_, Decl(intersectionsAndEmptyObjects.ts, 84, 25))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --))
>M : Symbol(M, Decl(intersectionsAndEmptyObjects.ts, 84, 22))
>M : Symbol(M, Decl(intersectionsAndEmptyObjects.ts, 84, 22))
mock(import('./ex'))
>mock : Symbol(mock, Decl(intersectionsAndEmptyObjects.ts, 80, 52))
>'./ex' : Symbol("tests/cases/conformance/types/intersection/ex", Decl(ex.d.ts, 0, 0))
=== tests/cases/conformance/types/intersection/ex.d.ts ===
export {}
No type information for this code.
No type information for this code.

View File

@@ -217,3 +217,19 @@ type Foo2 = { x: string } & { [K in number]: Foo2 };
>Foo2 : Foo2
>x : string
// Repro from #40239
declare function mock<M>(_: Promise<M>): {} & M;
>mock : <M>(_: Promise<M>) => {} & M
>_ : Promise<M>
mock(import('./ex'))
>mock(import('./ex')) : {}
>mock : <M>(_: Promise<M>) => {} & M
>import('./ex') : Promise<{ default: typeof import("tests/cases/conformance/types/intersection/ex"); }>
>'./ex' : "./ex"
=== tests/cases/conformance/types/intersection/ex.d.ts ===
export {}
No type information for this code.
No type information for this code.

View File

@@ -1,4 +1,7 @@
// @target: es2015
// @module: commonjs
// @esModuleInterop: true
// @filename: intersectionsAndEmptyObjects.ts
// Empty object type literals are removed from intersections types
// that contain other object types
@@ -81,3 +84,11 @@ var unknownChoicesAndEmpty: choices<IUnknownChoiceList & {}>;
type Foo1 = { x: string } & { [x: number]: Foo1 };
type Foo2 = { x: string } & { [K in number]: Foo2 };
// Repro from #40239
declare function mock<M>(_: Promise<M>): {} & M;
mock(import('./ex'))
// @filename: ex.d.ts
export {}