From 854c124a10773ef069bc065a0bbd24438c434171 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 5 Apr 2018 16:33:07 -0700 Subject: [PATCH 1/5] Combining symbol and removing error done but messy --- src/compiler/checker.ts | 45 ++++++++++++++++--- ...oduleExportWithExportPropertyAssignment.ts | 12 +++++ 2 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 34e5000790add..1a4a6a8248cd1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2096,9 +2096,15 @@ namespace ts { const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral; const moduleSym = resolveExternalModuleName(moduleName, moduleName); if (moduleSym) { - const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); - if (resolvedModuleSymbol) { - namespace = resolvedModuleSymbol; + if (moduleSym.exports.has(InternalSymbolName.ExportEquals as __String) && moduleSym.exports.size > 1) { + Debug.assert(!!(moduleSym.valueDeclaration as SourceFile).commonJsModuleIndicator); + namespace = combineCommonJsSymbol(moduleSym); + } + else { + const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); + if (resolvedModuleSymbol) { + namespace = resolvedModuleSymbol; + } } } } @@ -4350,7 +4356,8 @@ namespace ts { return unknownType; } - if (isPropertyAccessExpression(expression.left) && expression.left.expression.kind === SyntaxKind.ThisKeyword) { + const special = getSpecialPropertyAssignmentKind(expression); + if (special === SpecialPropertyAssignmentKind.ThisProperty) { const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false); // Properties defined in a constructor (or javascript constructor function) don't get undefined added. // Function expressions that are assigned to the prototype count as methods. @@ -4380,7 +4387,17 @@ namespace ts { } else if (!jsDocType) { // If we don't have an explicit JSDoc type, get the type from the expression. - const type = getWidenedLiteralType(checkExpressionCached(expression.right)); + let type = getWidenedLiteralType(checkExpressionCached(expression.right)); + + if (getObjectFlags(type) & ObjectFlags.Anonymous && + special === SpecialPropertyAssignmentKind.ModuleExports && + symbol.escapedName === InternalSymbolName.ExportEquals) { + const o = resolveStructuredTypeMembers(type as AnonymousType); + const members = createSymbolTable(); + copyEntries(o.members, members); + copyEntries(symbol.exports, members); + type = createAnonymousType(symbol, members, o.callSignatures, o.constructSignatures, o.stringIndexInfo, o.numberIndexInfo); + } let anyedType = type; if (isEmptyArrayLiteralType(type)) { anyedType = anyArrayType; @@ -6992,6 +7009,10 @@ namespace ts { function resolveExternalModuleTypeByLiteral(name: StringLiteral) { const moduleSym = resolveExternalModuleName(name, name); if (moduleSym) { + if (moduleSym.exports.has(InternalSymbolName.ExportEquals as __String) && moduleSym.exports.size > 1) { + Debug.assert(!!(moduleSym.valueDeclaration as SourceFile).commonJsModuleIndicator); + return getTypeOfSymbol(combineCommonJsSymbol(moduleSym)); + } const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); if (resolvedModuleSymbol) { return getTypeOfSymbol(resolvedModuleSymbol); @@ -7001,6 +7022,18 @@ namespace ts { return anyType; } + function combineCommonJsSymbol(moduleSym: Symbol): Symbol { + const combined = cloneSymbol(moduleSym.exports.get(InternalSymbolName.ExportEquals)); + moduleSym.exports.forEach((s,name) => { + if (name === InternalSymbolName.ExportEquals) return; + if (!combined.exports.has(name) || combined.exports.get(name).valueDeclaration.pos > s.valueDeclaration.pos) { + combined.exports.set(name, s); + } + }); + return combined; + + } + function getThisTypeOfSignature(signature: Signature): Type | undefined { if (signature.thisParameter) { return getTypeOfSymbol(signature.thisParameter); @@ -24568,7 +24601,7 @@ namespace ts { const exportEqualsSymbol = moduleSymbol.exports.get("export=" as __String); if (exportEqualsSymbol && hasExportedMembers(moduleSymbol)) { const declaration = getDeclarationOfAliasSymbol(exportEqualsSymbol) || exportEqualsSymbol.valueDeclaration; - if (!isTopLevelInExternalModuleAugmentation(declaration)) { + if (!isTopLevelInExternalModuleAugmentation(declaration) && !isInJavaScriptFile(declaration)) { error(declaration, Diagnostics.An_export_assignment_cannot_be_used_in_a_module_with_other_exported_elements); } } diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts new file mode 100644 index 0000000000000..9486f238e74e4 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts @@ -0,0 +1,12 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: mod1.js +// TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +module.exports = function () { } +module.exports.f = function () { } + +// @Filename: a.js +var mod1 = require('./mod1') +mod1() +mod1.f() From 8b67c9b799bb322f4e9cf49654404e0c0a7ee52d Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 5 Apr 2018 16:38:31 -0700 Subject: [PATCH 2/5] Small fix + add new test baselines All other tests are unchanged --- src/compiler/checker.ts | 2 +- ...ortWithExportPropertyAssignment.errors.txt | 21 +++++++++++ ...ExportWithExportPropertyAssignment.symbols | 23 ++++++++++++ ...leExportWithExportPropertyAssignment.types | 35 +++++++++++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment.types diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1a4a6a8248cd1..5cf682b5b6c95 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4396,7 +4396,7 @@ namespace ts { const members = createSymbolTable(); copyEntries(o.members, members); copyEntries(symbol.exports, members); - type = createAnonymousType(symbol, members, o.callSignatures, o.constructSignatures, o.stringIndexInfo, o.numberIndexInfo); + type = createAnonymousType(o.symbol, members, o.callSignatures, o.constructSignatures, o.stringIndexInfo, o.numberIndexInfo); } let anyedType = type; if (isEmptyArrayLiteralType(type)) { diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt new file mode 100644 index 0000000000000..63c13c96c136b --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt @@ -0,0 +1,21 @@ +tests/cases/conformance/salsa/a.js(1,12): error TS2304: Cannot find name 'require'. +tests/cases/conformance/salsa/mod1.js(2,1): error TS2304: Cannot find name 'module'. +tests/cases/conformance/salsa/mod1.js(3,1): error TS2304: Cannot find name 'module'. + + +==== tests/cases/conformance/salsa/a.js (1 errors) ==== + var mod1 = require('./mod1') + ~~~~~~~ +!!! error TS2304: Cannot find name 'require'. + mod1() + mod1.f() + +==== tests/cases/conformance/salsa/mod1.js (2 errors) ==== + // TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive + module.exports = function () { } + ~~~~~~ +!!! error TS2304: Cannot find name 'module'. + module.exports.f = function () { } + ~~~~~~ +!!! error TS2304: Cannot find name 'module'. + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols new file mode 100644 index 0000000000000..77fb9fd209745 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols @@ -0,0 +1,23 @@ +=== tests/cases/conformance/salsa/a.js === +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 0, 3)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1() +>mod1 : Symbol(mod1, Decl(a.js, 0, 3)) + +mod1.f() +>mod1.f : Symbol(f, Decl(mod1.js, 1, 32)) +>mod1 : Symbol(mod1, Decl(a.js, 0, 3)) +>f : Symbol(f, Decl(mod1.js, 1, 32)) + +=== tests/cases/conformance/salsa/mod1.js === +// TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +module.exports = function () { } +>module : Symbol(export=, Decl(mod1.js, 0, 0)) +>exports : Symbol(export=, Decl(mod1.js, 0, 0)) + +module.exports.f = function () { } +>module.exports : Symbol(f, Decl(mod1.js, 1, 32)) +>f : Symbol(f, Decl(mod1.js, 1, 32)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types new file mode 100644 index 0000000000000..d1657107fdfda --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/salsa/a.js === +var mod1 = require('./mod1') +>mod1 : { (): void; f: () => void; } +>require('./mod1') : { (): void; f: () => void; } +>require : any +>'./mod1' : "./mod1" + +mod1() +>mod1() : void +>mod1 : { (): void; f: () => void; } + +mod1.f() +>mod1.f() : void +>mod1.f : () => void +>mod1 : { (): void; f: () => void; } +>f : () => void + +=== tests/cases/conformance/salsa/mod1.js === +// TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +module.exports = function () { } +>module.exports = function () { } : () => void +>module.exports : any +>module : any +>exports : any +>function () { } : () => void + +module.exports.f = function () { } +>module.exports.f = function () { } : () => void +>module.exports.f : any +>module.exports : any +>module : any +>exports : any +>f : any +>function () { } : () => void + From 571e9350cbbbb5364f23172f81cf48c73a74a064 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 6 Apr 2018 10:44:21 -0700 Subject: [PATCH 3/5] Union conflicting assignment types+better names --- src/compiler/checker.ts | 34 +++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 5cf682b5b6c95..a33421c946dd5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2098,7 +2098,7 @@ namespace ts { if (moduleSym) { if (moduleSym.exports.has(InternalSymbolName.ExportEquals as __String) && moduleSym.exports.size > 1) { Debug.assert(!!(moduleSym.valueDeclaration as SourceFile).commonJsModuleIndicator); - namespace = combineCommonJsSymbol(moduleSym); + namespace = mergeCommonJsExportEquals(moduleSym); } else { const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); @@ -4392,11 +4392,27 @@ namespace ts { if (getObjectFlags(type) & ObjectFlags.Anonymous && special === SpecialPropertyAssignmentKind.ModuleExports && symbol.escapedName === InternalSymbolName.ExportEquals) { - const o = resolveStructuredTypeMembers(type as AnonymousType); + const exportedType = resolveStructuredTypeMembers(type as AnonymousType); const members = createSymbolTable(); - copyEntries(o.members, members); - copyEntries(symbol.exports, members); - type = createAnonymousType(o.symbol, members, o.callSignatures, o.constructSignatures, o.stringIndexInfo, o.numberIndexInfo); + copyEntries(exportedType.members, members); + symbol.exports.forEach((s, name) => { + if (members.has(name)) { + const exportedMember = exportedType.members.get(name); + const union = createSymbol(s.flags | exportedMember.flags, name); + union.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); + members.set(name, union); + } + else { + members.set(name, s); + } + }); + type = createAnonymousType( + exportedType.symbol, + members, + exportedType.callSignatures, + exportedType.constructSignatures, + exportedType.stringIndexInfo, + exportedType.numberIndexInfo); } let anyedType = type; if (isEmptyArrayLiteralType(type)) { @@ -7011,7 +7027,7 @@ namespace ts { if (moduleSym) { if (moduleSym.exports.has(InternalSymbolName.ExportEquals as __String) && moduleSym.exports.size > 1) { Debug.assert(!!(moduleSym.valueDeclaration as SourceFile).commonJsModuleIndicator); - return getTypeOfSymbol(combineCommonJsSymbol(moduleSym)); + return getTypeOfSymbol(mergeCommonJsExportEquals(moduleSym)); } const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); if (resolvedModuleSymbol) { @@ -7022,11 +7038,11 @@ namespace ts { return anyType; } - function combineCommonJsSymbol(moduleSym: Symbol): Symbol { + function mergeCommonJsExportEquals(moduleSym: Symbol): Symbol { const combined = cloneSymbol(moduleSym.exports.get(InternalSymbolName.ExportEquals)); - moduleSym.exports.forEach((s,name) => { + moduleSym.exports.forEach((s, name) => { if (name === InternalSymbolName.ExportEquals) return; - if (!combined.exports.has(name) || combined.exports.get(name).valueDeclaration.pos > s.valueDeclaration.pos) { + if (!combined.exports.has(name)) { combined.exports.set(name, s); } }); From 6203ec7ec1223a60f50f28adec6fc3ca8b200e94 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 6 Apr 2018 10:44:48 -0700 Subject: [PATCH 4/5] Add tests and update baselines --- ...ortWithExportPropertyAssignment.errors.txt | 25 ++-- ...ExportWithExportPropertyAssignment.symbols | 28 ++++- ...leExportWithExportPropertyAssignment.types | 40 +++--- ...rtWithExportPropertyAssignment2.errors.txt | 19 +++ ...xportWithExportPropertyAssignment2.symbols | 37 ++++++ ...eExportWithExportPropertyAssignment2.types | 48 ++++++++ ...rtWithExportPropertyAssignment3.errors.txt | 34 ++++++ ...xportWithExportPropertyAssignment3.symbols | 74 +++++++++++ ...eExportWithExportPropertyAssignment3.types | 96 +++++++++++++++ ...rtWithExportPropertyAssignment4.errors.txt | 36 ++++++ ...xportWithExportPropertyAssignment4.symbols | 87 +++++++++++++ ...eExportWithExportPropertyAssignment4.types | 115 ++++++++++++++++++ ...oduleExportWithExportPropertyAssignment.ts | 11 +- ...duleExportWithExportPropertyAssignment2.ts | 16 +++ ...duleExportWithExportPropertyAssignment3.ts | 24 ++++ ...duleExportWithExportPropertyAssignment4.ts | 26 ++++ 16 files changed, 680 insertions(+), 36 deletions(-) create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols create mode 100644 tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types create mode 100644 tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts create mode 100644 tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts create mode 100644 tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt index 63c13c96c136b..aab334e77f38c 100644 --- a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.errors.txt @@ -1,21 +1,20 @@ -tests/cases/conformance/salsa/a.js(1,12): error TS2304: Cannot find name 'require'. -tests/cases/conformance/salsa/mod1.js(2,1): error TS2304: Cannot find name 'module'. -tests/cases/conformance/salsa/mod1.js(3,1): error TS2304: Cannot find name 'module'. +tests/cases/conformance/salsa/a.js(4,1): error TS2554: Expected 1 arguments, but got 0. ==== tests/cases/conformance/salsa/a.js (1 errors) ==== + /// var mod1 = require('./mod1') - ~~~~~~~ -!!! error TS2304: Cannot find name 'require'. mod1() - mod1.f() + mod1.f() // error, not enough arguments + ~~~~~~~~ +!!! error TS2554: Expected 1 arguments, but got 0. -==== tests/cases/conformance/salsa/mod1.js (2 errors) ==== - // TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// module.exports = function () { } - ~~~~~~ -!!! error TS2304: Cannot find name 'module'. - module.exports.f = function () { } - ~~~~~~ -!!! error TS2304: Cannot find name 'module'. + /** @param {number} a */ + module.exports.f = function (a) { } \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols index 77fb9fd209745..c5120a80571e3 100644 --- a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.symbols @@ -1,23 +1,39 @@ === tests/cases/conformance/salsa/a.js === +/// var mod1 = require('./mod1') ->mod1 : Symbol(mod1, Decl(a.js, 0, 3)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) >'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) mod1() ->mod1 : Symbol(mod1, Decl(a.js, 0, 3)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) -mod1.f() +mod1.f() // error, not enough arguments >mod1.f : Symbol(f, Decl(mod1.js, 1, 32)) ->mod1 : Symbol(mod1, Decl(a.js, 0, 3)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) >f : Symbol(f, Decl(mod1.js, 1, 32)) +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + === tests/cases/conformance/salsa/mod1.js === -// TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +/// module.exports = function () { } +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) >module : Symbol(export=, Decl(mod1.js, 0, 0)) >exports : Symbol(export=, Decl(mod1.js, 0, 0)) -module.exports.f = function () { } +/** @param {number} a */ +module.exports.f = function (a) { } >module.exports : Symbol(f, Decl(mod1.js, 1, 32)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) >f : Symbol(f, Decl(mod1.js, 1, 32)) +>a : Symbol(a, Decl(mod1.js, 3, 29)) diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types index d1657107fdfda..b7170842c1f39 100644 --- a/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment.types @@ -1,35 +1,47 @@ === tests/cases/conformance/salsa/a.js === +/// var mod1 = require('./mod1') ->mod1 : { (): void; f: () => void; } ->require('./mod1') : { (): void; f: () => void; } ->require : any +>mod1 : { (): void; f: (a: number) => void; } +>require('./mod1') : { (): void; f: (a: number) => void; } +>require : (name: string) => any >'./mod1' : "./mod1" mod1() >mod1() : void ->mod1 : { (): void; f: () => void; } +>mod1 : { (): void; f: (a: number) => void; } -mod1.f() +mod1.f() // error, not enough arguments >mod1.f() : void ->mod1.f : () => void ->mod1 : { (): void; f: () => void; } ->f : () => void +>mod1.f : (a: number) => void +>mod1 : { (): void; f: (a: number) => void; } +>f : (a: number) => void + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string === tests/cases/conformance/salsa/mod1.js === -// TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +/// module.exports = function () { } >module.exports = function () { } : () => void >module.exports : any ->module : any +>module : { exports: any; } >exports : any >function () { } : () => void -module.exports.f = function () { } ->module.exports.f = function () { } : () => void +/** @param {number} a */ +module.exports.f = function (a) { } +>module.exports.f = function (a) { } : (a: number) => void >module.exports.f : any >module.exports : any ->module : any +>module : { exports: any; } >exports : any >f : any ->function () { } : () => void +>function (a) { } : (a: number) => void +>a : number diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt new file mode 100644 index 0000000000000..66cb517a25be7 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.errors.txt @@ -0,0 +1,19 @@ +tests/cases/conformance/salsa/a.js(4,6): error TS2339: Property 'f' does not exist on type 'number'. + + +==== tests/cases/conformance/salsa/a.js (1 errors) ==== + /// + var mod1 = require('./mod1') + mod1.toFixed(12) + mod1.f() // error, 'f' is not a property on 'number' + ~ +!!! error TS2339: Property 'f' does not exist on type 'number'. + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports = 1 + module.exports.f = function () { } + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols new file mode 100644 index 0000000000000..c9a09bb6a8b99 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1.toFixed(12) +>mod1.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +mod1.f() // error, 'f' is not a property on 'number' +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports = 1 +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 0, 0)) +>exports : Symbol(export=, Decl(mod1.js, 0, 0)) + +module.exports.f = function () { } +>module.exports : Symbol(f, Decl(mod1.js, 1, 18)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>f : Symbol(f, Decl(mod1.js, 1, 18)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types new file mode 100644 index 0000000000000..8af94a05fa5c6 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment2.types @@ -0,0 +1,48 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : number +>require('./mod1') : number +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1.toFixed(12) +>mod1.toFixed(12) : string +>mod1.toFixed : (fractionDigits?: number) => string +>mod1 : number +>toFixed : (fractionDigits?: number) => string +>12 : 12 + +mod1.f() // error, 'f' is not a property on 'number' +>mod1.f() : any +>mod1.f : any +>mod1 : number +>f : any + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports = 1 +>module.exports = 1 : 1 +>module.exports : any +>module : { exports: any; } +>exports : any +>1 : 1 + +module.exports.f = function () { } +>module.exports.f = function () { } : () => void +>module.exports.f : any +>module.exports : any +>module : { exports: any; } +>exports : any +>f : any +>function () { } : () => void + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt new file mode 100644 index 0000000000000..bbaed77a0f90c --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.errors.txt @@ -0,0 +1,34 @@ +tests/cases/conformance/salsa/a.js(4,17): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. +tests/cases/conformance/salsa/a.js(5,16): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. + + +==== tests/cases/conformance/salsa/a.js (2 errors) ==== + /// + var mod1 = require('./mod1') + mod1.justExport.toFixed() + mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.justProperty.length + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports.bothBefore = 'string' + module.exports = { + justExport: 1, + bothBefore: 2, + bothAfter: 3, + } + module.exports.bothAfter = 'string' + module.exports.justProperty = 'string' + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols new file mode 100644 index 0000000000000..a84080cc998d8 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.symbols @@ -0,0 +1,74 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1.justExport.toFixed() +>mod1.justExport.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>mod1.justExport : Symbol(justExport, Decl(mod1.js, 2, 18)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justExport : Symbol(justExport, Decl(mod1.js, 2, 18)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothBefore : Symbol(bothBefore) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothBefore : Symbol(bothBefore) + +mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothAfter : Symbol(bothAfter) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothAfter : Symbol(bothAfter) + +mod1.justProperty.length +>mod1.justProperty.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>mod1.justProperty : Symbol(justProperty, Decl(mod1.js, 7, 35)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 7, 35)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports : Symbol(bothBefore, Decl(mod1.js, 0, 0)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 0, 0)) + +module.exports = { +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 1, 36)) +>exports : Symbol(export=, Decl(mod1.js, 1, 36)) + + justExport: 1, +>justExport : Symbol(justExport, Decl(mod1.js, 2, 18)) + + bothBefore: 2, +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 3, 18)) + + bothAfter: 3, +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 4, 18)) +} +module.exports.bothAfter = 'string' +>module.exports : Symbol(bothAfter, Decl(mod1.js, 6, 1)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 6, 1)) + +module.exports.justProperty = 'string' +>module.exports : Symbol(justProperty, Decl(mod1.js, 7, 35)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 7, 35)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types new file mode 100644 index 0000000000000..4d14bf647fd2c --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment3.types @@ -0,0 +1,96 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>require('./mod1') : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1.justExport.toFixed() +>mod1.justExport.toFixed() : string +>mod1.justExport.toFixed : (fractionDigits?: number) => string +>mod1.justExport : number +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>justExport : number +>toFixed : (fractionDigits?: number) => string + +mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothBefore.toFixed() : any +>mod1.bothBefore.toFixed : any +>mod1.bothBefore : string | number +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>bothBefore : string | number +>toFixed : any + +mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' +>mod1.bothAfter.toFixed() : any +>mod1.bothAfter.toFixed : any +>mod1.bothAfter : string | number +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>bothAfter : string | number +>toFixed : any + +mod1.justProperty.length +>mod1.justProperty.length : number +>mod1.justProperty : string +>mod1 : { [x: string]: any; justExport: number; bothBefore: string | number; bothAfter: string | number; justProperty: string; } +>justProperty : string +>length : number + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports.bothBefore = 'string' : "string" +>module.exports.bothBefore : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothBefore : any +>'string' : "string" + +module.exports = { +>module.exports = { justExport: 1, bothBefore: 2, bothAfter: 3,} : { [x: string]: any; justExport: number; bothBefore: number; bothAfter: number; } +>module.exports : any +>module : { exports: any; } +>exports : any +>{ justExport: 1, bothBefore: 2, bothAfter: 3,} : { [x: string]: any; justExport: number; bothBefore: number; bothAfter: number; } + + justExport: 1, +>justExport : number +>1 : 1 + + bothBefore: 2, +>bothBefore : number +>2 : 2 + + bothAfter: 3, +>bothAfter : number +>3 : 3 +} +module.exports.bothAfter = 'string' +>module.exports.bothAfter = 'string' : "string" +>module.exports.bothAfter : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothAfter : any +>'string' : "string" + +module.exports.justProperty = 'string' +>module.exports.justProperty = 'string' : "string" +>module.exports.justProperty : any +>module.exports : any +>module : { exports: any; } +>exports : any +>justProperty : any +>'string' : "string" + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt new file mode 100644 index 0000000000000..247c29e0ad3af --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.errors.txt @@ -0,0 +1,36 @@ +tests/cases/conformance/salsa/a.js(4,17): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. +tests/cases/conformance/salsa/a.js(5,16): error TS2339: Property 'toFixed' does not exist on type 'string | number'. + Property 'toFixed' does not exist on type 'string'. + + +==== tests/cases/conformance/salsa/a.js (2 errors) ==== + /// + var mod1 = require('./mod1') + mod1.justExport.toFixed() + mod1.bothBefore.toFixed() // error + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.bothAfter.toFixed() + ~~~~~~~ +!!! error TS2339: Property 'toFixed' does not exist on type 'string | number'. +!!! error TS2339: Property 'toFixed' does not exist on type 'string'. + mod1.justProperty.length + +==== tests/cases/conformance/salsa/requires.d.ts (0 errors) ==== + declare var module: { exports: any }; + declare function require(name: string): any; +==== tests/cases/conformance/salsa/mod1.js (0 errors) ==== + /// + module.exports.bothBefore = 'string' + A.justExport = 4 + A.bothBefore = 2 + A.bothAfter = 3 + module.exports = A + function A() { + this.p = 1 + } + module.exports.bothAfter = 'string' + module.exports.justProperty = 'string' + \ No newline at end of file diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols new file mode 100644 index 0000000000000..b62a68c83f3c4 --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.symbols @@ -0,0 +1,87 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>'./mod1' : Symbol("tests/cases/conformance/salsa/mod1", Decl(mod1.js, 0, 0)) + +mod1.justExport.toFixed() +>mod1.justExport.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>mod1.justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +mod1.bothBefore.toFixed() // error +>mod1.bothBefore : Symbol(bothBefore) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothBefore : Symbol(bothBefore) + +mod1.bothAfter.toFixed() +>mod1.bothAfter : Symbol(bothAfter) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>bothAfter : Symbol(bothAfter) + +mod1.justProperty.length +>mod1.justProperty.length : Symbol(String.length, Decl(lib.d.ts, --, --)) +>mod1.justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) +>mod1 : Symbol(mod1, Decl(a.js, 1, 3)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) +>length : Symbol(String.length, Decl(lib.d.ts, --, --)) + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) + +declare function require(name: string): any; +>require : Symbol(require, Decl(requires.d.ts, 0, 37)) +>name : Symbol(name, Decl(requires.d.ts, 1, 25)) + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports : Symbol(bothBefore, Decl(mod1.js, 0, 0)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothBefore : Symbol(bothBefore, Decl(mod1.js, 0, 0)) + +A.justExport = 4 +>A.justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) +>justExport : Symbol(A.justExport, Decl(mod1.js, 1, 36)) + +A.bothBefore = 2 +>A.bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) +>bothBefore : Symbol(A.bothBefore, Decl(mod1.js, 2, 16)) + +A.bothAfter = 3 +>A.bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) +>bothAfter : Symbol(A.bothAfter, Decl(mod1.js, 3, 16)) + +module.exports = A +>module.exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>module : Symbol(export=, Decl(mod1.js, 4, 15)) +>exports : Symbol(export=, Decl(mod1.js, 4, 15)) +>A : Symbol(A, Decl(mod1.js, 5, 18)) + +function A() { +>A : Symbol(A, Decl(mod1.js, 5, 18)) + + this.p = 1 +>p : Symbol(A.p, Decl(mod1.js, 6, 14)) +} +module.exports.bothAfter = 'string' +>module.exports : Symbol(bothAfter, Decl(mod1.js, 8, 1)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>bothAfter : Symbol(bothAfter, Decl(mod1.js, 8, 1)) + +module.exports.justProperty = 'string' +>module.exports : Symbol(justProperty, Decl(mod1.js, 9, 35)) +>module : Symbol(module, Decl(requires.d.ts, 0, 11)) +>exports : Symbol(exports, Decl(requires.d.ts, 0, 21)) +>justProperty : Symbol(justProperty, Decl(mod1.js, 9, 35)) + diff --git a/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types new file mode 100644 index 0000000000000..f339118bf05ac --- /dev/null +++ b/tests/baselines/reference/moduleExportWithExportPropertyAssignment4.types @@ -0,0 +1,115 @@ +=== tests/cases/conformance/salsa/a.js === +/// +var mod1 = require('./mod1') +>mod1 : typeof A +>require('./mod1') : typeof A +>require : (name: string) => any +>'./mod1' : "./mod1" + +mod1.justExport.toFixed() +>mod1.justExport.toFixed() : string +>mod1.justExport.toFixed : (fractionDigits?: number) => string +>mod1.justExport : number +>mod1 : typeof A +>justExport : number +>toFixed : (fractionDigits?: number) => string + +mod1.bothBefore.toFixed() // error +>mod1.bothBefore.toFixed() : any +>mod1.bothBefore.toFixed : any +>mod1.bothBefore : string | number +>mod1 : typeof A +>bothBefore : string | number +>toFixed : any + +mod1.bothAfter.toFixed() +>mod1.bothAfter.toFixed() : any +>mod1.bothAfter.toFixed : any +>mod1.bothAfter : string | number +>mod1 : typeof A +>bothAfter : string | number +>toFixed : any + +mod1.justProperty.length +>mod1.justProperty.length : number +>mod1.justProperty : string +>mod1 : typeof A +>justProperty : string +>length : number + +=== tests/cases/conformance/salsa/requires.d.ts === +declare var module: { exports: any }; +>module : { exports: any; } +>exports : any + +declare function require(name: string): any; +>require : (name: string) => any +>name : string + +=== tests/cases/conformance/salsa/mod1.js === +/// +module.exports.bothBefore = 'string' +>module.exports.bothBefore = 'string' : "string" +>module.exports.bothBefore : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothBefore : any +>'string' : "string" + +A.justExport = 4 +>A.justExport = 4 : 4 +>A.justExport : number +>A : typeof A +>justExport : number +>4 : 4 + +A.bothBefore = 2 +>A.bothBefore = 2 : 2 +>A.bothBefore : number +>A : typeof A +>bothBefore : number +>2 : 2 + +A.bothAfter = 3 +>A.bothAfter = 3 : 3 +>A.bothAfter : number +>A : typeof A +>bothAfter : number +>3 : 3 + +module.exports = A +>module.exports = A : typeof A +>module.exports : any +>module : { exports: any; } +>exports : any +>A : typeof A + +function A() { +>A : typeof A + + this.p = 1 +>this.p = 1 : 1 +>this.p : any +>this : any +>p : any +>1 : 1 +} +module.exports.bothAfter = 'string' +>module.exports.bothAfter = 'string' : "string" +>module.exports.bothAfter : any +>module.exports : any +>module : { exports: any; } +>exports : any +>bothAfter : any +>'string' : "string" + +module.exports.justProperty = 'string' +>module.exports.justProperty = 'string' : "string" +>module.exports.justProperty : any +>module.exports : any +>module : { exports: any; } +>exports : any +>justProperty : any +>'string' : "string" + diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts index 9486f238e74e4..926a4cadf08f7 100644 --- a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment.ts @@ -1,12 +1,17 @@ // @noEmit: true // @allowJs: true // @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; // @Filename: mod1.js -// TODO: Test that this is not legal (or at least doesn't work) if module.exports is a primitive +/// module.exports = function () { } -module.exports.f = function () { } +/** @param {number} a */ +module.exports.f = function (a) { } // @Filename: a.js +/// var mod1 = require('./mod1') mod1() -mod1.f() +mod1.f() // error, not enough arguments diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts new file mode 100644 index 0000000000000..ae3d770b0a412 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment2.ts @@ -0,0 +1,16 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports = 1 +module.exports.f = function () { } + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1.toFixed(12) +mod1.f() // error, 'f' is not a property on 'number' diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts new file mode 100644 index 0000000000000..673858bb13e4f --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment3.ts @@ -0,0 +1,24 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports.bothBefore = 'string' +module.exports = { + justExport: 1, + bothBefore: 2, + bothAfter: 3, +} +module.exports.bothAfter = 'string' +module.exports.justProperty = 'string' + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1.justExport.toFixed() +mod1.bothBefore.toFixed() // error, 'toFixed' not on 'string | number' +mod1.bothAfter.toFixed() // error, 'toFixed' not on 'string | number' +mod1.justProperty.length diff --git a/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts new file mode 100644 index 0000000000000..90b54095cbf11 --- /dev/null +++ b/tests/cases/conformance/salsa/moduleExportWithExportPropertyAssignment4.ts @@ -0,0 +1,26 @@ +// @noEmit: true +// @allowJs: true +// @checkJs: true +// @Filename: requires.d.ts +declare var module: { exports: any }; +declare function require(name: string): any; +// @Filename: mod1.js +/// +module.exports.bothBefore = 'string' +A.justExport = 4 +A.bothBefore = 2 +A.bothAfter = 3 +module.exports = A +function A() { + this.p = 1 +} +module.exports.bothAfter = 'string' +module.exports.justProperty = 'string' + +// @Filename: a.js +/// +var mod1 = require('./mod1') +mod1.justExport.toFixed() +mod1.bothBefore.toFixed() // error +mod1.bothAfter.toFixed() +mod1.justProperty.length From c6a47d97fcc3bc0e6be6b0f17426e37d467524a4 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Fri, 6 Apr 2018 12:34:17 -0700 Subject: [PATCH 5/5] Check commonjs export= from resolveExternalModuleSymbol --- src/compiler/checker.ts | 45 +++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a33421c946dd5..f3d178e9478fa 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2096,15 +2096,9 @@ namespace ts { const moduleName = (namespace.valueDeclaration.initializer as CallExpression).arguments[0] as StringLiteral; const moduleSym = resolveExternalModuleName(moduleName, moduleName); if (moduleSym) { - if (moduleSym.exports.has(InternalSymbolName.ExportEquals as __String) && moduleSym.exports.size > 1) { - Debug.assert(!!(moduleSym.valueDeclaration as SourceFile).commonJsModuleIndicator); - namespace = mergeCommonJsExportEquals(moduleSym); - } - else { - const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); - if (resolvedModuleSymbol) { - namespace = resolvedModuleSymbol; - } + const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); + if (resolvedModuleSymbol) { + namespace = resolvedModuleSymbol; } } } @@ -2222,7 +2216,22 @@ namespace ts { // An external module with an 'export =' declaration resolves to the target of the 'export =' declaration, // and an external module with no 'export =' declaration resolves to the module itself. function resolveExternalModuleSymbol(moduleSymbol: Symbol, dontResolveAlias?: boolean): Symbol { - return moduleSymbol && getMergedSymbol(resolveSymbol(moduleSymbol.exports.get(InternalSymbolName.ExportEquals), dontResolveAlias)) || moduleSymbol; + return moduleSymbol && getMergedSymbol(resolveSymbol(getCommonJsExportEquals(moduleSymbol), dontResolveAlias)) || moduleSymbol; + } + + function getCommonJsExportEquals(moduleSymbol: Symbol): Symbol { + const exported = moduleSymbol.exports.get(InternalSymbolName.ExportEquals); + if (!exported || !exported.exports || moduleSymbol.exports.size === 1) { + return exported; + } + const merged = cloneSymbol(exported); + moduleSymbol.exports.forEach((s, name) => { + if (name === InternalSymbolName.ExportEquals) return; + if (!merged.exports.has(name)) { + merged.exports.set(name, s); + } + }); + return merged; } // An external module with an 'export =' declaration may be referenced as an ES6 module provided the 'export =' @@ -7025,10 +7034,6 @@ namespace ts { function resolveExternalModuleTypeByLiteral(name: StringLiteral) { const moduleSym = resolveExternalModuleName(name, name); if (moduleSym) { - if (moduleSym.exports.has(InternalSymbolName.ExportEquals as __String) && moduleSym.exports.size > 1) { - Debug.assert(!!(moduleSym.valueDeclaration as SourceFile).commonJsModuleIndicator); - return getTypeOfSymbol(mergeCommonJsExportEquals(moduleSym)); - } const resolvedModuleSymbol = resolveExternalModuleSymbol(moduleSym); if (resolvedModuleSymbol) { return getTypeOfSymbol(resolvedModuleSymbol); @@ -7038,18 +7043,6 @@ namespace ts { return anyType; } - function mergeCommonJsExportEquals(moduleSym: Symbol): Symbol { - const combined = cloneSymbol(moduleSym.exports.get(InternalSymbolName.ExportEquals)); - moduleSym.exports.forEach((s, name) => { - if (name === InternalSymbolName.ExportEquals) return; - if (!combined.exports.has(name)) { - combined.exports.set(name, s); - } - }); - return combined; - - } - function getThisTypeOfSignature(signature: Signature): Type | undefined { if (signature.thisParameter) { return getTypeOfSymbol(signature.thisParameter);