From fd020309cd50016dd45d5ee364918c4427c451dc Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Fri, 29 Aug 2025 10:28:54 +0100 Subject: [PATCH 1/4] fix(parser): panic when parsing JSDoc `@satisfies` with export assignments The parser was panicking when encountering JSDoc `@satisfies` tags on module.exports statements. The issue was that KindExportAssignment and KindJSExportAssignment were incorrectly grouped with nodes that have an Initializer() method, but they actually use Expression() instead. Also added missing support for KindCommonJSExport in the Initializer() and SetInitializer() methods. Reproduction: ```javascript /** * @satisfies {import('../types.js').SupportVersionTraceMap} */ module.exports = { zlib: zlib, 'node:zlib': { ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, }, }; ``` --- internal/ast/ast.go | 4 ++++ internal/parser/reparser.go | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/internal/ast/ast.go b/internal/ast/ast.go index 91fefba966..458cfa81b9 100644 --- a/internal/ast/ast.go +++ b/internal/ast/ast.go @@ -779,6 +779,8 @@ func (n *Node) Initializer() *Node { return n.AsForInOrOfStatement().Initializer case KindJsxAttribute: return n.AsJsxAttribute().Initializer + case KindCommonJSExport: + return n.AsCommonJSExport().Initializer } panic("Unhandled case in Node.Initializer") } @@ -806,6 +808,8 @@ func (m *mutableNode) SetInitializer(initializer *Node) { n.AsForInOrOfStatement().Initializer = initializer case KindJsxAttribute: n.AsJsxAttribute().Initializer = initializer + case KindCommonJSExport: + n.AsCommonJSExport().Initializer = initializer default: panic("Unhandled case in mutableNode.SetInitializer") } diff --git a/internal/parser/reparser.go b/internal/parser/reparser.go index 5b82837c3c..d33cb91024 100644 --- a/internal/parser/reparser.go +++ b/internal/parser/reparser.go @@ -357,7 +357,7 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node) } } case ast.KindVariableDeclaration, - ast.KindCommonJSExport, ast.KindExportAssignment, ast.KindJSExportAssignment, + ast.KindCommonJSExport, ast.KindPropertyDeclaration, ast.KindPropertyAssignment, ast.KindShorthandPropertyAssignment: if parent.Initializer() != nil && tag.AsJSDocSatisfiesTag().TypeExpression != nil { parent.AsMutable().SetInitializer(p.makeNewCast( @@ -366,7 +366,8 @@ func (p *Parser) reparseHosted(tag *ast.Node, parent *ast.Node, jsDoc *ast.Node) false /*isAssertion*/)) p.finishMutatedNode(parent) } - case ast.KindReturnStatement, ast.KindParenthesizedExpression: + case ast.KindReturnStatement, ast.KindParenthesizedExpression, + ast.KindExportAssignment, ast.KindJSExportAssignment: if parent.Expression() != nil && tag.AsJSDocSatisfiesTag().TypeExpression != nil { parent.AsMutable().SetExpression(p.makeNewCast( p.factory.DeepCloneReparse(tag.AsJSDocSatisfiesTag().TypeExpression.Type()), From 863b6b7f31a5d609d6623f0acb5ff9bb47a0522c Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Fri, 29 Aug 2025 18:58:34 +0100 Subject: [PATCH 2/4] test: add test case for JSDoc @satisfies with export assignments Adds a compiler test that verifies the parser doesn't panic when encountering JSDoc @satisfies tags on module.exports statements. This test would have failed before the fix in the previous commit. --- ...isfiesOnExportEqualsDeclaration.errors.txt | 29 ++++++++++ ...SatisfiesOnExportEqualsDeclaration.symbols | 46 ++++++++++++++++ ...icSatisfiesOnExportEqualsDeclaration.types | 55 +++++++++++++++++++ ...panicSatisfiesOnExportEqualsDeclaration.ts | 24 ++++++++ 4 files changed, 154 insertions(+) create mode 100644 testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt create mode 100644 testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols create mode 100644 testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types create mode 100644 testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt new file mode 100644 index 0000000000..979c02ad7d --- /dev/null +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt @@ -0,0 +1,29 @@ +panicSatisfiesOnExportEqualsDeclaration.js(2,14): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. +panicSatisfiesOnExportEqualsDeclaration.js(5,23): error TS2307: Cannot find module './types' or its corresponding type declarations. + + +==== types.d.ts (0 errors) ==== + export interface SupportVersionTraceMap { + zlib?: any; + 'node:zlib'?: any; + } + +==== panicSatisfiesOnExportEqualsDeclaration.js (2 errors) ==== + const zlib = {}; + const READ = Symbol('read'); + ~~~~~~ +!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. + + /** + * @satisfies {import('./types').SupportVersionTraceMap} + ~~~~~~~~~ +!!! error TS2307: Cannot find module './types' or its corresponding type declarations. + */ + module.exports = { + zlib: zlib, + 'node:zlib': { + ...zlib, + [READ]: { supported: ['14.13.1', '12.20.0'] }, + }, + }; + \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols new file mode 100644 index 0000000000..626f3814af --- /dev/null +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols @@ -0,0 +1,46 @@ +//// [tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts] //// + +=== types.d.ts === +export interface SupportVersionTraceMap { +>SupportVersionTraceMap : Symbol(SupportVersionTraceMap, Decl(types.d.ts, 0, 0)) + + zlib?: any; +>zlib : Symbol(SupportVersionTraceMap.zlib, Decl(types.d.ts, 0, 41)) + + 'node:zlib'?: any; +>'node:zlib' : Symbol(SupportVersionTraceMap["node:zlib"], Decl(types.d.ts, 1, 15)) +} + +=== panicSatisfiesOnExportEqualsDeclaration.js === +const zlib = {}; +>zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 5)) + +const READ = Symbol('read'); +>READ : Symbol(READ, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 5)) + +/** + * @satisfies {import('./types').SupportVersionTraceMap} + */ +module.exports = { +>module.exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 28)) +>module : Symbol(module.exports) +>exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 28)) + + zlib: zlib, +>zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 6, 18)) +>zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 5)) + + 'node:zlib': { +>'node:zlib' : Symbol('node:zlib', Decl(panicSatisfiesOnExportEqualsDeclaration.js, 7, 15)) + + ...zlib, +>zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 5)) + + [READ]: { supported: ['14.13.1', '12.20.0'] }, +>[READ] : Symbol([READ], Decl(panicSatisfiesOnExportEqualsDeclaration.js, 9, 16)) +>READ : Symbol(READ, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 5)) +>supported : Symbol(supported, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 10, 17)) + + }, +}; + diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types new file mode 100644 index 0000000000..584e5bc823 --- /dev/null +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts] //// + +=== types.d.ts === +export interface SupportVersionTraceMap { + zlib?: any; +>zlib : any + + 'node:zlib'?: any; +>'node:zlib' : any +} + +=== panicSatisfiesOnExportEqualsDeclaration.js === +const zlib = {}; +>zlib : {} +>{} : {} + +const READ = Symbol('read'); +>READ : any +>Symbol('read') : any +>Symbol : any +>'read' : "read" + +/** + * @satisfies {import('./types').SupportVersionTraceMap} + */ +module.exports = { +>module.exports = { zlib: zlib, 'node:zlib': { ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, },} : any +>module.exports : any +>module : { "export=": any; } +>exports : any +>{ zlib: zlib, 'node:zlib': { ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, },} : { zlib: {}; "node:zlib": {}; } + + zlib: zlib, +>zlib : {} +>zlib : {} + + 'node:zlib': { +>'node:zlib' : {} +>{ ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, } : {} + + ...zlib, +>zlib : {} + + [READ]: { supported: ['14.13.1', '12.20.0'] }, +>[READ] : { supported: string[]; } +>READ : any +>{ supported: ['14.13.1', '12.20.0'] } : { supported: string[]; } +>supported : string[] +>['14.13.1', '12.20.0'] : string[] +>'14.13.1' : "14.13.1" +>'12.20.0' : "12.20.0" + + }, +}; + diff --git a/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts b/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts new file mode 100644 index 0000000000..2549e9d003 --- /dev/null +++ b/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts @@ -0,0 +1,24 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true +// @module: commonjs +// @Filename: types.d.ts +export interface SupportVersionTraceMap { + zlib?: any; + 'node:zlib'?: any; +} + +// @Filename: panicSatisfiesOnExportEqualsDeclaration.js +const zlib = {}; +const READ = Symbol('read'); + +/** + * @satisfies {import('./types').SupportVersionTraceMap} + */ +module.exports = { + zlib: zlib, + 'node:zlib': { + ...zlib, + [READ]: { supported: ['14.13.1', '12.20.0'] }, + }, +}; From 0b3127a7639c35466e0ed7b22ce000ec9dcf52b8 Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Fri, 29 Aug 2025 19:50:33 +0100 Subject: [PATCH 3/4] make test case err free --- ...isfiesOnExportEqualsDeclaration.errors.txt | 23 ++-------- ...SatisfiesOnExportEqualsDeclaration.symbols | 39 ++-------------- ...icSatisfiesOnExportEqualsDeclaration.types | 46 ++----------------- ...panicSatisfiesOnExportEqualsDeclaration.ts | 19 ++------ 4 files changed, 15 insertions(+), 112 deletions(-) diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt index 979c02ad7d..a6a756d7ab 100644 --- a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt @@ -1,29 +1,14 @@ -panicSatisfiesOnExportEqualsDeclaration.js(2,14): error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. -panicSatisfiesOnExportEqualsDeclaration.js(5,23): error TS2307: Cannot find module './types' or its corresponding type declarations. +panicSatisfiesOnExportEqualsDeclaration.js(2,23): error TS2307: Cannot find module './types' or its corresponding type declarations. ==== types.d.ts (0 errors) ==== - export interface SupportVersionTraceMap { - zlib?: any; - 'node:zlib'?: any; - } - -==== panicSatisfiesOnExportEqualsDeclaration.js (2 errors) ==== - const zlib = {}; - const READ = Symbol('read'); - ~~~~~~ -!!! error TS2585: 'Symbol' only refers to a type, but is being used as a value here. Do you need to change your target library? Try changing the 'lib' compiler option to es2015 or later. + export interface SupportVersionTraceMap {} +==== panicSatisfiesOnExportEqualsDeclaration.js (1 errors) ==== /** * @satisfies {import('./types').SupportVersionTraceMap} ~~~~~~~~~ !!! error TS2307: Cannot find module './types' or its corresponding type declarations. */ - module.exports = { - zlib: zlib, - 'node:zlib': { - ...zlib, - [READ]: { supported: ['14.13.1', '12.20.0'] }, - }, - }; + module.exports = {}; \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols index 626f3814af..56992b3e15 100644 --- a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols @@ -1,46 +1,15 @@ //// [tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts] //// === types.d.ts === -export interface SupportVersionTraceMap { +export interface SupportVersionTraceMap {} >SupportVersionTraceMap : Symbol(SupportVersionTraceMap, Decl(types.d.ts, 0, 0)) - zlib?: any; ->zlib : Symbol(SupportVersionTraceMap.zlib, Decl(types.d.ts, 0, 41)) - - 'node:zlib'?: any; ->'node:zlib' : Symbol(SupportVersionTraceMap["node:zlib"], Decl(types.d.ts, 1, 15)) -} - === panicSatisfiesOnExportEqualsDeclaration.js === -const zlib = {}; ->zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 5)) - -const READ = Symbol('read'); ->READ : Symbol(READ, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 5)) - /** * @satisfies {import('./types').SupportVersionTraceMap} */ -module.exports = { ->module.exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 28)) +module.exports = {}; +>module.exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 0)) >module : Symbol(module.exports) ->exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 28)) - - zlib: zlib, ->zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 6, 18)) ->zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 5)) - - 'node:zlib': { ->'node:zlib' : Symbol('node:zlib', Decl(panicSatisfiesOnExportEqualsDeclaration.js, 7, 15)) - - ...zlib, ->zlib : Symbol(zlib, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 5)) - - [READ]: { supported: ['14.13.1', '12.20.0'] }, ->[READ] : Symbol([READ], Decl(panicSatisfiesOnExportEqualsDeclaration.js, 9, 16)) ->READ : Symbol(READ, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 1, 5)) ->supported : Symbol(supported, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 10, 17)) - - }, -}; +>exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 0)) diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types index 584e5bc823..23a1eec90c 100644 --- a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types @@ -1,55 +1,17 @@ //// [tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts] //// === types.d.ts === -export interface SupportVersionTraceMap { - zlib?: any; ->zlib : any - 'node:zlib'?: any; ->'node:zlib' : any -} +export interface SupportVersionTraceMap {} === panicSatisfiesOnExportEqualsDeclaration.js === -const zlib = {}; ->zlib : {} ->{} : {} - -const READ = Symbol('read'); ->READ : any ->Symbol('read') : any ->Symbol : any ->'read' : "read" - /** * @satisfies {import('./types').SupportVersionTraceMap} */ -module.exports = { ->module.exports = { zlib: zlib, 'node:zlib': { ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, },} : any +module.exports = {}; +>module.exports = {} : any >module.exports : any >module : { "export=": any; } >exports : any ->{ zlib: zlib, 'node:zlib': { ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, },} : { zlib: {}; "node:zlib": {}; } - - zlib: zlib, ->zlib : {} ->zlib : {} - - 'node:zlib': { ->'node:zlib' : {} ->{ ...zlib, [READ]: { supported: ['14.13.1', '12.20.0'] }, } : {} - - ...zlib, ->zlib : {} - - [READ]: { supported: ['14.13.1', '12.20.0'] }, ->[READ] : { supported: string[]; } ->READ : any ->{ supported: ['14.13.1', '12.20.0'] } : { supported: string[]; } ->supported : string[] ->['14.13.1', '12.20.0'] : string[] ->'14.13.1' : "14.13.1" ->'12.20.0' : "12.20.0" - - }, -}; +>{} : {} diff --git a/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts b/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts index 2549e9d003..b07c619beb 100644 --- a/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts +++ b/testdata/tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts @@ -2,23 +2,10 @@ // @checkJs: true // @noEmit: true // @module: commonjs -// @Filename: types.d.ts -export interface SupportVersionTraceMap { - zlib?: any; - 'node:zlib'?: any; -} - +// @lib: esnext,dom,dom.iterable // @Filename: panicSatisfiesOnExportEqualsDeclaration.js -const zlib = {}; -const READ = Symbol('read'); /** - * @satisfies {import('./types').SupportVersionTraceMap} + * @satisfies {Record} */ -module.exports = { - zlib: zlib, - 'node:zlib': { - ...zlib, - [READ]: { supported: ['14.13.1', '12.20.0'] }, - }, -}; +module.exports = {}; From 53e0b2bf936f6dab38435e21bc80f01ffc965caa Mon Sep 17 00:00:00 2001 From: Cameron Clark Date: Fri, 29 Aug 2025 19:54:21 +0100 Subject: [PATCH 4/4] update baseline --- ...icSatisfiesOnExportEqualsDeclaration.errors.txt | 14 -------------- ...panicSatisfiesOnExportEqualsDeclaration.symbols | 6 +----- .../panicSatisfiesOnExportEqualsDeclaration.types | 14 +++++--------- 3 files changed, 6 insertions(+), 28 deletions(-) delete mode 100644 testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt deleted file mode 100644 index a6a756d7ab..0000000000 --- a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.errors.txt +++ /dev/null @@ -1,14 +0,0 @@ -panicSatisfiesOnExportEqualsDeclaration.js(2,23): error TS2307: Cannot find module './types' or its corresponding type declarations. - - -==== types.d.ts (0 errors) ==== - export interface SupportVersionTraceMap {} - -==== panicSatisfiesOnExportEqualsDeclaration.js (1 errors) ==== - /** - * @satisfies {import('./types').SupportVersionTraceMap} - ~~~~~~~~~ -!!! error TS2307: Cannot find module './types' or its corresponding type declarations. - */ - module.exports = {}; - \ No newline at end of file diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols index 56992b3e15..8ebafccf77 100644 --- a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.symbols @@ -1,12 +1,8 @@ //// [tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts] //// -=== types.d.ts === -export interface SupportVersionTraceMap {} ->SupportVersionTraceMap : Symbol(SupportVersionTraceMap, Decl(types.d.ts, 0, 0)) - === panicSatisfiesOnExportEqualsDeclaration.js === /** - * @satisfies {import('./types').SupportVersionTraceMap} + * @satisfies {Record} */ module.exports = {}; >module.exports : Symbol(export=, Decl(panicSatisfiesOnExportEqualsDeclaration.js, 0, 0)) diff --git a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types index 23a1eec90c..ae32b132ed 100644 --- a/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types +++ b/testdata/baselines/reference/compiler/panicSatisfiesOnExportEqualsDeclaration.types @@ -1,17 +1,13 @@ //// [tests/cases/compiler/panicSatisfiesOnExportEqualsDeclaration.ts] //// -=== types.d.ts === - -export interface SupportVersionTraceMap {} - === panicSatisfiesOnExportEqualsDeclaration.js === /** - * @satisfies {import('./types').SupportVersionTraceMap} + * @satisfies {Record} */ module.exports = {}; ->module.exports = {} : any ->module.exports : any ->module : { "export=": any; } ->exports : any +>module.exports = {} : {} +>module.exports : {} +>module : { "export=": {}; } +>exports : {} >{} : {}